From 03863258ea87698ea577e4e5856bc7e70f50d2dd Mon Sep 17 00:00:00 2001 From: Frodo Baggins Date: Thu, 31 Oct 2024 17:58:48 -0700 Subject: [PATCH] add stuff for compiler user tracking --- CMakeLists.txt | 5 + boost.png | Bin 0 -> 6308 bytes boost/container/list.hpp | 1511 ++++++++ boost/container/slist.hpp | 1724 +++++++++ boost/container_hash/detail/hash_integral.hpp | 146 + boost/container_hash/detail/hash_mix.hpp | 113 + boost/container_hash/detail/hash_range.hpp | 408 +++ .../container_hash/detail/hash_tuple_like.hpp | 62 + boost/container_hash/detail/mulx.hpp | 79 + boost/container_hash/hash.hpp | 576 +++ boost/container_hash/hash_fwd.hpp | 37 + boost/container_hash/is_contiguous_range.hpp | 98 + boost/container_hash/is_described_class.hpp | 37 + boost/container_hash/is_range.hpp | 37 + boost/container_hash/is_tuple_like.hpp | 36 + boost/container_hash/is_unordered_range.hpp | 38 + boost/core/detail/is_same.hpp | 39 + boost/core/explicit_operator_bool.hpp | 163 + boost/core/invoke_swap.hpp | 93 + boost/core/lightweight_test_trait.hpp | 91 + boost/core/ref.hpp | 345 ++ boost/core/snprintf.hpp | 173 + boost/core/type_name.hpp | 1181 ++++++ boost/cregex.hpp | 43 + boost/describe/bases.hpp | 50 + boost/describe/detail/config.hpp | 40 + boost/describe/detail/cx_streq.hpp | 30 + boost/describe/detail/void_t.hpp | 32 + boost/describe/members.hpp | 161 + boost/describe/modifiers.hpp | 33 + boost/integer.hpp | 262 ++ boost/integer_traits.hpp | 256 ++ boost/io/detail/buffer_fill.hpp | 39 + boost/io/detail/ostream_guard.hpp | 45 + boost/io/ostream_put.hpp | 50 + boost/iterator/counting_iterator.hpp | 254 ++ .../iterator/detail/any_conversion_eater.hpp | 21 + boost/iterator/detail/minimum_category.hpp | 19 + boost/iterator/filter_iterator.hpp | 146 + boost/iterator/function_input_iterator.hpp | 180 + boost/iterator/function_output_iterator.hpp | 95 + boost/iterator/indirect_iterator.hpp | 145 + boost/iterator/is_lvalue_iterator.hpp | 164 + boost/iterator/is_readable_iterator.hpp | 119 + boost/iterator/iterator_archetypes.hpp | 509 +++ boost/iterator/minimum_category.hpp | 95 + boost/iterator/new_iterator_tests.hpp | 265 ++ boost/iterator/permutation_iterator.hpp | 76 + boost/iterator/transform_iterator.hpp | 179 + boost/iterator/zip_iterator.hpp | 367 ++ boost/mp11/algorithm.hpp | 1327 +++++++ boost/mp11/bind.hpp | 111 + boost/mp11/detail/config.hpp | 149 + boost/mp11/detail/mp_append.hpp | 321 ++ boost/mp11/detail/mp_copy_if.hpp | 48 + boost/mp11/detail/mp_count.hpp | 147 + boost/mp11/detail/mp_defer.hpp | 119 + boost/mp11/detail/mp_fold.hpp | 164 + boost/mp11/detail/mp_front.hpp | 50 + boost/mp11/detail/mp_is_list.hpp | 39 + boost/mp11/detail/mp_is_value_list.hpp | 41 + boost/mp11/detail/mp_list.hpp | 24 + boost/mp11/detail/mp_list_v.hpp | 27 + boost/mp11/detail/mp_map_find.hpp | 87 + boost/mp11/detail/mp_min_element.hpp | 51 + boost/mp11/detail/mp_plus.hpp | 84 + boost/mp11/detail/mp_remove_if.hpp | 48 + boost/mp11/detail/mp_rename.hpp | 54 + boost/mp11/detail/mp_value.hpp | 25 + boost/mp11/detail/mp_void.hpp | 32 + boost/mp11/detail/mp_with_index.hpp | 385 ++ boost/mp11/function.hpp | 222 ++ boost/mp11/integer_sequence.hpp | 112 + boost/mp11/integral.hpp | 42 + boost/mp11/list.hpp | 472 +++ boost/mp11/set.hpp | 188 + boost/mp11/utility.hpp | 169 + boost/mp11/version.hpp | 16 + boost/mpl/O1_size.hpp | 40 + boost/mpl/O1_size_fwd.hpp | 24 + boost/mpl/advance.hpp | 76 + boost/mpl/advance_fwd.hpp | 28 + boost/mpl/at.hpp | 52 + boost/mpl/at_fwd.hpp | 24 + boost/mpl/aux_/O1_size_impl.hpp | 87 + boost/mpl/aux_/advance_backward.hpp | 128 + boost/mpl/aux_/advance_forward.hpp | 127 + boost/mpl/aux_/at_impl.hpp | 45 + boost/mpl/aux_/begin_end_impl.hpp | 101 + boost/mpl/aux_/clear_impl.hpp | 35 + boost/mpl/aux_/config/typeof.hpp | 38 + boost/mpl/aux_/fold_impl.hpp | 43 + boost/mpl/aux_/fold_impl_body.hpp | 365 ++ boost/mpl/aux_/has_begin.hpp | 23 + boost/mpl/aux_/has_size.hpp | 23 + boost/mpl/aux_/inserter_algorithm.hpp | 159 + boost/mpl/aux_/iter_fold_impl.hpp | 42 + boost/mpl/aux_/msvc_type.hpp | 62 + boost/mpl/aux_/push_back_impl.hpp | 70 + boost/mpl/aux_/push_front_impl.hpp | 71 + boost/mpl/aux_/reverse_fold_impl.hpp | 44 + boost/mpl/aux_/reverse_fold_impl_body.hpp | 412 +++ boost/mpl/aux_/sequence_wrapper.hpp | 292 ++ boost/mpl/aux_/traits_lambda_spec.hpp | 63 + boost/mpl/back_fwd.hpp | 24 + boost/mpl/back_inserter.hpp | 34 + boost/mpl/begin_end.hpp | 57 + boost/mpl/begin_end_fwd.hpp | 27 + boost/mpl/bitand.hpp | 45 + boost/mpl/clear.hpp | 39 + boost/mpl/clear_fwd.hpp | 24 + boost/mpl/deref.hpp | 41 + boost/mpl/distance.hpp | 78 + boost/mpl/distance_fwd.hpp | 28 + boost/mpl/empty_fwd.hpp | 24 + boost/mpl/fold.hpp | 48 + boost/mpl/front_fwd.hpp | 24 + boost/mpl/front_inserter.hpp | 33 + boost/mpl/inserter.hpp | 32 + boost/mpl/is_sequence.hpp | 112 + boost/mpl/iter_fold.hpp | 49 + boost/mpl/iterator_category.hpp | 35 + boost/mpl/iterator_range.hpp | 42 + boost/mpl/iterator_tags.hpp | 27 + boost/mpl/limits/unrolling.hpp | 21 + boost/mpl/limits/vector.hpp | 21 + boost/mpl/long.hpp | 22 + boost/mpl/long_fwd.hpp | 27 + boost/mpl/min_max.hpp | 46 + boost/mpl/minus.hpp | 21 + boost/mpl/negate.hpp | 81 + boost/mpl/pair.hpp | 70 + boost/mpl/pair_view.hpp | 169 + boost/mpl/plus.hpp | 21 + boost/mpl/pop_back_fwd.hpp | 24 + boost/mpl/pop_front_fwd.hpp | 24 + boost/mpl/prior.hpp | 19 + boost/mpl/push_back.hpp | 53 + boost/mpl/push_back_fwd.hpp | 24 + boost/mpl/push_front.hpp | 52 + boost/mpl/push_front_fwd.hpp | 24 + boost/mpl/reverse_fold.hpp | 50 + boost/mpl/sequence_tag.hpp | 124 + boost/mpl/sequence_tag_fwd.hpp | 26 + boost/mpl/size_fwd.hpp | 24 + boost/mpl/transform.hpp | 145 + boost/mpl/vector.hpp | 57 + boost/mpl/vector/aux_/O1_size.hpp | 56 + boost/mpl/vector/aux_/at.hpp | 116 + boost/mpl/vector/aux_/back.hpp | 59 + boost/mpl/vector/aux_/begin_end.hpp | 49 + boost/mpl/vector/aux_/clear.hpp | 55 + boost/mpl/vector/aux_/empty.hpp | 68 + boost/mpl/vector/aux_/front.hpp | 56 + .../mpl/vector/aux_/include_preprocessed.hpp | 55 + boost/mpl/vector/aux_/item.hpp | 103 + boost/mpl/vector/aux_/iterator.hpp | 130 + boost/mpl/vector/aux_/numbered.hpp | 218 ++ boost/mpl/vector/aux_/numbered_c.hpp | 77 + boost/mpl/vector/aux_/pop_back.hpp | 40 + boost/mpl/vector/aux_/pop_front.hpp | 40 + .../aux_/preprocessed/no_ctps/vector10.hpp | 1528 ++++++++ .../aux_/preprocessed/no_ctps/vector10_c.hpp | 149 + .../aux_/preprocessed/no_ctps/vector20.hpp | 1804 ++++++++++ .../aux_/preprocessed/no_ctps/vector20_c.hpp | 195 + .../aux_/preprocessed/no_ctps/vector30.hpp | 2124 +++++++++++ .../aux_/preprocessed/no_ctps/vector30_c.hpp | 238 ++ .../aux_/preprocessed/no_ctps/vector40.hpp | 2444 +++++++++++++ .../aux_/preprocessed/no_ctps/vector40_c.hpp | 281 ++ .../aux_/preprocessed/no_ctps/vector50.hpp | 2764 ++++++++++++++ .../aux_/preprocessed/no_ctps/vector50_c.hpp | 325 ++ .../aux_/preprocessed/plain/vector10.hpp | 829 +++++ .../aux_/preprocessed/plain/vector10_c.hpp | 149 + .../aux_/preprocessed/plain/vector20.hpp | 1144 ++++++ .../aux_/preprocessed/plain/vector20_c.hpp | 195 + .../aux_/preprocessed/plain/vector30.hpp | 1464 ++++++++ .../aux_/preprocessed/plain/vector30_c.hpp | 238 ++ .../aux_/preprocessed/plain/vector40.hpp | 1784 +++++++++ .../aux_/preprocessed/plain/vector40_c.hpp | 281 ++ .../aux_/preprocessed/plain/vector50.hpp | 2104 +++++++++++ .../aux_/preprocessed/plain/vector50_c.hpp | 325 ++ .../preprocessed/typeof_based/vector10.hpp | 139 + .../preprocessed/typeof_based/vector10_c.hpp | 154 + .../preprocessed/typeof_based/vector20.hpp | 159 + .../preprocessed/typeof_based/vector20_c.hpp | 163 + .../preprocessed/typeof_based/vector30.hpp | 179 + .../preprocessed/typeof_based/vector30_c.hpp | 173 + .../preprocessed/typeof_based/vector40.hpp | 199 ++ .../preprocessed/typeof_based/vector40_c.hpp | 183 + .../preprocessed/typeof_based/vector50.hpp | 219 ++ .../preprocessed/typeof_based/vector50_c.hpp | 193 + boost/mpl/vector/aux_/push_back.hpp | 40 + boost/mpl/vector/aux_/push_front.hpp | 40 + boost/mpl/vector/aux_/size.hpp | 49 + boost/mpl/vector/aux_/tag.hpp | 32 + boost/mpl/vector/aux_/vector0.hpp | 52 + boost/mpl/vector/vector0.hpp | 34 + boost/mpl/vector/vector0_c.hpp | 31 + boost/mpl/vector/vector10.hpp | 45 + boost/mpl/vector/vector10_c.hpp | 46 + boost/mpl/vector/vector20.hpp | 45 + boost/mpl/vector/vector20_c.hpp | 46 + boost/mpl/vector/vector30.hpp | 45 + boost/mpl/vector/vector30_c.hpp | 47 + boost/mpl/vector/vector40.hpp | 45 + boost/mpl/vector/vector40_c.hpp | 46 + boost/mpl/vector/vector50.hpp | 45 + boost/mpl/vector/vector50_c.hpp | 46 + boost/predef.h | 24 + boost/predef/architecture.h | 35 + boost/predef/architecture/alpha.h | 65 + boost/predef/architecture/arm.h | 144 + boost/predef/architecture/blackfin.h | 52 + boost/predef/architecture/convex.h | 71 + boost/predef/architecture/e2k.h | 54 + boost/predef/architecture/ia64.h | 55 + boost/predef/architecture/loongarch.h | 41 + boost/predef/architecture/m68k.h | 88 + boost/predef/architecture/mips.h | 84 + boost/predef/architecture/parisc.h | 70 + boost/predef/architecture/ppc.h | 124 + boost/predef/architecture/ptx.h | 50 + boost/predef/architecture/pyramid.h | 48 + boost/predef/architecture/riscv.h | 48 + boost/predef/architecture/rs6k.h | 67 + boost/predef/architecture/sparc.h | 67 + boost/predef/architecture/superh.h | 81 + boost/predef/architecture/sys370.h | 49 + boost/predef/architecture/sys390.h | 49 + boost/predef/architecture/x86.h | 38 + boost/predef/architecture/x86/32.h | 93 + boost/predef/architecture/x86/64.h | 56 + boost/predef/architecture/z.h | 48 + boost/predef/compiler.h | 44 + boost/predef/compiler/borland.h | 64 + boost/predef/compiler/clang.h | 57 + boost/predef/compiler/comeau.h | 62 + boost/predef/compiler/compaq.h | 67 + boost/predef/compiler/diab.h | 57 + boost/predef/compiler/digitalmars.h | 57 + boost/predef/compiler/dignus.h | 57 + boost/predef/compiler/edg.h | 57 + boost/predef/compiler/ekopath.h | 58 + boost/predef/compiler/gcc.h | 69 + boost/predef/compiler/gcc_xml.h | 54 + boost/predef/compiler/greenhills.h | 67 + boost/predef/compiler/hp_acc.h | 62 + boost/predef/compiler/iar.h | 57 + boost/predef/compiler/ibm.h | 73 + boost/predef/compiler/intel.h | 80 + boost/predef/compiler/kai.h | 57 + boost/predef/compiler/llvm.h | 58 + boost/predef/compiler/metaware.h | 54 + boost/predef/compiler/metrowerks.h | 78 + boost/predef/compiler/microtec.h | 54 + boost/predef/compiler/mpw.h | 64 + boost/predef/compiler/nvcc.h | 74 + boost/predef/compiler/palm.h | 57 + boost/predef/compiler/pgi.h | 61 + boost/predef/compiler/sgi_mipspro.h | 67 + boost/predef/compiler/sunpro.h | 77 + boost/predef/compiler/tendra.h | 54 + boost/predef/compiler/visualc.h | 106 + boost/predef/compiler/watcom.h | 57 + boost/predef/detail/_cassert.h | 17 + boost/predef/detail/_exception.h | 15 + boost/predef/detail/comp_detected.h | 10 + boost/predef/hardware.h | 16 + boost/predef/hardware/simd.h | 168 + boost/predef/hardware/simd/arm.h | 61 + boost/predef/hardware/simd/arm/versions.h | 38 + boost/predef/hardware/simd/ppc.h | 71 + boost/predef/hardware/simd/ppc/versions.h | 57 + boost/predef/hardware/simd/x86.h | 125 + boost/predef/hardware/simd/x86/versions.h | 135 + boost/predef/hardware/simd/x86_amd.h | 89 + boost/predef/hardware/simd/x86_amd/versions.h | 56 + boost/predef/language.h | 18 + boost/predef/language/cuda.h | 53 + boost/predef/language/objc.h | 43 + boost/predef/language/stdc.h | 54 + boost/predef/language/stdcpp.h | 128 + boost/predef/library.h | 16 + boost/predef/library/c.h | 21 + boost/predef/library/c/_prefix.h | 13 + boost/predef/library/c/cloudabi.h | 54 + boost/predef/library/c/gnu.h | 62 + boost/predef/library/c/uc.h | 48 + boost/predef/library/c/vms.h | 48 + boost/predef/library/c/zos.h | 57 + boost/predef/library/std.h | 26 + boost/predef/library/std/_prefix.h | 23 + boost/predef/library/std/cxx.h | 47 + boost/predef/library/std/dinkumware.h | 53 + boost/predef/library/std/libcomo.h | 48 + boost/predef/library/std/modena.h | 46 + boost/predef/library/std/msl.h | 54 + boost/predef/library/std/msvc.h | 53 + boost/predef/library/std/roguewave.h | 57 + boost/predef/library/std/sgi.h | 52 + boost/predef/library/std/stdcpp3.h | 54 + boost/predef/library/std/stlport.h | 60 + boost/predef/library/std/vacpp.h | 45 + boost/predef/os.h | 32 + boost/predef/os/aix.h | 67 + boost/predef/os/amigaos.h | 47 + boost/predef/os/beos.h | 46 + boost/predef/os/bsd.h | 102 + boost/predef/os/bsd/bsdi.h | 50 + boost/predef/os/bsd/dragonfly.h | 52 + boost/predef/os/bsd/free.h | 69 + boost/predef/os/bsd/net.h | 86 + boost/predef/os/bsd/open.h | 253 ++ boost/predef/os/cygwin.h | 51 + boost/predef/os/haiku.h | 47 + boost/predef/os/hpux.h | 48 + boost/predef/os/irix.h | 47 + boost/predef/os/linux.h | 50 + boost/predef/os/macos.h | 66 + boost/predef/os/os400.h | 46 + boost/predef/os/qnxnto.h | 60 + boost/predef/os/solaris.h | 47 + boost/predef/os/unix.h | 78 + boost/predef/os/vms.h | 53 + boost/predef/other.h | 17 + boost/predef/other/endian.h | 202 ++ boost/predef/other/wordsize.h | 73 + boost/predef/other/workaround.h | 95 + boost/predef/version.h | 15 + boost/preprocessor/arithmetic/div.hpp | 75 + boost/preprocessor/arithmetic/mul.hpp | 112 + boost/preprocessor/detail/is_unary.hpp | 30 + boost/preprocessor/enum.hpp | 17 + boost/preprocessor/enum_params.hpp | 17 + .../enum_params_with_a_default.hpp | 17 + boost/preprocessor/facilities/intercept.hpp | 306 ++ .../facilities/limits/intercept_1024.hpp | 530 +++ .../facilities/limits/intercept_256.hpp | 273 ++ .../facilities/limits/intercept_512.hpp | 274 ++ boost/preprocessor/list/for_each.hpp | 49 + boost/preprocessor/punctuation/paren.hpp | 23 + boost/preprocessor/repetition/enum.hpp | 66 + .../repetition/enum_params_with_a_default.hpp | 25 + boost/ref.hpp | 17 + boost/regex.hpp | 41 + boost/regex/config.hpp | 480 +++ boost/regex/config/borland.hpp | 72 + boost/regex/config/cwchar.hpp | 207 ++ boost/regex/pattern_except.hpp | 32 + boost/regex/pending/static_mutex.hpp | 182 + boost/regex/regex_traits.hpp | 39 + boost/regex/user.hpp | 95 + boost/regex/v4/basic_regex.hpp | 797 +++++ boost/regex/v4/basic_regex_creator.hpp | 1598 +++++++++ boost/regex/v4/basic_regex_parser.hpp | 3174 +++++++++++++++++ boost/regex/v4/c_regex_traits.hpp | 511 +++ boost/regex/v4/char_regex_traits.hpp | 81 + boost/regex/v4/cpp_regex_traits.hpp | 1237 +++++++ boost/regex/v4/cregex.hpp | 213 ++ boost/regex/v4/error_type.hpp | 59 + boost/regex/v4/indexed_bit_flag.hpp | 54 + boost/regex/v4/iterator_category.hpp | 91 + boost/regex/v4/iterator_traits.hpp | 135 + boost/regex/v4/match_flags.hpp | 161 + boost/regex/v4/match_results.hpp | 716 ++++ boost/regex/v4/mem_block_cache.hpp | 183 + boost/regex/v4/object_cache.hpp | 171 + boost/regex/v4/pattern_except.hpp | 128 + boost/regex/v4/perl_matcher.hpp | 645 ++++ boost/regex/v4/perl_matcher_common.hpp | 1030 ++++++ boost/regex/v4/perl_matcher_non_recursive.hpp | 1947 ++++++++++ boost/regex/v4/perl_matcher_recursive.hpp | 1131 ++++++ boost/regex/v4/primary_transform.hpp | 146 + boost/regex/v4/protected_call.hpp | 83 + boost/regex/v4/regbase.hpp | 180 + boost/regex/v4/regex.hpp | 166 + boost/regex/v4/regex_format.hpp | 1158 ++++++ boost/regex/v4/regex_fwd.hpp | 73 + boost/regex/v4/regex_grep.hpp | 155 + boost/regex/v4/regex_iterator.hpp | 195 + boost/regex/v4/regex_match.hpp | 382 ++ boost/regex/v4/regex_merge.hpp | 93 + boost/regex/v4/regex_raw_buffer.hpp | 241 ++ boost/regex/v4/regex_replace.hpp | 99 + boost/regex/v4/regex_search.hpp | 217 ++ boost/regex/v4/regex_split.hpp | 174 + boost/regex/v4/regex_token_iterator.hpp | 327 ++ boost/regex/v4/regex_traits.hpp | 189 + boost/regex/v4/regex_traits_defaults.hpp | 997 ++++++ boost/regex/v4/regex_workaround.hpp | 237 ++ boost/regex/v4/states.hpp | 321 ++ boost/regex/v4/sub_match.hpp | 516 +++ boost/regex/v4/syntax_type.hpp | 105 + boost/regex/v4/w32_regex_traits.hpp | 1229 +++++++ boost/regex/v5/basic_regex.hpp | 734 ++++ boost/regex/v5/basic_regex_creator.hpp | 1576 ++++++++ boost/regex/v5/basic_regex_parser.hpp | 3130 ++++++++++++++++ boost/regex/v5/c_regex_traits.hpp | 474 +++ boost/regex/v5/char_regex_traits.hpp | 59 + boost/regex/v5/cpp_regex_traits.hpp | 1040 ++++++ boost/regex/v5/cregex.hpp | 195 + boost/regex/v5/error_type.hpp | 59 + boost/regex/v5/iterator_category.hpp | 84 + boost/regex/v5/match_flags.hpp | 156 + boost/regex/v5/match_results.hpp | 667 ++++ boost/regex/v5/mem_block_cache.hpp | 173 + boost/regex/v5/object_cache.hpp | 160 + boost/regex/v5/pattern_except.hpp | 106 + boost/regex/v5/perl_matcher.hpp | 576 +++ boost/regex/v5/perl_matcher_common.hpp | 921 +++++ boost/regex/v5/perl_matcher_non_recursive.hpp | 1874 ++++++++++ boost/regex/v5/primary_transform.hpp | 120 + boost/regex/v5/regbase.hpp | 158 + boost/regex/v5/regex.hpp | 106 + boost/regex/v5/regex_format.hpp | 1124 ++++++ boost/regex/v5/regex_fwd.hpp | 73 + boost/regex/v5/regex_grep.hpp | 98 + boost/regex/v5/regex_iterator.hpp | 173 + boost/regex/v5/regex_match.hpp | 92 + boost/regex/v5/regex_merge.hpp | 71 + boost/regex/v5/regex_raw_buffer.hpp | 213 ++ boost/regex/v5/regex_replace.hpp | 77 + boost/regex/v5/regex_search.hpp | 103 + boost/regex/v5/regex_split.hpp | 152 + boost/regex/v5/regex_token_iterator.hpp | 255 ++ boost/regex/v5/regex_traits.hpp | 130 + boost/regex/v5/regex_traits_defaults.hpp | 996 ++++++ boost/regex/v5/regex_workaround.hpp | 159 + boost/regex/v5/states.hpp | 299 ++ boost/regex/v5/sub_match.hpp | 382 ++ boost/regex/v5/syntax_type.hpp | 105 + boost/regex/v5/w32_regex_traits.hpp | 1311 +++++++ boost/regex_fwd.hpp | 37 + boost/scoped_array.hpp | 15 + boost/scoped_ptr.hpp | 15 + boost/smart_ptr/scoped_array.hpp | 133 + boost/smart_ptr/scoped_ptr.hpp | 168 + boost/type_traits/cv_traits.hpp | 24 + boost/type_traits/object_traits.hpp | 33 + boost/type_traits/same_traits.hpp | 15 + build.cmd | 7 + build.sh | 7 + doc/src/boostbook.css | 789 ++++ doc/src/images/caution.png | Bin 0 -> 1250 bytes doc/src/images/home.png | Bin 0 -> 358 bytes doc/src/images/next.png | Bin 0 -> 336 bytes doc/src/images/note.png | Bin 0 -> 490 bytes doc/src/images/prev.png | Bin 0 -> 334 bytes doc/src/images/up.png | Bin 0 -> 370 bytes doc/src/images/warning.png | Bin 0 -> 1241 bytes libs/align/.github/workflows/ci.yml | 185 + libs/align/.travis.yml | 297 ++ libs/config/test/config_info.cpp | 1567 ++++++++ libs/iterator/.gitattributes | 96 + libs/iterator/.github/workflows/ci.yml | 508 +++ libs/iterator/CMakeLists.txt | 30 + libs/iterator/README.md | 27 + libs/iterator/appveyor.yml | 102 + libs/iterator/doc/BidirectionalTraversal.html | 76 + libs/iterator/doc/BidirectionalTraversal.rst | 41 + libs/iterator/doc/ForwardTraversal.html | 67 + libs/iterator/doc/ForwardTraversal.rst | 31 + libs/iterator/doc/GNUmakefile | 15 + libs/iterator/doc/IncrementableIterator.html | 66 + libs/iterator/doc/IncrementableIterator.rst | 32 + libs/iterator/doc/InteroperableIterator.rst | 61 + libs/iterator/doc/Jamfile.v2 | 27 + libs/iterator/doc/LvalueIterator.html | 56 + libs/iterator/doc/LvalueIterator.rst | 25 + libs/iterator/doc/RandomAccessTraversal.html | 134 + libs/iterator/doc/RandomAccessTraversal.rst | 67 + libs/iterator/doc/ReadableIterator.html | 64 + libs/iterator/doc/ReadableIterator.rst | 26 + libs/iterator/doc/SinglePassIterator.html | 68 + libs/iterator/doc/SinglePassIterator.rst | 32 + libs/iterator/doc/SwappableIterator.html | 54 + libs/iterator/doc/SwappableIterator.rst | 23 + libs/iterator/doc/WritableIterator.html | 52 + libs/iterator/doc/WritableIterator.rst | 21 + libs/iterator/doc/access.png | Bin 0 -> 11127 bytes libs/iterator/doc/access2old.png | Bin 0 -> 42175 bytes libs/iterator/doc/advance.rst | 75 + libs/iterator/doc/counting_iterator.html | 301 ++ libs/iterator/doc/counting_iterator.pdf | Bin 0 -> 72583 bytes libs/iterator/doc/counting_iterator.rst | 43 + .../doc/counting_iterator_abstract.rst | 8 + libs/iterator/doc/counting_iterator_eg.rst | 43 + libs/iterator/doc/counting_iterator_ref.rst | 149 + libs/iterator/doc/default.css | 226 ++ libs/iterator/doc/distance.rst | 72 + libs/iterator/doc/docutils.sty | 54 + libs/iterator/doc/facade-and-adaptor.html | 2716 ++++++++++++++ libs/iterator/doc/facade-and-adaptor.pdf | Bin 0 -> 226024 bytes libs/iterator/doc/facade-and-adaptor.rst | 438 +++ .../iterator/doc/facade_iterator_category.rst | 53 + libs/iterator/doc/filter_iterator.html | 413 +++ libs/iterator/doc/filter_iterator.pdf | Bin 0 -> 69532 bytes libs/iterator/doc/filter_iterator.rst | 33 + .../iterator/doc/filter_iterator_abstract.rst | 15 + libs/iterator/doc/filter_iterator_eg.rst | 72 + libs/iterator/doc/filter_iterator_ref.rst | 177 + .../doc/func_output_iter_abstract.rst | 12 + libs/iterator/doc/func_output_iter_ref.rst | 73 + .../iterator/doc/function_input_iterator.html | 142 + libs/iterator/doc/function_input_iterator.rst | 132 + .../doc/function_output_iterator.html | 191 + .../iterator/doc/function_output_iterator.pdf | Bin 0 -> 57133 bytes .../iterator/doc/function_output_iterator.rst | 28 + .../doc/function_output_iterator_eg.rst | 39 + libs/iterator/doc/generate.py | 32 + libs/iterator/doc/generator_iterator.htm | 163 + libs/iterator/doc/index.html | 252 ++ libs/iterator/doc/index.rst | 355 ++ libs/iterator/doc/indirect_iterator.html | 345 ++ libs/iterator/doc/indirect_iterator.pdf | Bin 0 -> 75031 bytes libs/iterator/doc/indirect_iterator.rst | 34 + .../doc/indirect_iterator_abstract.rst | 15 + libs/iterator/doc/indirect_iterator_eg.rst | 73 + libs/iterator/doc/indirect_iterator_ref.rst | 181 + libs/iterator/doc/indirect_reference_ref.rst | 29 + .../doc/interoperability-revisited.rst | 238 ++ libs/iterator/doc/issues.rst | 152 + libs/iterator/doc/iterator_adaptor.html | 461 +++ libs/iterator/doc/iterator_adaptor.pdf | Bin 0 -> 100117 bytes libs/iterator/doc/iterator_adaptor.rst | 41 + .../doc/iterator_adaptor_abstract.rst | 19 + libs/iterator/doc/iterator_adaptor_body.rst | 43 + libs/iterator/doc/iterator_adaptor_ref.rst | 182 + .../doc/iterator_adaptor_tutorial.rst | 135 + libs/iterator/doc/iterator_archetypes.html | 224 ++ libs/iterator/doc/iterator_archetypes.pdf | Bin 0 -> 61213 bytes libs/iterator/doc/iterator_archetypes.rst | 193 + libs/iterator/doc/iterator_concepts.html | 127 + libs/iterator/doc/iterator_concepts.pdf | Bin 0 -> 66710 bytes libs/iterator/doc/iterator_concepts.rst | 130 + libs/iterator/doc/iterator_facade.html | 1348 +++++++ libs/iterator/doc/iterator_facade.pdf | Bin 0 -> 167634 bytes libs/iterator/doc/iterator_facade.rst | 44 + .../iterator/doc/iterator_facade_abstract.rst | 8 + libs/iterator/doc/iterator_facade_body.rst | 195 + libs/iterator/doc/iterator_facade_ref.rst | 441 +++ .../iterator/doc/iterator_facade_tutorial.rst | 523 +++ libs/iterator/doc/iterator_traits.html | 109 + libs/iterator/doc/iterator_traits.pdf | Bin 0 -> 49650 bytes libs/iterator/doc/iterator_traits.rst | 77 + libs/iterator/doc/make_counting_iterator.rst | 12 + libs/iterator/doc/make_filter_iterator.rst | 19 + libs/iterator/doc/make_reverse_iterator.rst | 13 + libs/iterator/doc/make_transform_iterator.rst | 23 + libs/iterator/doc/make_zip_iterator.rst | 12 + libs/iterator/doc/new-iter-concepts.html | 1029 ++++++ libs/iterator/doc/new-iter-concepts.pdf | Bin 0 -> 175676 bytes libs/iterator/doc/new-iter-concepts.rst | 803 +++++ libs/iterator/doc/oldeqnew.png | Bin 0 -> 33786 bytes .../doc/permutation_iter_abstract.rst | 8 + libs/iterator/doc/permutation_iterator.html | 311 ++ libs/iterator/doc/permutation_iterator.pdf | Bin 0 -> 66744 bytes libs/iterator/doc/permutation_iterator.rst | 41 + .../doc/permutation_iterator_body.rst | 19 + libs/iterator/doc/permutation_iterator_eg.rst | 71 + .../iterator/doc/permutation_iterator_ref.rst | 130 + libs/iterator/doc/pointee.html | 183 + libs/iterator/doc/pointee.pdf | Bin 0 -> 62356 bytes libs/iterator/doc/pointee.rst | 88 + libs/iterator/doc/pointee_ref.rst | 38 + libs/iterator/doc/quickbook/adaptor.qbk | 332 ++ libs/iterator/doc/quickbook/algorithms.qbk | 149 + libs/iterator/doc/quickbook/archetypes.qbk | 158 + .../doc/quickbook/concept_checking.qbk | 54 + libs/iterator/doc/quickbook/concepts.qbk | 375 ++ .../doc/quickbook/counting_iterator.qbk | 193 + libs/iterator/doc/quickbook/facade.qbk | 636 ++++ .../doc/quickbook/facade_tutorial.qbk | 506 +++ .../doc/quickbook/filter_iterator.qbk | 240 ++ .../quickbook/function_output_iterator.qbk | 99 + .../doc/quickbook/indirect_iterator.qbk | 254 ++ libs/iterator/doc/quickbook/iterator.qbk | 307 ++ .../doc/quickbook/iterator_traits.qbk | 54 + .../doc/quickbook/permutation_iterator.qbk | 207 ++ .../doc/quickbook/reverse_iterator.qbk | 159 + .../quickbook/shared_container_iterator.qbk | 249 ++ .../doc/quickbook/specialized_adaptors.qbk | 21 + .../doc/quickbook/transform_iterator.qbk | 216 ++ libs/iterator/doc/quickbook/type_traits.qbk | 211 ++ libs/iterator/doc/quickbook/zip_iterator.qbk | 265 ++ libs/iterator/doc/ref_problem.rst | 63 + libs/iterator/doc/reverse_iterator.html | 297 ++ libs/iterator/doc/reverse_iterator.pdf | Bin 0 -> 61924 bytes libs/iterator/doc/reverse_iterator.rst | 33 + .../doc/reverse_iterator_abstract.rst | 12 + libs/iterator/doc/reverse_iterator_eg.rst | 45 + libs/iterator/doc/reverse_iterator_ref.rst | 141 + libs/iterator/doc/rst2html.sh | 10 + libs/iterator/doc/rst2latex.sh | 7 + libs/iterator/doc/scanrst.py | 29 + libs/iterator/doc/sources.py | 25 + libs/iterator/doc/syscmd.py | 14 + libs/iterator/doc/transform_iterator.html | 346 ++ libs/iterator/doc/transform_iterator.pdf | Bin 0 -> 67596 bytes libs/iterator/doc/transform_iterator.rst | 32 + .../doc/transform_iterator_abstract.rst | 7 + libs/iterator/doc/transform_iterator_eg.rst | 46 + libs/iterator/doc/transform_iterator_ref.rst | 175 + libs/iterator/doc/traversal.png | Bin 0 -> 9112 bytes libs/iterator/doc/zip_iterator.html | 367 ++ libs/iterator/doc/zip_iterator.pdf | Bin 0 -> 62372 bytes libs/iterator/doc/zip_iterator.rst | 29 + libs/iterator/doc/zip_iterator_abstract.rst | 20 + libs/iterator/doc/zip_iterator_eg.rst | 115 + libs/iterator/doc/zip_iterator_ref.rst | 155 + .../example/counting_iterator_example.cpp | 52 + .../example/filter_iterator_example.cpp | 59 + .../example/func_output_iter_example.cpp | 46 + .../example/indirect_iterator_example.cpp | 60 + libs/iterator/example/node.hpp | 60 + libs/iterator/example/node_iterator1.cpp | 44 + libs/iterator/example/node_iterator1.hpp | 42 + libs/iterator/example/node_iterator2.cpp | 53 + libs/iterator/example/node_iterator2.hpp | 73 + libs/iterator/example/node_iterator3.cpp | 53 + libs/iterator/example/node_iterator3.hpp | 60 + .../example/permutation_iter_example.cpp | 68 + libs/iterator/example/reverse_iterator.cpp | 19 + .../example/reverse_iterator_example.cpp | 41 + .../example/shared_iterator_example1.cpp | 42 + .../example/shared_iterator_example2.cpp | 43 + .../example/shared_iterator_example3.cpp | 41 + .../example/transform_iterator_example.cpp | 75 + .../boost/function_output_iterator.hpp | 18 + .../include/boost/generator_iterator.hpp | 85 + .../include/boost/indirect_reference.hpp | 43 + .../include/boost/iterator/advance.hpp | 95 + .../boost/iterator/counting_iterator.hpp | 254 ++ .../iterator/detail/any_conversion_eater.hpp | 21 + .../boost/iterator/detail/config_def.hpp | 128 + .../boost/iterator/detail/config_undef.hpp | 24 + .../boost/iterator/detail/enable_if.hpp | 83 + .../detail/facade_iterator_category.hpp | 193 + .../iterator/detail/minimum_category.hpp | 19 + .../include/boost/iterator/distance.hpp | 65 + .../boost/iterator/filter_iterator.hpp | 146 + .../iterator/function_input_iterator.hpp | 180 + .../iterator/function_output_iterator.hpp | 95 + .../boost/iterator/indirect_iterator.hpp | 145 + .../include/boost/iterator/interoperable.hpp | 54 + .../include/boost/iterator/is_iterator.hpp | 148 + .../boost/iterator/is_lvalue_iterator.hpp | 164 + .../boost/iterator/is_readable_iterator.hpp | 119 + .../boost/iterator/iterator_adaptor.hpp | 358 ++ .../boost/iterator/iterator_archetypes.hpp | 509 +++ .../boost/iterator/iterator_categories.hpp | 216 ++ .../boost/iterator/iterator_concepts.hpp | 273 ++ .../boost/iterator/iterator_facade.hpp | 1062 ++++++ .../boost/iterator/iterator_traits.hpp | 61 + .../boost/iterator/minimum_category.hpp | 95 + .../boost/iterator/new_iterator_tests.hpp | 265 ++ .../boost/iterator/permutation_iterator.hpp | 76 + .../boost/iterator/reverse_iterator.hpp | 77 + .../boost/iterator/transform_iterator.hpp | 179 + .../include/boost/iterator/zip_iterator.hpp | 367 ++ .../include/boost/iterator_adaptors.hpp | 13 + libs/iterator/include/boost/next_prior.hpp | 154 + .../boost/pending/detail/int_iterator.hpp | 82 + .../boost/pending/iterator_adaptors.hpp | 6 + .../include/boost/pending/iterator_tests.hpp | 290 ++ libs/iterator/include/boost/pointee.hpp | 76 + .../boost/shared_container_iterator.hpp | 69 + libs/iterator/index.html | 12 + libs/iterator/meta/libraries.json | 19 + libs/iterator/test/Jamfile.v2 | 70 + libs/iterator/test/adl_test.cpp | 25 + libs/iterator/test/advance_test.cpp | 91 + libs/iterator/test/concept_tests.cpp | 107 + libs/iterator/test/constant_iter_arrow.cpp | 16 + .../test/constant_iter_arrow_fail.cpp | 20 + libs/iterator/test/counting_iterator_test.cpp | 301 ++ .../test/detail/zip_iterator_test.ipp | 85 + .../detail/zip_iterator_test_original.ipp | 857 +++++ libs/iterator/test/distance_test.cpp | 84 + libs/iterator/test/filter_iterator_test.cpp | 272 ++ .../test/function_input_iterator_test.cpp | 129 + .../test/function_output_iterator_cf.cpp | 37 + .../test/function_output_iterator_test.cpp | 61 + .../iterator/test/generator_iterator_test.cpp | 63 + .../test/indirect_iter_member_types.cpp | 87 + libs/iterator/test/indirect_iterator_test.cpp | 220 ++ libs/iterator/test/interoperable.cpp | 60 + libs/iterator/test/interoperable_fail.cpp | 21 + libs/iterator/test/is_convertible_fail.cpp | 19 + libs/iterator/test/is_iterator.cpp | 164 + libs/iterator/test/is_lvalue_iterator.cpp | 148 + libs/iterator/test/is_readable_iterator.cpp | 96 + .../test/iter_archetype_default_ctor.cpp | 21 + libs/iterator/test/iterator_adaptor_cc.cpp | 46 + libs/iterator/test/iterator_adaptor_test.cpp | 304 ++ libs/iterator/test/iterator_archetype_cc.cpp | 61 + libs/iterator/test/iterator_facade.cpp | 263 ++ libs/iterator/test/iterator_traits_test.cpp | 232 ++ libs/iterator/test/lvalue_concept_fail.cpp | 20 + libs/iterator/test/minimum_category.cpp | 22 + .../test/minimum_category_compile_fail.cpp | 19 + libs/iterator/test/next_prior_test.cpp | 112 + .../test/permutation_iterator_test.cpp | 103 + libs/iterator/test/pointee.cpp | 83 + .../test/range_distance_compat_test.cpp | 22 + libs/iterator/test/reverse_iterator_test.cpp | 174 + libs/iterator/test/shared_iterator_test.cpp | 64 + libs/iterator/test/static_assert_same.hpp | 20 + libs/iterator/test/test_cmake/CMakeLists.txt | 20 + libs/iterator/test/test_cmake/main.cpp | 54 + .../iterator/test/transform_iterator_test.cpp | 284 ++ libs/iterator/test/unit_tests.cpp | 107 + libs/iterator/test/zip_iterator_test.cpp | 8 + .../test/zip_iterator_test2_fusion_deque.cpp | 9 + .../test/zip_iterator_test2_fusion_list.cpp | 11 + .../test/zip_iterator_test2_fusion_vector.cpp | 11 + .../test/zip_iterator_test2_std_tuple.cpp | 24 + .../test/zip_iterator_test_fusion.cpp | 15 + .../test/zip_iterator_test_std_pair.cpp | 33 + .../test/zip_iterator_test_std_tuple.cpp | 29 + libs/optional/.drone.star | 36 + libs/optional/.drone/drone.sh | 37 + libs/optional/.gitattributes | 96 + libs/optional/.github/workflows/ci.yml | 396 ++ libs/optional/.travis.yml | 201 ++ libs/optional/CMakeLists.txt | 25 + libs/optional/README.md | 15 + libs/optional/doc/00_optional.qbk | 105 + libs/optional/doc/01_quick_start.qbk | 160 + libs/optional/doc/10_motivation.qbk | 80 + libs/optional/doc/11_development.qbk | 251 ++ libs/optional/doc/12_when_to_use.qbk | 37 + libs/optional/doc/13_relational_operators.qbk | 37 + libs/optional/doc/14_monadic_interface.qbk | 45 + libs/optional/doc/15_io.qbk | 37 + libs/optional/doc/16_optional_references.qbk | 123 + libs/optional/doc/17_in_place_factories.qbk | 139 + libs/optional/doc/18_gotchas.qbk | 111 + libs/optional/doc/19_exception_safety.qbk | 57 + libs/optional/doc/1A_type_requirements.qbk | 38 + libs/optional/doc/1B_on_performance.qbk | 156 + libs/optional/doc/21_ref_none.qbk | 31 + .../doc/22_ref_bad_optional_access.qbk | 40 + libs/optional/doc/23_ref_optional_io.qbk | 74 + libs/optional/doc/24_ref_optional_fwd.qbk | 32 + .../optional/doc/27_ref_optional_synopsis.qbk | 303 ++ .../doc/28_ref_optional_semantics.qbk | 1444 ++++++++ .../doc/29_ref_optional_convenience.qbk | 17 + libs/optional/doc/90_dependencies.qbk | 116 + libs/optional/doc/91_relnotes.qbk | 138 + libs/optional/doc/92_acknowledgments.qbk | 62 + libs/optional/doc/Jamfile.v2 | 53 + .../a_note_about_optional_bool_.html | 108 + .../html/boost_optional/acknowledgements.html | 130 + .../html/boost_optional/acknowledgments.html | 125 + .../dependencies_and_portability.html | 91 + ...emplace_operations_in_older_compilers.html | 90 + .../optional_reference_binding.html | 107 + .../boost_optional/detailed_semantics.html | 1975 ++++++++++ .../doc/html/boost_optional/development.html | 412 +++ .../doc/html/boost_optional/discussion.html | 128 + .../doc/html/boost_optional/examples.html | 147 + .../exception_safety_guarantees.html | 170 + .../boost_optional/implementation_notes.html | 55 + .../boost_optional/in_place_factories.html | 196 + .../doc/html/boost_optional/motivation.html | 128 + .../boost_optional/optional_references.html | 114 + .../doc/html/boost_optional/quick_start.html | 169 + ...sing_unnecessary_default_construction.html | 75 + .../optional_automatic_variables.html | 75 + .../quick_start/optional_data_members.html | 94 + .../quick_start/optional_return_values.html | 135 + .../quick_start/storage_in_containers.html | 64 + ...for_assignment_of_optional_references.html | 148 + .../reference/acknowledgements.html | 131 + .../dependencies_and_portability.html | 84 + .../optional_reference_binding.html | 100 + ...ost_optional_bad_optional_access_hpp_.html | 63 + .../detailed_semantics.html | 60 + .../header__boost_optional_hpp_.html | 47 + ...der__boost_optional_optional_fwd_hpp_.html | 66 + .../detailed_semantics.html | 2423 +++++++++++++ .../detailed_semantics____free_functions.html | 447 +++ ...iled_semantics____optional_references.html | 57 + ...detailed_semantics____optional_values.html | 1983 ++++++++++ .../detailed_semantics___free_functions.html | 521 +++ ...ailed_semantics___optional_references.html | 552 +++ .../detailed_semantics___optional_values.html | 1788 ++++++++++ .../header__boost_optional_hpp_.html | 47 + .../header_optional_in_place_init.html | 61 + .../header_optional_optional_refs.html | 118 + .../header_optional_optional_values.html | 153 + .../boost_optional/reference/io_header.html | 72 + .../reference/io_header/io_semantics.html | 112 + .../boost_optional/reference/relnotes.html | 183 + .../doc/html/boost_optional/relnotes.html | 384 ++ .../doc/html/boost_optional/synopsis.html | 174 + .../doc/html/boost_optional/tutorial.html | 523 +++ .../tutorial/a_note_about_optional_bool_.html | 108 + .../tutorial/design_overview.html | 184 + .../design_overview/the_interface.html | 187 + .../design_overview/the_semantics.html | 121 + .../tutorial/exception_safety_guarantees.html | 175 + .../html/boost_optional/tutorial/gotchas.html | 112 + ...e_positive_with__wmaybe_uninitialized.html | 77 + .../gotchas/mixed_relational_comparisons.html | 59 + .../gotchas/moved_from__optional_.html | 63 + .../tutorial/in_place_factories.html | 197 + .../boost_optional/tutorial/io_operators.html | 87 + .../boost_optional/tutorial/motivation.html | 129 + .../tutorial/optional_references.html | 117 + ...for_assignment_of_optional_references.html | 147 + .../tutorial/performance_considerations.html | 265 ++ ...for_assignment_of_optional_references.html | 149 + .../tutorial/relational_operators.html | 113 + .../tutorial/type_requirements.html | 109 + .../tutorial/when_to_use_optional.html | 142 + .../boost_optional/type_requirements.html | 61 + libs/optional/doc/html/images/callouts/R.png | Bin 0 -> 293 bytes libs/optional/doc/html/images/opt_align1.png | Bin 0 -> 417 bytes libs/optional/doc/html/images/opt_align2.png | Bin 0 -> 472 bytes libs/optional/doc/html/images/opt_align3.png | Bin 0 -> 468 bytes libs/optional/doc/html/images/opt_align4.png | Bin 0 -> 428 bytes libs/optional/doc/html/images/space.png | Bin 0 -> 81 bytes libs/optional/doc/html/index.html | 154 + .../optional/doc/html/optional/reference.html | 89 + .../header__boost_optional_optional_hpp_.html | 111 + libs/optional/doc/html/optional/tutorial.html | 153 + libs/optional/doc/images/opt_align1.png | Bin 0 -> 417 bytes libs/optional/doc/images/opt_align2.png | Bin 0 -> 472 bytes libs/optional/doc/images/opt_align3.png | Bin 0 -> 468 bytes libs/optional/doc/images/opt_align4.png | Bin 0 -> 428 bytes libs/optional/include/boost/none.hpp | 59 + libs/optional/include/boost/none_t.hpp | 49 + libs/optional/include/boost/optional.hpp | 18 + .../boost/optional/bad_optional_access.hpp | 41 + .../optional/detail/experimental_traits.hpp | 104 + .../detail/old_optional_implementation.hpp | 1059 ++++++ .../detail/optional_aligned_storage.hpp | 71 + .../boost/optional/detail/optional_config.hpp | 135 + .../detail/optional_factory_support.hpp | 36 + .../boost/optional/detail/optional_hash.hpp | 49 + .../detail/optional_reference_spec.hpp | 279 ++ .../boost/optional/detail/optional_relops.hpp | 196 + .../boost/optional/detail/optional_swap.hpp | 117 + .../optional_trivially_copyable_base.hpp | 510 +++ .../include/boost/optional/optional.hpp | 1666 +++++++++ .../include/boost/optional/optional_fwd.hpp | 41 + .../include/boost/optional/optional_io.hpp | 95 + libs/optional/index.html | 13 + libs/optional/meta/libraries.json | 17 + libs/optional/test/Jamfile.v2 | 91 + .../test/optional_ref_assign_test_defs.hpp | 181 + libs/optional/test/optional_test.cpp | 954 +++++ libs/optional/test/optional_test_assign.cpp | 30 + libs/optional/test/optional_test_common.hpp | 283 ++ ...optional_test_constructible_from_other.cpp | 59 + .../test/optional_test_conversions_from_U.cpp | 111 + .../test/optional_test_convert_assign.cpp | 57 + .../test/optional_test_convert_from_T.cpp | 70 + .../optional_test_deleted_default_ctor.cpp | 66 + libs/optional/test/optional_test_emplace.cpp | 390 ++ .../test/optional_test_empty_braces.cpp | 57 + .../test/optional_test_equals_none.cpp | 43 + .../optional_test_experimental_traits.cpp | 152 + libs/optional/test/optional_test_fail1.cpp | 25 + libs/optional/test/optional_test_fail2.cpp | 26 + libs/optional/test/optional_test_fail3.cpp | 33 + libs/optional/test/optional_test_fail3a.cpp | 25 + libs/optional/test/optional_test_fail3b.cpp | 28 + .../test/optional_test_fail_const_swap.cpp | 26 + ...onal_test_fail_convert_assign_of_enums.cpp | 26 + .../optional_test_fail_convert_from_null.cpp | 25 + ...onal_test_fail_copying_a_moveable_type.cpp | 36 + ...test_fail_explicit_convert_in_value_or.cpp | 32 + ...fail_explicit_convert_in_value_or_call.cpp | 34 + ...tional_test_fail_implicit_bool_convert.cpp | 28 + .../test/optional_test_fail_io_without_io.cpp | 24 + .../optional_test_fail_none_io_without_io.cpp | 23 + ...optional_test_fail_optional_rvalue_ref.cpp | 19 + libs/optional/test/optional_test_flat_map.cpp | 275 ++ libs/optional/test/optional_test_hash.cpp | 64 + .../test/optional_test_inplace_factory.cpp | 113 + .../test/optional_test_inplace_fail.cpp | 53 + .../test/optional_test_inplace_fail2.cpp | 53 + libs/optional/test/optional_test_io.cpp | 100 + .../test/optional_test_make_optional.cpp | 121 + libs/optional/test/optional_test_map.cpp | 192 + ...ional_test_maybe_uninitialized_warning.cpp | 32 + libs/optional/test/optional_test_member_T.cpp | 44 + .../optional_test_minimum_requirements.cpp | 76 + libs/optional/test/optional_test_move.cpp | 352 ++ .../optional_test_msvc_bug_workaround.cpp | 41 + .../test/optional_test_noexcept_move.cpp | 116 + libs/optional/test/optional_test_old_impl.cpp | 223 ++ .../test/optional_test_path_assignment.cpp | 73 + .../optional_test_ref_assign_const_int.cpp | 34 + .../optional_test_ref_assign_mutable_int.cpp | 31 + ...ional_test_ref_assign_portable_minimum.cpp | 45 + ...onal_test_ref_convert_assign_const_int.cpp | 30 + ...ref_convert_assign_const_int_prevented.cpp | 32 + ...al_test_ref_convert_assign_mutable_int.cpp | 30 + ...tional_test_ref_convert_assign_non_int.cpp | 39 + .../optional_test_ref_converting_ctor.cpp | 110 + .../optional/test/optional_test_ref_fail1.cpp | 25 + .../optional/test/optional_test_ref_fail3.cpp | 23 + .../optional/test/optional_test_ref_fail4.cpp | 24 + ...onal_test_ref_fail_assign_from_Trefref.cpp | 26 + ...onal_test_ref_fail_assign_from_Urefref.cpp | 26 + ...tional_test_ref_fail_init_from_Trefref.cpp | 27 + ...tional_test_ref_fail_init_from_Urefref.cpp | 27 + libs/optional/test/optional_test_ref_move.cpp | 69 + .../optional_test_ref_portable_minimum.cpp | 499 +++ .../test/optional_test_ref_to_val.cpp | 116 + .../optional_test_sfinae_friendly_ctor.cpp | 49 + .../test/optional_test_static_properties.cpp | 146 + libs/optional/test/optional_test_swap.cpp | 366 ++ libs/optional/test/optional_test_tc_base.cpp | 87 + libs/optional/test/optional_test_tie.cpp | 74 + .../test/optional_test_value_access.cpp | 222 ++ ...xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp | 50 + ...xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp | 37 + ...xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp | 38 + ...g_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp | 42 + ...g_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp | 41 + ..._NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp | 43 + ..._NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp | 42 + libs/optional/test/testable_classes.hpp | 103 + libs/range/.gitattributes | 96 + libs/range/.travis.yml | 151 + libs/range/CMakeLists.txt | 41 + libs/range/doc/Jamfile.v2 | 35 + libs/range/doc/boost_range.qbk | 199 ++ libs/range/doc/concepts.qbk | 255 ++ libs/range/doc/example.cpp | 151 + libs/range/doc/examples.qbk | 28 + libs/range/doc/faq.qbk | 30 + libs/range/doc/headers.qbk | 143 + libs/range/doc/history_ack.qbk | 58 + libs/range/doc/introduction.qbk | 43 + libs/range/doc/mfc_atl.qbk | 148 + libs/range/doc/mfc_atl.rst | 232 ++ libs/range/doc/portability.qbk | 27 + libs/range/doc/reference.qbk | 21 + libs/range/doc/reference/adaptors.qbk | 188 + .../reference/adaptors/adjacent_filtered.qbk | 32 + libs/range/doc/reference/adaptors/copied.qbk | 30 + .../adaptors/examples/indirected.cpp | 32 + .../range/doc/reference/adaptors/filtered.qbk | 32 + .../doc/reference/adaptors/formatted.qbk | 51 + libs/range/doc/reference/adaptors/indexed.qbk | 84 + .../doc/reference/adaptors/indirected.qbk | 31 + .../range/doc/reference/adaptors/map_keys.qbk | 31 + .../doc/reference/adaptors/map_values.qbk | 31 + .../doc/reference/adaptors/ref_unwrapped.qbk | 32 + .../range/doc/reference/adaptors/replaced.qbk | 33 + .../doc/reference/adaptors/replaced_if.qbk | 33 + .../range/doc/reference/adaptors/reversed.qbk | 30 + libs/range/doc/reference/adaptors/sliced.qbk | 31 + libs/range/doc/reference/adaptors/strided.qbk | 30 + .../doc/reference/adaptors/tokenized.qbk | 67 + .../doc/reference/adaptors/transformed.qbk | 32 + .../doc/reference/adaptors/type_erased.qbk | 65 + libs/range/doc/reference/adaptors/uniqued.qbk | 31 + .../doc/reference/algorithm/adjacent_find.qbk | 85 + .../doc/reference/algorithm/binary_search.qbk | 60 + libs/range/doc/reference/algorithm/copy.qbk | 41 + .../doc/reference/algorithm/copy_backward.qbk | 46 + libs/range/doc/reference/algorithm/count.qbk | 41 + .../doc/reference/algorithm/count_if.qbk | 37 + libs/range/doc/reference/algorithm/equal.qbk | 64 + .../doc/reference/algorithm/equal_range.qbk | 83 + libs/range/doc/reference/algorithm/fill.qbk | 36 + libs/range/doc/reference/algorithm/fill_n.qbk | 36 + libs/range/doc/reference/algorithm/find.qbk | 45 + .../doc/reference/algorithm/find_end.qbk | 74 + .../doc/reference/algorithm/find_first_of.qbk | 74 + .../range/doc/reference/algorithm/find_if.qbk | 50 + .../doc/reference/algorithm/for_each.qbk | 45 + .../doc/reference/algorithm/generate.qbk | 44 + .../doc/reference/algorithm/includes.qbk | 69 + .../doc/reference/algorithm/inplace_merge.qbk | 77 + .../algorithm/lexicographical_compare.qbk | 60 + .../doc/reference/algorithm/lower_bound.qbk | 93 + .../doc/reference/algorithm/make_heap.qbk | 56 + .../doc/reference/algorithm/max_element.qbk | 86 + libs/range/doc/reference/algorithm/merge.qbk | 88 + .../doc/reference/algorithm/min_element.qbk | 86 + .../doc/reference/algorithm/mismatch.qbk | 119 + .../reference/algorithm/next_permutation.qbk | 56 + .../doc/reference/algorithm/nth_element.qbk | 67 + .../doc/reference/algorithm/partial_sort.qbk | 69 + .../doc/reference/algorithm/partition.qbk | 63 + .../doc/reference/algorithm/pop_heap.qbk | 61 + .../reference/algorithm/prev_permutation.qbk | 56 + .../doc/reference/algorithm/push_heap.qbk | 61 + .../reference/algorithm/random_shuffle.qbk | 55 + libs/range/doc/reference/algorithm/remove.qbk | 60 + .../doc/reference/algorithm/remove_copy.qbk | 39 + .../reference/algorithm/remove_copy_if.qbk | 38 + .../doc/reference/algorithm/remove_if.qbk | 63 + .../range/doc/reference/algorithm/replace.qbk | 46 + .../doc/reference/algorithm/replace_copy.qbk | 38 + .../reference/algorithm/replace_copy_if.qbk | 39 + .../doc/reference/algorithm/replace_if.qbk | 41 + .../range/doc/reference/algorithm/reverse.qbk | 37 + .../doc/reference/algorithm/reverse_copy.qbk | 36 + libs/range/doc/reference/algorithm/rotate.qbk | 44 + .../doc/reference/algorithm/rotate_copy.qbk | 43 + libs/range/doc/reference/algorithm/search.qbk | 106 + .../doc/reference/algorithm/search_n.qbk | 63 + .../reference/algorithm/set_difference.qbk | 81 + .../reference/algorithm/set_intersection.qbk | 81 + .../algorithm/set_symmetric_difference.qbk | 83 + .../doc/reference/algorithm/set_union.qbk | 80 + libs/range/doc/reference/algorithm/sort.qbk | 58 + .../doc/reference/algorithm/sort_heap.qbk | 60 + .../reference/algorithm/stable_partition.qbk | 61 + .../doc/reference/algorithm/stable_sort.qbk | 59 + .../doc/reference/algorithm/swap_ranges.qbk | 37 + .../doc/reference/algorithm/transform.qbk | 88 + libs/range/doc/reference/algorithm/unique.qbk | 77 + .../doc/reference/algorithm/unique_copy.qbk | 49 + .../doc/reference/algorithm/upper_bound.qbk | 90 + .../doc/reference/algorithm_ext/copy_n.qbk | 37 + .../doc/reference/algorithm_ext/erase.qbk | 37 + .../doc/reference/algorithm_ext/for_each.qbk | 73 + .../doc/reference/algorithm_ext/insert.qbk | 46 + .../doc/reference/algorithm_ext/iota.qbk | 33 + .../doc/reference/algorithm_ext/is_sorted.qbk | 40 + .../doc/reference/algorithm_ext/overwrite.qbk | 39 + .../doc/reference/algorithm_ext/push_back.qbk | 37 + .../reference/algorithm_ext/push_front.qbk | 37 + .../reference/algorithm_ext/remove_erase.qbk | 33 + .../algorithm_ext/remove_erase_if.qbk | 34 + libs/range/doc/reference/algorithms.qbk | 182 + libs/range/doc/reference/extending.qbk | 328 ++ .../doc/reference/numeric/accumulate.qbk | 61 + .../reference/numeric/adjacent_difference.qbk | 68 + .../doc/reference/numeric/inner_product.qbk | 73 + .../doc/reference/numeric/partial_sum.qbk | 60 + libs/range/doc/reference/overview.qbk | 19 + libs/range/doc/reference/ranges.qbk | 14 + libs/range/doc/reference/ranges/any_range.qbk | 115 + .../doc/reference/ranges/counting_range.qbk | 36 + libs/range/doc/reference/ranges/irange.qbk | 43 + .../doc/reference/ranges/istream_range.qbk | 24 + libs/range/doc/reference/semantics.qbk | 200 ++ libs/range/doc/reference/synopsis.qbk | 144 + libs/range/doc/reference/utilities.qbk | 417 +++ libs/range/doc/style.qbk | 50 + libs/range/doc/upgrade.qbk | 67 + libs/range/include/boost/range.hpp | 23 + .../boost/range/adaptor/adjacent_filtered.hpp | 237 ++ .../boost/range/adaptor/argument_fwd.hpp | 80 + .../include/boost/range/adaptor/copied.hpp | 68 + .../boost/range/adaptor/define_adaptor.hpp | 109 + .../include/boost/range/adaptor/filtered.hpp | 121 + .../include/boost/range/adaptor/formatted.hpp | 229 ++ .../include/boost/range/adaptor/indexed.hpp | 395 ++ .../boost/range/adaptor/indirected.hpp | 100 + .../range/include/boost/range/adaptor/map.hpp | 204 ++ .../boost/range/adaptor/ref_unwrapped.hpp | 102 + .../include/boost/range/adaptor/replaced.hpp | 159 + .../boost/range/adaptor/replaced_if.hpp | 165 + .../include/boost/range/adaptor/reversed.hpp | 103 + .../include/boost/range/adaptor/sliced.hpp | 97 + .../include/boost/range/adaptor/strided.hpp | 697 ++++ .../include/boost/range/adaptor/tokenized.hpp | 137 + .../boost/range/adaptor/transformed.hpp | 137 + .../boost/range/adaptor/type_erased.hpp | 196 + .../include/boost/range/adaptor/uniqued.hpp | 97 + libs/range/include/boost/range/adaptors.hpp | 31 + libs/range/include/boost/range/algorithm.hpp | 104 + .../boost/range/algorithm/adjacent_find.hpp | 125 + .../boost/range/algorithm/binary_search.hpp | 49 + .../include/boost/range/algorithm/copy.hpp | 41 + .../boost/range/algorithm/copy_backward.hpp | 43 + .../include/boost/range/algorithm/count.hpp | 50 + .../boost/range/algorithm/count_if.hpp | 51 + .../include/boost/range/algorithm/equal.hpp | 200 ++ .../boost/range/algorithm/equal_range.hpp | 80 + .../include/boost/range/algorithm/fill.hpp | 49 + .../include/boost/range/algorithm/fill_n.hpp | 53 + .../include/boost/range/algorithm/find.hpp | 80 + .../boost/range/algorithm/find_end.hpp | 152 + .../boost/range/algorithm/find_first_of.hpp | 155 + .../include/boost/range/algorithm/find_if.hpp | 81 + .../boost/range/algorithm/for_each.hpp | 110 + .../boost/range/algorithm/generate.hpp | 49 + .../boost/range/algorithm/heap_algorithm.hpp | 194 + .../boost/range/algorithm/inplace_merge.hpp | 74 + .../algorithm/lexicographical_compare.hpp | 58 + .../boost/range/algorithm/lower_bound.hpp | 124 + .../boost/range/algorithm/max_element.hpp | 137 + .../include/boost/range/algorithm/merge.hpp | 61 + .../boost/range/algorithm/min_element.hpp | 137 + .../boost/range/algorithm/mismatch.hpp | 195 + .../boost/range/algorithm/nth_element.hpp | 74 + .../boost/range/algorithm/partial_sort.hpp | 76 + .../range/algorithm/partial_sort_copy.hpp | 82 + .../boost/range/algorithm/partition.hpp | 74 + .../boost/range/algorithm/permutation.hpp | 108 + .../boost/range/algorithm/random_shuffle.hpp | 141 + .../include/boost/range/algorithm/remove.hpp | 74 + .../boost/range/algorithm/remove_copy.hpp | 44 + .../boost/range/algorithm/remove_copy_if.hpp | 38 + .../boost/range/algorithm/remove_if.hpp | 75 + .../include/boost/range/algorithm/replace.hpp | 53 + .../boost/range/algorithm/replace_copy.hpp | 42 + .../boost/range/algorithm/replace_copy_if.hpp | 46 + .../boost/range/algorithm/replace_if.hpp | 54 + .../include/boost/range/algorithm/reverse.hpp | 50 + .../boost/range/algorithm/reverse_copy.hpp | 40 + .../include/boost/range/algorithm/rotate.hpp | 51 + .../boost/range/algorithm/rotate_copy.hpp | 44 + .../include/boost/range/algorithm/search.hpp | 134 + .../boost/range/algorithm/search_n.hpp | 360 ++ .../boost/range/algorithm/set_algorithm.hpp | 198 + .../include/boost/range/algorithm/sort.hpp | 68 + .../range/algorithm/stable_partition.hpp | 73 + .../boost/range/algorithm/stable_sort.hpp | 68 + .../boost/range/algorithm/swap_ranges.hpp | 132 + .../boost/range/algorithm/transform.hpp | 96 + .../include/boost/range/algorithm/unique.hpp | 107 + .../boost/range/algorithm/unique_copy.hpp | 51 + .../boost/range/algorithm/upper_bound.hpp | 127 + .../include/boost/range/algorithm_ext.hpp | 28 + .../boost/range/algorithm_ext/copy_n.hpp | 53 + .../boost/range/algorithm_ext/erase.hpp | 82 + .../boost/range/algorithm_ext/for_each.hpp | 86 + .../boost/range/algorithm_ext/insert.hpp | 49 + .../boost/range/algorithm_ext/iota.hpp | 54 + .../boost/range/algorithm_ext/is_sorted.hpp | 57 + .../boost/range/algorithm_ext/overwrite.hpp | 84 + .../boost/range/algorithm_ext/push_back.hpp | 41 + .../boost/range/algorithm_ext/push_front.hpp | 41 + libs/range/include/boost/range/any_range.hpp | 204 ++ libs/range/include/boost/range/as_array.hpp | 41 + libs/range/include/boost/range/as_literal.hpp | 164 + libs/range/include/boost/range/atl.hpp | 724 ++++ libs/range/include/boost/range/begin.hpp | 137 + libs/range/include/boost/range/category.hpp | 29 + libs/range/include/boost/range/combine.hpp | 45 + libs/range/include/boost/range/concepts.hpp | 388 ++ libs/range/include/boost/range/config.hpp | 56 + .../include/boost/range/const_iterator.hpp | 76 + .../boost/range/const_reverse_iterator.hpp | 39 + .../include/boost/range/counting_range.hpp | 76 + .../boost/range/detail/any_iterator.hpp | 589 +++ .../range/detail/any_iterator_buffer.hpp | 117 + .../range/detail/any_iterator_interface.hpp | 273 ++ .../range/detail/any_iterator_wrapper.hpp | 640 ++++ .../boost/range/detail/collection_traits.hpp | 237 ++ .../range/detail/collection_traits_detail.hpp | 447 +++ .../boost/range/detail/combine_cxx03.hpp | 79 + .../boost/range/detail/combine_cxx11.hpp | 38 + .../boost/range/detail/combine_no_rvalue.hpp | 73 + .../boost/range/detail/combine_rvalue.hpp | 32 + .../include/boost/range/detail/common.hpp | 116 + .../detail/default_constructible_unary_fn.hpp | 81 + .../detail/demote_iterator_traversal_tag.hpp | 91 + .../boost/range/detail/difference_type.hpp | 121 + .../include/boost/range/detail/empty.hpp | 120 + .../range/detail/extract_optional_type.hpp | 48 + .../boost/range/detail/has_member_size.hpp | 66 + .../range/detail/implementation_help.hpp | 114 + .../boost/range/detail/join_iterator.hpp | 358 ++ .../range/include/boost/range/detail/less.hpp | 26 + .../include/boost/range/detail/microsoft.hpp | 932 +++++ .../boost/range/detail/misc_concept.hpp | 33 + .../detail/msvc_has_iterator_workaround.hpp | 132 + .../boost/range/detail/range_return.hpp | 181 + .../include/boost/range/detail/safe_bool.hpp | 72 + .../include/boost/range/detail/sfinae.hpp | 77 + .../include/boost/range/detail/sizer.hpp | 35 + .../include/boost/range/detail/str_types.hpp | 38 + .../include/boost/range/difference_type.hpp | 47 + libs/range/include/boost/range/distance.hpp | 40 + libs/range/include/boost/range/empty.hpp | 34 + libs/range/include/boost/range/end.hpp | 130 + libs/range/include/boost/range/functions.hpp | 27 + .../boost/range/has_range_iterator.hpp | 83 + libs/range/include/boost/range/irange.hpp | 243 ++ .../include/boost/range/istream_range.hpp | 37 + libs/range/include/boost/range/iterator.hpp | 74 + .../include/boost/range/iterator_range.hpp | 16 + .../boost/range/iterator_range_core.hpp | 852 +++++ .../boost/range/iterator_range_hash.hpp | 22 + .../include/boost/range/iterator_range_io.hpp | 93 + libs/range/include/boost/range/join.hpp | 91 + .../include/boost/range/metafunctions.hpp | 28 + libs/range/include/boost/range/mfc.hpp | 984 +++++ libs/range/include/boost/range/mfc_map.hpp | 114 + .../include/boost/range/mutable_iterator.hpp | 79 + libs/range/include/boost/range/numeric.hpp | 188 + libs/range/include/boost/range/pointer.hpp | 30 + libs/range/include/boost/range/range_fwd.hpp | 63 + libs/range/include/boost/range/rbegin.hpp | 52 + libs/range/include/boost/range/reference.hpp | 29 + libs/range/include/boost/range/rend.hpp | 52 + .../include/boost/range/result_iterator.hpp | 37 + .../include/boost/range/reverse_iterator.hpp | 42 + .../boost/range/reverse_result_iterator.hpp | 36 + libs/range/include/boost/range/size.hpp | 76 + libs/range/include/boost/range/size_type.hpp | 90 + libs/range/include/boost/range/sub_range.hpp | 287 ++ libs/range/include/boost/range/traversal.hpp | 31 + libs/range/include/boost/range/value_type.hpp | 30 + libs/range/index.html | 16 + libs/range/meta/libraries.json | 17 + libs/range/test/Jamfile.v2 | 226 ++ .../test/adaptor_test/adjacent_filtered.cpp | 110 + .../adjacent_filtered_example.cpp | 65 + libs/range/test/adaptor_test/chained.cpp | 119 + libs/range/test/adaptor_test/copied.cpp | 84 + .../test/adaptor_test/copied_example.cpp | 64 + libs/range/test/adaptor_test/filtered.cpp | 197 + .../test/adaptor_test/filtered_example.cpp | 71 + libs/range/test/adaptor_test/formatted.cpp | 311 ++ .../test/adaptor_test/formatted_example.cpp | 61 + libs/range/test/adaptor_test/indexed.cpp | 152 + .../test/adaptor_test/indexed_example.cpp | 104 + libs/range/test/adaptor_test/indirected.cpp | 99 + .../test/adaptor_test/indirected_example.cpp | 66 + libs/range/test/adaptor_test/map.cpp | 171 + .../test/adaptor_test/map_keys_example.cpp | 66 + .../test/adaptor_test/map_values_example.cpp | 66 + .../range/test/adaptor_test/ref_unwrapped.cpp | 101 + .../adaptor_test/ref_unwrapped_example.cpp | 47 + libs/range/test/adaptor_test/replaced.cpp | 87 + .../test/adaptor_test/replaced_example.cpp | 64 + libs/range/test/adaptor_test/replaced_if.cpp | 96 + .../test/adaptor_test/replaced_if_example.cpp | 71 + libs/range/test/adaptor_test/reversed.cpp | 84 + .../test/adaptor_test/reversed_example.cpp | 61 + libs/range/test/adaptor_test/sliced.cpp | 99 + .../test/adaptor_test/sliced_example.cpp | 64 + libs/range/test/adaptor_test/strided.cpp | 313 ++ libs/range/test/adaptor_test/strided2.cpp | 67 + .../test/adaptor_test/strided_example.cpp | 64 + .../ticket_6742_transformed_c4789_warning.cpp | 69 + .../ticket_8676_sliced_transformed.cpp | 56 + .../ticket_9519_strided_reversed.cpp | 67 + libs/range/test/adaptor_test/tokenized.cpp | 79 + .../test/adaptor_test/tokenized_example.cpp | 65 + libs/range/test/adaptor_test/transformed.cpp | 171 + .../test/adaptor_test/transformed_example.cpp | 72 + libs/range/test/adaptor_test/type_erased.cpp | 44 + .../adaptor_test/type_erased_abstract.cpp | 88 + .../type_erased_bidirectional.cpp | 57 + .../adaptor_test/type_erased_brackets.cpp | 70 + .../test/adaptor_test/type_erased_example.cpp | 124 + .../test/adaptor_test/type_erased_forward.cpp | 57 + .../adaptor_test/type_erased_mix_values.cpp | 94 + .../type_erased_random_access.cpp | 50 + .../adaptor_test/type_erased_single_pass.cpp | 57 + .../test/adaptor_test/type_erased_test.hpp | 289 ++ .../adaptor_test/type_erased_tparam_conv.cpp | 74 + .../adaptor_test/type_erased_transformed.cpp | 67 + libs/range/test/adaptor_test/uniqued.cpp | 168 + .../test/adaptor_test/uniqued_example.cpp | 64 + libs/range/test/adaptors.cpp | 236 ++ libs/range/test/adl_conformance.cpp | 188 + libs/range/test/adl_conformance_no_using.cpp | 110 + libs/range/test/algorithm.cpp | 478 +++ libs/range/test/algorithm_example.cpp | 92 + libs/range/test/algorithm_ext_test/copy_n.cpp | 60 + libs/range/test/algorithm_ext_test/erase.cpp | 188 + .../test/algorithm_ext_test/for_each_ext.cpp | 98 + libs/range/test/algorithm_ext_test/insert.cpp | 72 + libs/range/test/algorithm_ext_test/iota.cpp | 70 + .../test/algorithm_ext_test/is_sorted.cpp | 62 + .../test/algorithm_ext_test/overwrite.cpp | 74 + .../test/algorithm_ext_test/push_back.cpp | 72 + .../test/algorithm_ext_test/push_front.cpp | 84 + .../test/algorithm_test/adjacent_find.cpp | 95 + .../test/algorithm_test/binary_search.cpp | 125 + libs/range/test/algorithm_test/copy.cpp | 74 + .../test/algorithm_test/copy_backward.cpp | 84 + libs/range/test/algorithm_test/copy_n.cpp | 70 + libs/range/test/algorithm_test/count.cpp | 85 + libs/range/test/algorithm_test/count_if.cpp | 100 + libs/range/test/algorithm_test/equal.cpp | 143 + .../range/test/algorithm_test/equal_range.cpp | 180 + libs/range/test/algorithm_test/fill.cpp | 86 + libs/range/test/algorithm_test/find.cpp | 131 + libs/range/test/algorithm_test/find_end.cpp | 200 ++ .../test/algorithm_test/find_first_of.cpp | 198 + libs/range/test/algorithm_test/find_if.cpp | 126 + libs/range/test/algorithm_test/for_each.cpp | 95 + libs/range/test/algorithm_test/generate.cpp | 95 + libs/range/test/algorithm_test/heap.cpp | 144 + libs/range/test/algorithm_test/includes.cpp | 164 + .../test/algorithm_test/inplace_merge.cpp | 166 + .../lexicographical_compare.cpp | 157 + .../range/test/algorithm_test/lower_bound.cpp | 180 + .../range/test/algorithm_test/max_element.cpp | 164 + libs/range/test/algorithm_test/merge.cpp | 236 ++ .../range/test/algorithm_test/min_element.cpp | 162 + libs/range/test/algorithm_test/mismatch.cpp | 242 ++ .../test/algorithm_test/next_permutation.cpp | 125 + .../range/test/algorithm_test/nth_element.cpp | 174 + .../test/algorithm_test/partial_sort.cpp | 170 + libs/range/test/algorithm_test/partition.cpp | 135 + .../test/algorithm_test/prev_permutation.cpp | 124 + .../test/algorithm_test/random_shuffle.cpp | 197 + libs/range/test/algorithm_test/remove.cpp | 100 + .../range/test/algorithm_test/remove_copy.cpp | 107 + .../test/algorithm_test/remove_copy_if.cpp | 115 + libs/range/test/algorithm_test/remove_if.cpp | 111 + libs/range/test/algorithm_test/replace.cpp | 86 + .../test/algorithm_test/replace_copy.cpp | 110 + .../test/algorithm_test/replace_copy_if.cpp | 117 + libs/range/test/algorithm_test/replace_if.cpp | 98 + libs/range/test/algorithm_test/reverse.cpp | 79 + .../test/algorithm_test/reverse_copy.cpp | 96 + libs/range/test/algorithm_test/rotate.cpp | 106 + .../range/test/algorithm_test/rotate_copy.cpp | 114 + libs/range/test/algorithm_test/search.cpp | 113 + libs/range/test/algorithm_test/search_n.cpp | 198 + .../test/algorithm_test/set_difference.cpp | 213 ++ .../test/algorithm_test/set_intersection.cpp | 213 ++ .../set_symmetric_difference.cpp | 215 ++ libs/range/test/algorithm_test/set_union.cpp | 209 ++ libs/range/test/algorithm_test/sort.cpp | 104 + .../test/algorithm_test/stable_partition.cpp | 133 + .../range/test/algorithm_test/stable_sort.cpp | 102 + .../range/test/algorithm_test/swap_ranges.cpp | 115 + libs/range/test/algorithm_test/transform.cpp | 184 + libs/range/test/algorithm_test/unique.cpp | 262 ++ .../range/test/algorithm_test/unique_copy.cpp | 157 + .../range/test/algorithm_test/upper_bound.cpp | 181 + libs/range/test/array.cpp | 83 + libs/range/test/atl.cpp | 623 ++++ libs/range/test/begin.cpp | 119 + libs/range/test/category.cpp | 61 + libs/range/test/combine.cpp | 160 + libs/range/test/compat2.cpp | 75 + libs/range/test/compat3.cpp | 75 + .../adaptor/adjacent_filtered_concept.cpp | 39 + .../adaptor/adjacent_filtered_concept2.cpp | 39 + .../adaptor/adjacent_filtered_concept3.cpp | 40 + .../adaptor/adjacent_filtered_concept4.cpp | 40 + .../compile_fail/adaptor/copied_concept.cpp | 24 + .../compile_fail/adaptor/copied_concept2.cpp | 24 + .../compile_fail/adaptor/copied_concept3.cpp | 23 + .../compile_fail/adaptor/copied_concept4.cpp | 24 + .../compile_fail/adaptor/mock_iterator.hpp | 82 + .../test/compile_fail/adaptor/mock_range.hpp | 50 + .../compile_fail/adaptor/reversed_concept.cpp | 23 + .../adaptor/reversed_concept2.cpp | 23 + .../adaptor/reversed_concept3.cpp | 23 + .../adaptor/reversed_concept4.cpp | 23 + .../compile_fail/adaptor/sliced_concept.cpp | 23 + .../compile_fail/adaptor/sliced_concept2.cpp | 23 + .../compile_fail/adaptor/sliced_concept3.cpp | 22 + .../compile_fail/adaptor/sliced_concept4.cpp | 22 + .../compile_fail/adaptor/uniqued_concept.cpp | 22 + .../compile_fail/adaptor/uniqued_concept2.cpp | 23 + .../compile_fail/adaptor/uniqued_concept3.cpp | 22 + .../compile_fail/adaptor/uniqued_concept4.cpp | 22 + .../test/compile_fail/iterator_range1.cpp | 22 + libs/range/test/const_iterator.cpp | 61 + libs/range/test/const_ranges.cpp | 59 + libs/range/test/const_reverse_iterator.cpp | 63 + libs/range/test/counting_range.cpp | 90 + libs/range/test/difference_type.cpp | 61 + libs/range/test/end.cpp | 119 + libs/range/test/extension_mechanism.cpp | 109 + libs/range/test/extension_size.cpp | 224 ++ libs/range/test/has_range_iterator.cpp | 68 + libs/range/test/irange.cpp | 191 + libs/range/test/istream_range.cpp | 58 + libs/range/test/iterator.cpp | 61 + libs/range/test/iterator_ext.cpp | 153 + libs/range/test/iterator_pair.cpp | 104 + libs/range/test/iterator_range.cpp | 330 ++ libs/range/test/iterator_range_drop.cpp | 200 ++ .../test/iterator_range_equality_bug.cpp | 39 + libs/range/test/iterator_range_hash.cpp | 52 + libs/range/test/iterator_range_variant.cpp | 60 + libs/range/test/join.cpp | 397 +++ libs/range/test/mfc.cpp | 743 ++++ libs/range/test/mutable_iterator.cpp | 61 + libs/range/test/partial_workaround.cpp | 114 + libs/range/test/pointer.cpp | 61 + libs/range/test/pointer_as_iterator.cpp | 39 + libs/range/test/reference.cpp | 61 + libs/range/test/result_iterator.cpp | 62 + libs/range/test/reverse_iterator.cpp | 61 + libs/range/test/reverse_result_iterator.cpp | 63 + libs/range/test/reversible_range.cpp | 74 + libs/range/test/size_type.cpp | 61 + libs/range/test/std_container.cpp | 74 + libs/range/test/string.cpp | 281 ++ libs/range/test/sub_range.cpp | 289 ++ .../range_overload_test_driver.hpp | 74 + .../test_driver/range_return_test_driver.hpp | 406 +++ .../test/test_function/check_equal_fn.hpp | 49 + .../test/test_function/counted_function.hpp | 40 + libs/range/test/test_function/equal_to_x.hpp | 33 + .../test/test_function/false_predicate.hpp | 29 + .../test/test_function/greater_than_x.hpp | 32 + .../test/test_function/multiply_by_x.hpp | 32 + .../test/test_function/true_predicate.hpp | 29 + libs/range/test/test_utils.hpp | 24 + libs/range/test/ticket_10336.cpp | 43 + libs/range/test/ticket_5486.cpp | 58 + .../test/ticket_5544_terminate_irange.cpp | 47 + libs/range/test/ticket_5547.cpp | 42 + .../test/ticket_5556_is_sorted_namespace.cpp | 37 + .../test/ticket_5811_indirected_optional.cpp | 48 + .../ticket_6715_iterator_range_equality.cpp | 52 + libs/range/test/ticket_6944.cpp | 46 + libs/range/test/value_type.cpp | 61 + libs/regex/build/Jamfile.v2 | 165 + libs/regex/build/has_icu_test.cpp | 56 + libs/regex/build/is_legacy_03.cpp | 16 + libs/regex/src/internals.hpp | 35 + libs/regex/src/posix_api.cpp | 290 ++ libs/regex/src/regex.cpp | 120 + libs/regex/src/regex_debug.cpp | 59 + libs/regex/src/static_mutex.cpp | 189 + libs/regex/src/wide_posix_api.cpp | 314 ++ .../test/config_info/regex_config_info.cpp | 73 + libs/tuple/.gitattributes | 96 + libs/tuple/.github/workflows/ci.yml | 609 ++++ libs/tuple/.travis.yml | 111 + libs/tuple/CMakeLists.txt | 27 + libs/tuple/doc/Jamfile.v2 | 37 + libs/tuple/doc/design_decisions_rationale.qbk | 190 + libs/tuple/doc/tuple_advanced_interface.qbk | 159 + libs/tuple/doc/tuple_users_guide.qbk | 525 +++ .../boost/tuple/detail/tuple_basic.hpp | 992 ++++++ libs/tuple/include/boost/tuple/tuple.hpp | 118 + .../include/boost/tuple/tuple_comparison.hpp | 175 + libs/tuple/include/boost/tuple/tuple_io.hpp | 339 ++ libs/tuple/index.html | 13 + libs/tuple/meta/libraries.json | 18 + libs/tuple/test/CMakeLists.txt | 11 + libs/tuple/test/Jamfile | 12 + libs/tuple/test/README | 16 + libs/tuple/test/another_tuple_test_bench.cpp | 162 + .../test/cmake_install_test/CMakeLists.txt | 17 + libs/tuple/test/cmake_install_test/main.cpp | 18 + .../test/cmake_subdir_test/CMakeLists.txt | 40 + libs/tuple/test/io_test.cpp | 147 + libs/tuple/test/quick.cpp | 16 + libs/tuple/test/std_tuple_element.cpp | 56 + libs/tuple/test/std_tuple_size.cpp | 61 + libs/tuple/test/structured_bindings.cpp | 77 + libs/tuple/test/tuple_test_bench.cpp | 490 +++ libs/type_traits/test/check_type.hpp | 76 + libs/type_traits/test/test.hpp | 494 +++ libs/utility/.gitattributes | 96 + libs/utility/.github/workflows/ci.yml | 470 +++ libs/utility/Assignable.html | 109 + libs/utility/CMakeLists.txt | 24 + libs/utility/Collection.html | 534 +++ libs/utility/CopyConstructible.html | 185 + libs/utility/LessThanComparable.html | 210 ++ libs/utility/MultiPassInputIterator.html | 95 + libs/utility/OptionalPointee.html | 159 + libs/utility/README.md | 26 + libs/utility/appveyor.yml | 88 + libs/utility/call_traits.htm | 19 + libs/utility/checked_delete.html | 19 + libs/utility/compressed_pair.htm | 19 + libs/utility/doc/BOOST_BINARY.qbk | 81 + libs/utility/doc/Jamfile.v2 | 413 +++ libs/utility/doc/base_from_member.qbk | 376 ++ libs/utility/doc/call_traits.qbk | 443 +++ libs/utility/doc/compressed_pair.qbk | 98 + libs/utility/doc/in_place_factory.qbk | 308 ++ libs/utility/doc/logo.png | Bin 0 -> 10457 bytes libs/utility/doc/logo.svg | 539 +++ libs/utility/doc/main.qbk | 234 ++ libs/utility/doc/operators.qbk | 2008 +++++++++++ libs/utility/doc/other.qbk | 29 + libs/utility/doc/overview.qbk | 46 + libs/utility/doc/quickref.xml | 497 +++ libs/utility/doc/result_of.qbk | 421 +++ libs/utility/doc/string_view.qbk | 209 ++ libs/utility/doc/utilities.qbk | 32 + libs/utility/doc/value_init.qbk | 584 +++ libs/utility/enable_if.html | 19 + libs/utility/identity_type/doc/Jamfile.v2 | 44 + .../utility/identity_type/doc/html/index.html | 252 ++ .../identity_type/doc/identity_type.qbk | 165 + libs/utility/identity_type/index.html | 15 + libs/utility/identity_type/test/Jamfile.v2 | 16 + libs/utility/identity_type/test/abstract.cpp | 35 + .../identity_type/test/noncopyable.cpp | 25 + libs/utility/identity_type/test/paren.cpp | 35 + libs/utility/identity_type/test/template.cpp | 48 + libs/utility/identity_type/test/var.cpp | 26 + libs/utility/identity_type/test/var_error.cpp | 18 + libs/utility/in_place_factories.html | 19 + libs/utility/include/boost/call_traits.hpp | 20 + .../utility/include/boost/compressed_pair.hpp | 20 + .../include/boost/detail/call_traits.hpp | 172 + .../include/boost/detail/compressed_pair.hpp | 456 +++ .../boost/detail/ob_compressed_pair.hpp | 498 +++ libs/utility/include/boost/operators.hpp | 920 +++++ libs/utility/include/boost/operators_v1.hpp | 951 +++++ libs/utility/include/boost/utility.hpp | 24 + .../boost/utility/base_from_member.hpp | 173 + libs/utility/include/boost/utility/binary.hpp | 709 ++++ .../boost/utility/compare_pointees.hpp | 76 + .../detail/in_place_factory_prefix.hpp | 36 + .../detail/in_place_factory_suffix.hpp | 23 + .../boost/utility/detail/minstd_rand.hpp | 58 + .../utility/detail/result_of_iterate.hpp | 218 ++ .../utility/detail/result_of_variadic.hpp | 190 + .../include/boost/utility/identity_type.hpp | 46 + .../boost/utility/in_place_factory.hpp | 92 + .../include/boost/utility/result_of.hpp | 256 ++ .../include/boost/utility/string_ref.hpp | 520 +++ .../include/boost/utility/string_ref_fwd.hpp | 37 + .../include/boost/utility/string_view.hpp | 694 ++++ .../include/boost/utility/string_view_fwd.hpp | 39 + .../boost/utility/typed_in_place_factory.hpp | 82 + .../include/boost/utility/value_init.hpp | 247 ++ libs/utility/index.html | 19 + libs/utility/iterator_adaptors.htm | 19 + libs/utility/meta/libraries.json | 133 + libs/utility/operators.htm | 19 + libs/utility/sublibs | 1 + libs/utility/test/Jamfile.v2 | 47 + .../test/base_from_member_ref_test.cpp | 29 + libs/utility/test/base_from_member_test.cpp | 593 +++ libs/utility/test/binary_test.cpp | 647 ++++ libs/utility/test/call_traits_test.cpp | 418 +++ .../test/compressed_pair_final_test.cpp | 55 + libs/utility/test/compressed_pair_test.cpp | 387 ++ libs/utility/test/initialized_test.cpp | 116 + libs/utility/test/initialized_test_fail1.cpp | 33 + libs/utility/test/initialized_test_fail2.cpp | 37 + libs/utility/test/iterators_test.cpp | 322 ++ .../utility/test/operators_constexpr_test.cpp | 59 + libs/utility/test/operators_test.cpp | 938 +++++ libs/utility/test/result_of_test.cpp | 322 ++ libs/utility/test/string_ref_from_rvalue.cpp | 26 + libs/utility/test/string_ref_test1.cpp | 111 + libs/utility/test/string_ref_test2.cpp | 325 ++ libs/utility/test/string_ref_test_io.cpp | 184 + .../test/string_view_constexpr_test1.cpp | 115 + libs/utility/test/string_view_from_rvalue.cpp | 26 + libs/utility/test/string_view_test1.cpp | 121 + libs/utility/test/string_view_test2.cpp | 440 +++ libs/utility/test/string_view_test_io.cpp | 184 + libs/utility/test/value_init_test.cpp | 373 ++ libs/utility/test/value_init_test2.cpp | 169 + libs/utility/test/value_init_test3.cpp | 40 + libs/utility/test/value_init_test_fail1.cpp | 27 + libs/utility/test/value_init_test_fail2.cpp | 27 + libs/utility/test/value_init_test_fail3.cpp | 27 + .../test/value_init_workaround_test.cpp | 163 + libs/utility/throw_exception.html | 15 + libs/utility/utility.htm | 19 + libs/utility/value_init.htm | 19 + rst.css | 149 + 1563 files changed, 247188 insertions(+) create mode 100644 boost.png create mode 100644 boost/container/list.hpp create mode 100644 boost/container/slist.hpp create mode 100644 boost/container_hash/detail/hash_integral.hpp create mode 100644 boost/container_hash/detail/hash_mix.hpp create mode 100644 boost/container_hash/detail/hash_range.hpp create mode 100644 boost/container_hash/detail/hash_tuple_like.hpp create mode 100644 boost/container_hash/detail/mulx.hpp create mode 100644 boost/container_hash/hash.hpp create mode 100644 boost/container_hash/hash_fwd.hpp create mode 100644 boost/container_hash/is_contiguous_range.hpp create mode 100644 boost/container_hash/is_described_class.hpp create mode 100644 boost/container_hash/is_range.hpp create mode 100644 boost/container_hash/is_tuple_like.hpp create mode 100644 boost/container_hash/is_unordered_range.hpp create mode 100644 boost/core/detail/is_same.hpp create mode 100644 boost/core/explicit_operator_bool.hpp create mode 100644 boost/core/invoke_swap.hpp create mode 100644 boost/core/lightweight_test_trait.hpp create mode 100644 boost/core/ref.hpp create mode 100644 boost/core/snprintf.hpp create mode 100644 boost/core/type_name.hpp create mode 100644 boost/cregex.hpp create mode 100644 boost/describe/bases.hpp create mode 100644 boost/describe/detail/config.hpp create mode 100644 boost/describe/detail/cx_streq.hpp create mode 100644 boost/describe/detail/void_t.hpp create mode 100644 boost/describe/members.hpp create mode 100644 boost/describe/modifiers.hpp create mode 100644 boost/integer.hpp create mode 100644 boost/integer_traits.hpp create mode 100644 boost/io/detail/buffer_fill.hpp create mode 100644 boost/io/detail/ostream_guard.hpp create mode 100644 boost/io/ostream_put.hpp create mode 100644 boost/iterator/counting_iterator.hpp create mode 100644 boost/iterator/detail/any_conversion_eater.hpp create mode 100644 boost/iterator/detail/minimum_category.hpp create mode 100644 boost/iterator/filter_iterator.hpp create mode 100644 boost/iterator/function_input_iterator.hpp create mode 100644 boost/iterator/function_output_iterator.hpp create mode 100644 boost/iterator/indirect_iterator.hpp create mode 100644 boost/iterator/is_lvalue_iterator.hpp create mode 100644 boost/iterator/is_readable_iterator.hpp create mode 100644 boost/iterator/iterator_archetypes.hpp create mode 100644 boost/iterator/minimum_category.hpp create mode 100644 boost/iterator/new_iterator_tests.hpp create mode 100644 boost/iterator/permutation_iterator.hpp create mode 100644 boost/iterator/transform_iterator.hpp create mode 100644 boost/iterator/zip_iterator.hpp create mode 100644 boost/mp11/algorithm.hpp create mode 100644 boost/mp11/bind.hpp create mode 100644 boost/mp11/detail/config.hpp create mode 100644 boost/mp11/detail/mp_append.hpp create mode 100644 boost/mp11/detail/mp_copy_if.hpp create mode 100644 boost/mp11/detail/mp_count.hpp create mode 100644 boost/mp11/detail/mp_defer.hpp create mode 100644 boost/mp11/detail/mp_fold.hpp create mode 100644 boost/mp11/detail/mp_front.hpp create mode 100644 boost/mp11/detail/mp_is_list.hpp create mode 100644 boost/mp11/detail/mp_is_value_list.hpp create mode 100644 boost/mp11/detail/mp_list.hpp create mode 100644 boost/mp11/detail/mp_list_v.hpp create mode 100644 boost/mp11/detail/mp_map_find.hpp create mode 100644 boost/mp11/detail/mp_min_element.hpp create mode 100644 boost/mp11/detail/mp_plus.hpp create mode 100644 boost/mp11/detail/mp_remove_if.hpp create mode 100644 boost/mp11/detail/mp_rename.hpp create mode 100644 boost/mp11/detail/mp_value.hpp create mode 100644 boost/mp11/detail/mp_void.hpp create mode 100644 boost/mp11/detail/mp_with_index.hpp create mode 100644 boost/mp11/function.hpp create mode 100644 boost/mp11/integer_sequence.hpp create mode 100644 boost/mp11/integral.hpp create mode 100644 boost/mp11/list.hpp create mode 100644 boost/mp11/set.hpp create mode 100644 boost/mp11/utility.hpp create mode 100644 boost/mp11/version.hpp create mode 100644 boost/mpl/O1_size.hpp create mode 100644 boost/mpl/O1_size_fwd.hpp create mode 100644 boost/mpl/advance.hpp create mode 100644 boost/mpl/advance_fwd.hpp create mode 100644 boost/mpl/at.hpp create mode 100644 boost/mpl/at_fwd.hpp create mode 100644 boost/mpl/aux_/O1_size_impl.hpp create mode 100644 boost/mpl/aux_/advance_backward.hpp create mode 100644 boost/mpl/aux_/advance_forward.hpp create mode 100644 boost/mpl/aux_/at_impl.hpp create mode 100644 boost/mpl/aux_/begin_end_impl.hpp create mode 100644 boost/mpl/aux_/clear_impl.hpp create mode 100644 boost/mpl/aux_/config/typeof.hpp create mode 100644 boost/mpl/aux_/fold_impl.hpp create mode 100644 boost/mpl/aux_/fold_impl_body.hpp create mode 100644 boost/mpl/aux_/has_begin.hpp create mode 100644 boost/mpl/aux_/has_size.hpp create mode 100644 boost/mpl/aux_/inserter_algorithm.hpp create mode 100644 boost/mpl/aux_/iter_fold_impl.hpp create mode 100644 boost/mpl/aux_/msvc_type.hpp create mode 100644 boost/mpl/aux_/push_back_impl.hpp create mode 100644 boost/mpl/aux_/push_front_impl.hpp create mode 100644 boost/mpl/aux_/reverse_fold_impl.hpp create mode 100644 boost/mpl/aux_/reverse_fold_impl_body.hpp create mode 100644 boost/mpl/aux_/sequence_wrapper.hpp create mode 100644 boost/mpl/aux_/traits_lambda_spec.hpp create mode 100644 boost/mpl/back_fwd.hpp create mode 100644 boost/mpl/back_inserter.hpp create mode 100644 boost/mpl/begin_end.hpp create mode 100644 boost/mpl/begin_end_fwd.hpp create mode 100644 boost/mpl/bitand.hpp create mode 100644 boost/mpl/clear.hpp create mode 100644 boost/mpl/clear_fwd.hpp create mode 100644 boost/mpl/deref.hpp create mode 100644 boost/mpl/distance.hpp create mode 100644 boost/mpl/distance_fwd.hpp create mode 100644 boost/mpl/empty_fwd.hpp create mode 100644 boost/mpl/fold.hpp create mode 100644 boost/mpl/front_fwd.hpp create mode 100644 boost/mpl/front_inserter.hpp create mode 100644 boost/mpl/inserter.hpp create mode 100644 boost/mpl/is_sequence.hpp create mode 100644 boost/mpl/iter_fold.hpp create mode 100644 boost/mpl/iterator_category.hpp create mode 100644 boost/mpl/iterator_range.hpp create mode 100644 boost/mpl/iterator_tags.hpp create mode 100644 boost/mpl/limits/unrolling.hpp create mode 100644 boost/mpl/limits/vector.hpp create mode 100644 boost/mpl/long.hpp create mode 100644 boost/mpl/long_fwd.hpp create mode 100644 boost/mpl/min_max.hpp create mode 100644 boost/mpl/minus.hpp create mode 100644 boost/mpl/negate.hpp create mode 100644 boost/mpl/pair.hpp create mode 100644 boost/mpl/pair_view.hpp create mode 100644 boost/mpl/plus.hpp create mode 100644 boost/mpl/pop_back_fwd.hpp create mode 100644 boost/mpl/pop_front_fwd.hpp create mode 100644 boost/mpl/prior.hpp create mode 100644 boost/mpl/push_back.hpp create mode 100644 boost/mpl/push_back_fwd.hpp create mode 100644 boost/mpl/push_front.hpp create mode 100644 boost/mpl/push_front_fwd.hpp create mode 100644 boost/mpl/reverse_fold.hpp create mode 100644 boost/mpl/sequence_tag.hpp create mode 100644 boost/mpl/sequence_tag_fwd.hpp create mode 100644 boost/mpl/size_fwd.hpp create mode 100644 boost/mpl/transform.hpp create mode 100644 boost/mpl/vector.hpp create mode 100644 boost/mpl/vector/aux_/O1_size.hpp create mode 100644 boost/mpl/vector/aux_/at.hpp create mode 100644 boost/mpl/vector/aux_/back.hpp create mode 100644 boost/mpl/vector/aux_/begin_end.hpp create mode 100644 boost/mpl/vector/aux_/clear.hpp create mode 100644 boost/mpl/vector/aux_/empty.hpp create mode 100644 boost/mpl/vector/aux_/front.hpp create mode 100644 boost/mpl/vector/aux_/include_preprocessed.hpp create mode 100644 boost/mpl/vector/aux_/item.hpp create mode 100644 boost/mpl/vector/aux_/iterator.hpp create mode 100644 boost/mpl/vector/aux_/numbered.hpp create mode 100644 boost/mpl/vector/aux_/numbered_c.hpp create mode 100644 boost/mpl/vector/aux_/pop_back.hpp create mode 100644 boost/mpl/vector/aux_/pop_front.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/no_ctps/vector10.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/no_ctps/vector10_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/no_ctps/vector20.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/no_ctps/vector20_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/no_ctps/vector30.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/no_ctps/vector30_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/no_ctps/vector40.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/no_ctps/vector40_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/no_ctps/vector50.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/no_ctps/vector50_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/plain/vector10.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/plain/vector10_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/plain/vector20.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/plain/vector20_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/plain/vector30.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/plain/vector30_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/plain/vector40.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/plain/vector40_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/plain/vector50.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/plain/vector50_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/typeof_based/vector10.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/typeof_based/vector10_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/typeof_based/vector20.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/typeof_based/vector20_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/typeof_based/vector30.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/typeof_based/vector30_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/typeof_based/vector40.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/typeof_based/vector40_c.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/typeof_based/vector50.hpp create mode 100644 boost/mpl/vector/aux_/preprocessed/typeof_based/vector50_c.hpp create mode 100644 boost/mpl/vector/aux_/push_back.hpp create mode 100644 boost/mpl/vector/aux_/push_front.hpp create mode 100644 boost/mpl/vector/aux_/size.hpp create mode 100644 boost/mpl/vector/aux_/tag.hpp create mode 100644 boost/mpl/vector/aux_/vector0.hpp create mode 100644 boost/mpl/vector/vector0.hpp create mode 100644 boost/mpl/vector/vector0_c.hpp create mode 100644 boost/mpl/vector/vector10.hpp create mode 100644 boost/mpl/vector/vector10_c.hpp create mode 100644 boost/mpl/vector/vector20.hpp create mode 100644 boost/mpl/vector/vector20_c.hpp create mode 100644 boost/mpl/vector/vector30.hpp create mode 100644 boost/mpl/vector/vector30_c.hpp create mode 100644 boost/mpl/vector/vector40.hpp create mode 100644 boost/mpl/vector/vector40_c.hpp create mode 100644 boost/mpl/vector/vector50.hpp create mode 100644 boost/mpl/vector/vector50_c.hpp create mode 100644 boost/predef.h create mode 100644 boost/predef/architecture.h create mode 100644 boost/predef/architecture/alpha.h create mode 100644 boost/predef/architecture/arm.h create mode 100644 boost/predef/architecture/blackfin.h create mode 100644 boost/predef/architecture/convex.h create mode 100644 boost/predef/architecture/e2k.h create mode 100644 boost/predef/architecture/ia64.h create mode 100644 boost/predef/architecture/loongarch.h create mode 100644 boost/predef/architecture/m68k.h create mode 100644 boost/predef/architecture/mips.h create mode 100644 boost/predef/architecture/parisc.h create mode 100644 boost/predef/architecture/ppc.h create mode 100644 boost/predef/architecture/ptx.h create mode 100644 boost/predef/architecture/pyramid.h create mode 100644 boost/predef/architecture/riscv.h create mode 100644 boost/predef/architecture/rs6k.h create mode 100644 boost/predef/architecture/sparc.h create mode 100644 boost/predef/architecture/superh.h create mode 100644 boost/predef/architecture/sys370.h create mode 100644 boost/predef/architecture/sys390.h create mode 100644 boost/predef/architecture/x86.h create mode 100644 boost/predef/architecture/x86/32.h create mode 100644 boost/predef/architecture/x86/64.h create mode 100644 boost/predef/architecture/z.h create mode 100644 boost/predef/compiler.h create mode 100644 boost/predef/compiler/borland.h create mode 100644 boost/predef/compiler/clang.h create mode 100644 boost/predef/compiler/comeau.h create mode 100644 boost/predef/compiler/compaq.h create mode 100644 boost/predef/compiler/diab.h create mode 100644 boost/predef/compiler/digitalmars.h create mode 100644 boost/predef/compiler/dignus.h create mode 100644 boost/predef/compiler/edg.h create mode 100644 boost/predef/compiler/ekopath.h create mode 100644 boost/predef/compiler/gcc.h create mode 100644 boost/predef/compiler/gcc_xml.h create mode 100644 boost/predef/compiler/greenhills.h create mode 100644 boost/predef/compiler/hp_acc.h create mode 100644 boost/predef/compiler/iar.h create mode 100644 boost/predef/compiler/ibm.h create mode 100644 boost/predef/compiler/intel.h create mode 100644 boost/predef/compiler/kai.h create mode 100644 boost/predef/compiler/llvm.h create mode 100644 boost/predef/compiler/metaware.h create mode 100644 boost/predef/compiler/metrowerks.h create mode 100644 boost/predef/compiler/microtec.h create mode 100644 boost/predef/compiler/mpw.h create mode 100644 boost/predef/compiler/nvcc.h create mode 100644 boost/predef/compiler/palm.h create mode 100644 boost/predef/compiler/pgi.h create mode 100644 boost/predef/compiler/sgi_mipspro.h create mode 100644 boost/predef/compiler/sunpro.h create mode 100644 boost/predef/compiler/tendra.h create mode 100644 boost/predef/compiler/visualc.h create mode 100644 boost/predef/compiler/watcom.h create mode 100644 boost/predef/detail/_cassert.h create mode 100644 boost/predef/detail/_exception.h create mode 100644 boost/predef/detail/comp_detected.h create mode 100644 boost/predef/hardware.h create mode 100644 boost/predef/hardware/simd.h create mode 100644 boost/predef/hardware/simd/arm.h create mode 100644 boost/predef/hardware/simd/arm/versions.h create mode 100644 boost/predef/hardware/simd/ppc.h create mode 100644 boost/predef/hardware/simd/ppc/versions.h create mode 100644 boost/predef/hardware/simd/x86.h create mode 100644 boost/predef/hardware/simd/x86/versions.h create mode 100644 boost/predef/hardware/simd/x86_amd.h create mode 100644 boost/predef/hardware/simd/x86_amd/versions.h create mode 100644 boost/predef/language.h create mode 100644 boost/predef/language/cuda.h create mode 100644 boost/predef/language/objc.h create mode 100644 boost/predef/language/stdc.h create mode 100644 boost/predef/language/stdcpp.h create mode 100644 boost/predef/library.h create mode 100644 boost/predef/library/c.h create mode 100644 boost/predef/library/c/_prefix.h create mode 100644 boost/predef/library/c/cloudabi.h create mode 100644 boost/predef/library/c/gnu.h create mode 100644 boost/predef/library/c/uc.h create mode 100644 boost/predef/library/c/vms.h create mode 100644 boost/predef/library/c/zos.h create mode 100644 boost/predef/library/std.h create mode 100644 boost/predef/library/std/_prefix.h create mode 100644 boost/predef/library/std/cxx.h create mode 100644 boost/predef/library/std/dinkumware.h create mode 100644 boost/predef/library/std/libcomo.h create mode 100644 boost/predef/library/std/modena.h create mode 100644 boost/predef/library/std/msl.h create mode 100644 boost/predef/library/std/msvc.h create mode 100644 boost/predef/library/std/roguewave.h create mode 100644 boost/predef/library/std/sgi.h create mode 100644 boost/predef/library/std/stdcpp3.h create mode 100644 boost/predef/library/std/stlport.h create mode 100644 boost/predef/library/std/vacpp.h create mode 100644 boost/predef/os.h create mode 100644 boost/predef/os/aix.h create mode 100644 boost/predef/os/amigaos.h create mode 100644 boost/predef/os/beos.h create mode 100644 boost/predef/os/bsd.h create mode 100644 boost/predef/os/bsd/bsdi.h create mode 100644 boost/predef/os/bsd/dragonfly.h create mode 100644 boost/predef/os/bsd/free.h create mode 100644 boost/predef/os/bsd/net.h create mode 100644 boost/predef/os/bsd/open.h create mode 100644 boost/predef/os/cygwin.h create mode 100644 boost/predef/os/haiku.h create mode 100644 boost/predef/os/hpux.h create mode 100644 boost/predef/os/irix.h create mode 100644 boost/predef/os/linux.h create mode 100644 boost/predef/os/macos.h create mode 100644 boost/predef/os/os400.h create mode 100644 boost/predef/os/qnxnto.h create mode 100644 boost/predef/os/solaris.h create mode 100644 boost/predef/os/unix.h create mode 100644 boost/predef/os/vms.h create mode 100644 boost/predef/other.h create mode 100644 boost/predef/other/endian.h create mode 100644 boost/predef/other/wordsize.h create mode 100644 boost/predef/other/workaround.h create mode 100644 boost/predef/version.h create mode 100644 boost/preprocessor/arithmetic/div.hpp create mode 100644 boost/preprocessor/arithmetic/mul.hpp create mode 100644 boost/preprocessor/detail/is_unary.hpp create mode 100644 boost/preprocessor/enum.hpp create mode 100644 boost/preprocessor/enum_params.hpp create mode 100644 boost/preprocessor/enum_params_with_a_default.hpp create mode 100644 boost/preprocessor/facilities/intercept.hpp create mode 100644 boost/preprocessor/facilities/limits/intercept_1024.hpp create mode 100644 boost/preprocessor/facilities/limits/intercept_256.hpp create mode 100644 boost/preprocessor/facilities/limits/intercept_512.hpp create mode 100644 boost/preprocessor/list/for_each.hpp create mode 100644 boost/preprocessor/punctuation/paren.hpp create mode 100644 boost/preprocessor/repetition/enum.hpp create mode 100644 boost/preprocessor/repetition/enum_params_with_a_default.hpp create mode 100644 boost/ref.hpp create mode 100644 boost/regex.hpp create mode 100644 boost/regex/config.hpp create mode 100644 boost/regex/config/borland.hpp create mode 100644 boost/regex/config/cwchar.hpp create mode 100644 boost/regex/pattern_except.hpp create mode 100644 boost/regex/pending/static_mutex.hpp create mode 100644 boost/regex/regex_traits.hpp create mode 100644 boost/regex/user.hpp create mode 100644 boost/regex/v4/basic_regex.hpp create mode 100644 boost/regex/v4/basic_regex_creator.hpp create mode 100644 boost/regex/v4/basic_regex_parser.hpp create mode 100644 boost/regex/v4/c_regex_traits.hpp create mode 100644 boost/regex/v4/char_regex_traits.hpp create mode 100644 boost/regex/v4/cpp_regex_traits.hpp create mode 100644 boost/regex/v4/cregex.hpp create mode 100644 boost/regex/v4/error_type.hpp create mode 100644 boost/regex/v4/indexed_bit_flag.hpp create mode 100644 boost/regex/v4/iterator_category.hpp create mode 100644 boost/regex/v4/iterator_traits.hpp create mode 100644 boost/regex/v4/match_flags.hpp create mode 100644 boost/regex/v4/match_results.hpp create mode 100644 boost/regex/v4/mem_block_cache.hpp create mode 100644 boost/regex/v4/object_cache.hpp create mode 100644 boost/regex/v4/pattern_except.hpp create mode 100644 boost/regex/v4/perl_matcher.hpp create mode 100644 boost/regex/v4/perl_matcher_common.hpp create mode 100644 boost/regex/v4/perl_matcher_non_recursive.hpp create mode 100644 boost/regex/v4/perl_matcher_recursive.hpp create mode 100644 boost/regex/v4/primary_transform.hpp create mode 100644 boost/regex/v4/protected_call.hpp create mode 100644 boost/regex/v4/regbase.hpp create mode 100644 boost/regex/v4/regex.hpp create mode 100644 boost/regex/v4/regex_format.hpp create mode 100644 boost/regex/v4/regex_fwd.hpp create mode 100644 boost/regex/v4/regex_grep.hpp create mode 100644 boost/regex/v4/regex_iterator.hpp create mode 100644 boost/regex/v4/regex_match.hpp create mode 100644 boost/regex/v4/regex_merge.hpp create mode 100644 boost/regex/v4/regex_raw_buffer.hpp create mode 100644 boost/regex/v4/regex_replace.hpp create mode 100644 boost/regex/v4/regex_search.hpp create mode 100644 boost/regex/v4/regex_split.hpp create mode 100644 boost/regex/v4/regex_token_iterator.hpp create mode 100644 boost/regex/v4/regex_traits.hpp create mode 100644 boost/regex/v4/regex_traits_defaults.hpp create mode 100644 boost/regex/v4/regex_workaround.hpp create mode 100644 boost/regex/v4/states.hpp create mode 100644 boost/regex/v4/sub_match.hpp create mode 100644 boost/regex/v4/syntax_type.hpp create mode 100644 boost/regex/v4/w32_regex_traits.hpp create mode 100644 boost/regex/v5/basic_regex.hpp create mode 100644 boost/regex/v5/basic_regex_creator.hpp create mode 100644 boost/regex/v5/basic_regex_parser.hpp create mode 100644 boost/regex/v5/c_regex_traits.hpp create mode 100644 boost/regex/v5/char_regex_traits.hpp create mode 100644 boost/regex/v5/cpp_regex_traits.hpp create mode 100644 boost/regex/v5/cregex.hpp create mode 100644 boost/regex/v5/error_type.hpp create mode 100644 boost/regex/v5/iterator_category.hpp create mode 100644 boost/regex/v5/match_flags.hpp create mode 100644 boost/regex/v5/match_results.hpp create mode 100644 boost/regex/v5/mem_block_cache.hpp create mode 100644 boost/regex/v5/object_cache.hpp create mode 100644 boost/regex/v5/pattern_except.hpp create mode 100644 boost/regex/v5/perl_matcher.hpp create mode 100644 boost/regex/v5/perl_matcher_common.hpp create mode 100644 boost/regex/v5/perl_matcher_non_recursive.hpp create mode 100644 boost/regex/v5/primary_transform.hpp create mode 100644 boost/regex/v5/regbase.hpp create mode 100644 boost/regex/v5/regex.hpp create mode 100644 boost/regex/v5/regex_format.hpp create mode 100644 boost/regex/v5/regex_fwd.hpp create mode 100644 boost/regex/v5/regex_grep.hpp create mode 100644 boost/regex/v5/regex_iterator.hpp create mode 100644 boost/regex/v5/regex_match.hpp create mode 100644 boost/regex/v5/regex_merge.hpp create mode 100644 boost/regex/v5/regex_raw_buffer.hpp create mode 100644 boost/regex/v5/regex_replace.hpp create mode 100644 boost/regex/v5/regex_search.hpp create mode 100644 boost/regex/v5/regex_split.hpp create mode 100644 boost/regex/v5/regex_token_iterator.hpp create mode 100644 boost/regex/v5/regex_traits.hpp create mode 100644 boost/regex/v5/regex_traits_defaults.hpp create mode 100644 boost/regex/v5/regex_workaround.hpp create mode 100644 boost/regex/v5/states.hpp create mode 100644 boost/regex/v5/sub_match.hpp create mode 100644 boost/regex/v5/syntax_type.hpp create mode 100644 boost/regex/v5/w32_regex_traits.hpp create mode 100644 boost/regex_fwd.hpp create mode 100644 boost/scoped_array.hpp create mode 100644 boost/scoped_ptr.hpp create mode 100644 boost/smart_ptr/scoped_array.hpp create mode 100644 boost/smart_ptr/scoped_ptr.hpp create mode 100644 boost/type_traits/cv_traits.hpp create mode 100644 boost/type_traits/object_traits.hpp create mode 100644 boost/type_traits/same_traits.hpp create mode 100644 doc/src/boostbook.css create mode 100644 doc/src/images/caution.png create mode 100644 doc/src/images/home.png create mode 100644 doc/src/images/next.png create mode 100644 doc/src/images/note.png create mode 100644 doc/src/images/prev.png create mode 100644 doc/src/images/up.png create mode 100644 doc/src/images/warning.png create mode 100644 libs/align/.github/workflows/ci.yml create mode 100644 libs/align/.travis.yml create mode 100644 libs/config/test/config_info.cpp create mode 100644 libs/iterator/.gitattributes create mode 100644 libs/iterator/.github/workflows/ci.yml create mode 100644 libs/iterator/CMakeLists.txt create mode 100644 libs/iterator/README.md create mode 100644 libs/iterator/appveyor.yml create mode 100644 libs/iterator/doc/BidirectionalTraversal.html create mode 100644 libs/iterator/doc/BidirectionalTraversal.rst create mode 100644 libs/iterator/doc/ForwardTraversal.html create mode 100644 libs/iterator/doc/ForwardTraversal.rst create mode 100644 libs/iterator/doc/GNUmakefile create mode 100644 libs/iterator/doc/IncrementableIterator.html create mode 100644 libs/iterator/doc/IncrementableIterator.rst create mode 100644 libs/iterator/doc/InteroperableIterator.rst create mode 100644 libs/iterator/doc/Jamfile.v2 create mode 100644 libs/iterator/doc/LvalueIterator.html create mode 100644 libs/iterator/doc/LvalueIterator.rst create mode 100644 libs/iterator/doc/RandomAccessTraversal.html create mode 100644 libs/iterator/doc/RandomAccessTraversal.rst create mode 100644 libs/iterator/doc/ReadableIterator.html create mode 100644 libs/iterator/doc/ReadableIterator.rst create mode 100644 libs/iterator/doc/SinglePassIterator.html create mode 100644 libs/iterator/doc/SinglePassIterator.rst create mode 100644 libs/iterator/doc/SwappableIterator.html create mode 100644 libs/iterator/doc/SwappableIterator.rst create mode 100644 libs/iterator/doc/WritableIterator.html create mode 100644 libs/iterator/doc/WritableIterator.rst create mode 100644 libs/iterator/doc/access.png create mode 100644 libs/iterator/doc/access2old.png create mode 100644 libs/iterator/doc/advance.rst create mode 100644 libs/iterator/doc/counting_iterator.html create mode 100644 libs/iterator/doc/counting_iterator.pdf create mode 100644 libs/iterator/doc/counting_iterator.rst create mode 100644 libs/iterator/doc/counting_iterator_abstract.rst create mode 100644 libs/iterator/doc/counting_iterator_eg.rst create mode 100644 libs/iterator/doc/counting_iterator_ref.rst create mode 100644 libs/iterator/doc/default.css create mode 100644 libs/iterator/doc/distance.rst create mode 100644 libs/iterator/doc/docutils.sty create mode 100644 libs/iterator/doc/facade-and-adaptor.html create mode 100644 libs/iterator/doc/facade-and-adaptor.pdf create mode 100644 libs/iterator/doc/facade-and-adaptor.rst create mode 100644 libs/iterator/doc/facade_iterator_category.rst create mode 100644 libs/iterator/doc/filter_iterator.html create mode 100644 libs/iterator/doc/filter_iterator.pdf create mode 100644 libs/iterator/doc/filter_iterator.rst create mode 100644 libs/iterator/doc/filter_iterator_abstract.rst create mode 100644 libs/iterator/doc/filter_iterator_eg.rst create mode 100644 libs/iterator/doc/filter_iterator_ref.rst create mode 100644 libs/iterator/doc/func_output_iter_abstract.rst create mode 100644 libs/iterator/doc/func_output_iter_ref.rst create mode 100644 libs/iterator/doc/function_input_iterator.html create mode 100644 libs/iterator/doc/function_input_iterator.rst create mode 100644 libs/iterator/doc/function_output_iterator.html create mode 100644 libs/iterator/doc/function_output_iterator.pdf create mode 100644 libs/iterator/doc/function_output_iterator.rst create mode 100644 libs/iterator/doc/function_output_iterator_eg.rst create mode 100644 libs/iterator/doc/generate.py create mode 100644 libs/iterator/doc/generator_iterator.htm create mode 100644 libs/iterator/doc/index.html create mode 100644 libs/iterator/doc/index.rst create mode 100644 libs/iterator/doc/indirect_iterator.html create mode 100644 libs/iterator/doc/indirect_iterator.pdf create mode 100644 libs/iterator/doc/indirect_iterator.rst create mode 100644 libs/iterator/doc/indirect_iterator_abstract.rst create mode 100644 libs/iterator/doc/indirect_iterator_eg.rst create mode 100644 libs/iterator/doc/indirect_iterator_ref.rst create mode 100644 libs/iterator/doc/indirect_reference_ref.rst create mode 100644 libs/iterator/doc/interoperability-revisited.rst create mode 100644 libs/iterator/doc/issues.rst create mode 100644 libs/iterator/doc/iterator_adaptor.html create mode 100644 libs/iterator/doc/iterator_adaptor.pdf create mode 100644 libs/iterator/doc/iterator_adaptor.rst create mode 100644 libs/iterator/doc/iterator_adaptor_abstract.rst create mode 100644 libs/iterator/doc/iterator_adaptor_body.rst create mode 100644 libs/iterator/doc/iterator_adaptor_ref.rst create mode 100644 libs/iterator/doc/iterator_adaptor_tutorial.rst create mode 100644 libs/iterator/doc/iterator_archetypes.html create mode 100644 libs/iterator/doc/iterator_archetypes.pdf create mode 100644 libs/iterator/doc/iterator_archetypes.rst create mode 100644 libs/iterator/doc/iterator_concepts.html create mode 100644 libs/iterator/doc/iterator_concepts.pdf create mode 100644 libs/iterator/doc/iterator_concepts.rst create mode 100644 libs/iterator/doc/iterator_facade.html create mode 100644 libs/iterator/doc/iterator_facade.pdf create mode 100644 libs/iterator/doc/iterator_facade.rst create mode 100644 libs/iterator/doc/iterator_facade_abstract.rst create mode 100644 libs/iterator/doc/iterator_facade_body.rst create mode 100644 libs/iterator/doc/iterator_facade_ref.rst create mode 100644 libs/iterator/doc/iterator_facade_tutorial.rst create mode 100644 libs/iterator/doc/iterator_traits.html create mode 100644 libs/iterator/doc/iterator_traits.pdf create mode 100644 libs/iterator/doc/iterator_traits.rst create mode 100644 libs/iterator/doc/make_counting_iterator.rst create mode 100644 libs/iterator/doc/make_filter_iterator.rst create mode 100644 libs/iterator/doc/make_reverse_iterator.rst create mode 100644 libs/iterator/doc/make_transform_iterator.rst create mode 100644 libs/iterator/doc/make_zip_iterator.rst create mode 100644 libs/iterator/doc/new-iter-concepts.html create mode 100644 libs/iterator/doc/new-iter-concepts.pdf create mode 100644 libs/iterator/doc/new-iter-concepts.rst create mode 100644 libs/iterator/doc/oldeqnew.png create mode 100644 libs/iterator/doc/permutation_iter_abstract.rst create mode 100644 libs/iterator/doc/permutation_iterator.html create mode 100644 libs/iterator/doc/permutation_iterator.pdf create mode 100644 libs/iterator/doc/permutation_iterator.rst create mode 100644 libs/iterator/doc/permutation_iterator_body.rst create mode 100644 libs/iterator/doc/permutation_iterator_eg.rst create mode 100644 libs/iterator/doc/permutation_iterator_ref.rst create mode 100644 libs/iterator/doc/pointee.html create mode 100644 libs/iterator/doc/pointee.pdf create mode 100644 libs/iterator/doc/pointee.rst create mode 100644 libs/iterator/doc/pointee_ref.rst create mode 100644 libs/iterator/doc/quickbook/adaptor.qbk create mode 100644 libs/iterator/doc/quickbook/algorithms.qbk create mode 100644 libs/iterator/doc/quickbook/archetypes.qbk create mode 100644 libs/iterator/doc/quickbook/concept_checking.qbk create mode 100644 libs/iterator/doc/quickbook/concepts.qbk create mode 100644 libs/iterator/doc/quickbook/counting_iterator.qbk create mode 100644 libs/iterator/doc/quickbook/facade.qbk create mode 100644 libs/iterator/doc/quickbook/facade_tutorial.qbk create mode 100644 libs/iterator/doc/quickbook/filter_iterator.qbk create mode 100644 libs/iterator/doc/quickbook/function_output_iterator.qbk create mode 100644 libs/iterator/doc/quickbook/indirect_iterator.qbk create mode 100644 libs/iterator/doc/quickbook/iterator.qbk create mode 100644 libs/iterator/doc/quickbook/iterator_traits.qbk create mode 100644 libs/iterator/doc/quickbook/permutation_iterator.qbk create mode 100644 libs/iterator/doc/quickbook/reverse_iterator.qbk create mode 100644 libs/iterator/doc/quickbook/shared_container_iterator.qbk create mode 100644 libs/iterator/doc/quickbook/specialized_adaptors.qbk create mode 100644 libs/iterator/doc/quickbook/transform_iterator.qbk create mode 100644 libs/iterator/doc/quickbook/type_traits.qbk create mode 100644 libs/iterator/doc/quickbook/zip_iterator.qbk create mode 100644 libs/iterator/doc/ref_problem.rst create mode 100644 libs/iterator/doc/reverse_iterator.html create mode 100644 libs/iterator/doc/reverse_iterator.pdf create mode 100644 libs/iterator/doc/reverse_iterator.rst create mode 100644 libs/iterator/doc/reverse_iterator_abstract.rst create mode 100644 libs/iterator/doc/reverse_iterator_eg.rst create mode 100644 libs/iterator/doc/reverse_iterator_ref.rst create mode 100644 libs/iterator/doc/rst2html.sh create mode 100644 libs/iterator/doc/rst2latex.sh create mode 100644 libs/iterator/doc/scanrst.py create mode 100644 libs/iterator/doc/sources.py create mode 100644 libs/iterator/doc/syscmd.py create mode 100644 libs/iterator/doc/transform_iterator.html create mode 100644 libs/iterator/doc/transform_iterator.pdf create mode 100644 libs/iterator/doc/transform_iterator.rst create mode 100644 libs/iterator/doc/transform_iterator_abstract.rst create mode 100644 libs/iterator/doc/transform_iterator_eg.rst create mode 100644 libs/iterator/doc/transform_iterator_ref.rst create mode 100644 libs/iterator/doc/traversal.png create mode 100644 libs/iterator/doc/zip_iterator.html create mode 100644 libs/iterator/doc/zip_iterator.pdf create mode 100644 libs/iterator/doc/zip_iterator.rst create mode 100644 libs/iterator/doc/zip_iterator_abstract.rst create mode 100644 libs/iterator/doc/zip_iterator_eg.rst create mode 100644 libs/iterator/doc/zip_iterator_ref.rst create mode 100644 libs/iterator/example/counting_iterator_example.cpp create mode 100644 libs/iterator/example/filter_iterator_example.cpp create mode 100644 libs/iterator/example/func_output_iter_example.cpp create mode 100644 libs/iterator/example/indirect_iterator_example.cpp create mode 100644 libs/iterator/example/node.hpp create mode 100644 libs/iterator/example/node_iterator1.cpp create mode 100644 libs/iterator/example/node_iterator1.hpp create mode 100644 libs/iterator/example/node_iterator2.cpp create mode 100644 libs/iterator/example/node_iterator2.hpp create mode 100644 libs/iterator/example/node_iterator3.cpp create mode 100644 libs/iterator/example/node_iterator3.hpp create mode 100644 libs/iterator/example/permutation_iter_example.cpp create mode 100644 libs/iterator/example/reverse_iterator.cpp create mode 100644 libs/iterator/example/reverse_iterator_example.cpp create mode 100644 libs/iterator/example/shared_iterator_example1.cpp create mode 100644 libs/iterator/example/shared_iterator_example2.cpp create mode 100644 libs/iterator/example/shared_iterator_example3.cpp create mode 100644 libs/iterator/example/transform_iterator_example.cpp create mode 100644 libs/iterator/include/boost/function_output_iterator.hpp create mode 100644 libs/iterator/include/boost/generator_iterator.hpp create mode 100644 libs/iterator/include/boost/indirect_reference.hpp create mode 100644 libs/iterator/include/boost/iterator/advance.hpp create mode 100644 libs/iterator/include/boost/iterator/counting_iterator.hpp create mode 100644 libs/iterator/include/boost/iterator/detail/any_conversion_eater.hpp create mode 100644 libs/iterator/include/boost/iterator/detail/config_def.hpp create mode 100644 libs/iterator/include/boost/iterator/detail/config_undef.hpp create mode 100644 libs/iterator/include/boost/iterator/detail/enable_if.hpp create mode 100644 libs/iterator/include/boost/iterator/detail/facade_iterator_category.hpp create mode 100644 libs/iterator/include/boost/iterator/detail/minimum_category.hpp create mode 100644 libs/iterator/include/boost/iterator/distance.hpp create mode 100644 libs/iterator/include/boost/iterator/filter_iterator.hpp create mode 100644 libs/iterator/include/boost/iterator/function_input_iterator.hpp create mode 100644 libs/iterator/include/boost/iterator/function_output_iterator.hpp create mode 100644 libs/iterator/include/boost/iterator/indirect_iterator.hpp create mode 100644 libs/iterator/include/boost/iterator/interoperable.hpp create mode 100644 libs/iterator/include/boost/iterator/is_iterator.hpp create mode 100644 libs/iterator/include/boost/iterator/is_lvalue_iterator.hpp create mode 100644 libs/iterator/include/boost/iterator/is_readable_iterator.hpp create mode 100644 libs/iterator/include/boost/iterator/iterator_adaptor.hpp create mode 100644 libs/iterator/include/boost/iterator/iterator_archetypes.hpp create mode 100644 libs/iterator/include/boost/iterator/iterator_categories.hpp create mode 100644 libs/iterator/include/boost/iterator/iterator_concepts.hpp create mode 100644 libs/iterator/include/boost/iterator/iterator_facade.hpp create mode 100644 libs/iterator/include/boost/iterator/iterator_traits.hpp create mode 100644 libs/iterator/include/boost/iterator/minimum_category.hpp create mode 100644 libs/iterator/include/boost/iterator/new_iterator_tests.hpp create mode 100644 libs/iterator/include/boost/iterator/permutation_iterator.hpp create mode 100644 libs/iterator/include/boost/iterator/reverse_iterator.hpp create mode 100644 libs/iterator/include/boost/iterator/transform_iterator.hpp create mode 100644 libs/iterator/include/boost/iterator/zip_iterator.hpp create mode 100644 libs/iterator/include/boost/iterator_adaptors.hpp create mode 100644 libs/iterator/include/boost/next_prior.hpp create mode 100644 libs/iterator/include/boost/pending/detail/int_iterator.hpp create mode 100644 libs/iterator/include/boost/pending/iterator_adaptors.hpp create mode 100644 libs/iterator/include/boost/pending/iterator_tests.hpp create mode 100644 libs/iterator/include/boost/pointee.hpp create mode 100644 libs/iterator/include/boost/shared_container_iterator.hpp create mode 100644 libs/iterator/index.html create mode 100644 libs/iterator/meta/libraries.json create mode 100644 libs/iterator/test/Jamfile.v2 create mode 100644 libs/iterator/test/adl_test.cpp create mode 100644 libs/iterator/test/advance_test.cpp create mode 100644 libs/iterator/test/concept_tests.cpp create mode 100644 libs/iterator/test/constant_iter_arrow.cpp create mode 100644 libs/iterator/test/constant_iter_arrow_fail.cpp create mode 100644 libs/iterator/test/counting_iterator_test.cpp create mode 100644 libs/iterator/test/detail/zip_iterator_test.ipp create mode 100644 libs/iterator/test/detail/zip_iterator_test_original.ipp create mode 100644 libs/iterator/test/distance_test.cpp create mode 100644 libs/iterator/test/filter_iterator_test.cpp create mode 100644 libs/iterator/test/function_input_iterator_test.cpp create mode 100644 libs/iterator/test/function_output_iterator_cf.cpp create mode 100644 libs/iterator/test/function_output_iterator_test.cpp create mode 100644 libs/iterator/test/generator_iterator_test.cpp create mode 100644 libs/iterator/test/indirect_iter_member_types.cpp create mode 100644 libs/iterator/test/indirect_iterator_test.cpp create mode 100644 libs/iterator/test/interoperable.cpp create mode 100644 libs/iterator/test/interoperable_fail.cpp create mode 100644 libs/iterator/test/is_convertible_fail.cpp create mode 100644 libs/iterator/test/is_iterator.cpp create mode 100644 libs/iterator/test/is_lvalue_iterator.cpp create mode 100644 libs/iterator/test/is_readable_iterator.cpp create mode 100644 libs/iterator/test/iter_archetype_default_ctor.cpp create mode 100644 libs/iterator/test/iterator_adaptor_cc.cpp create mode 100644 libs/iterator/test/iterator_adaptor_test.cpp create mode 100644 libs/iterator/test/iterator_archetype_cc.cpp create mode 100644 libs/iterator/test/iterator_facade.cpp create mode 100644 libs/iterator/test/iterator_traits_test.cpp create mode 100644 libs/iterator/test/lvalue_concept_fail.cpp create mode 100644 libs/iterator/test/minimum_category.cpp create mode 100644 libs/iterator/test/minimum_category_compile_fail.cpp create mode 100644 libs/iterator/test/next_prior_test.cpp create mode 100644 libs/iterator/test/permutation_iterator_test.cpp create mode 100644 libs/iterator/test/pointee.cpp create mode 100644 libs/iterator/test/range_distance_compat_test.cpp create mode 100644 libs/iterator/test/reverse_iterator_test.cpp create mode 100644 libs/iterator/test/shared_iterator_test.cpp create mode 100644 libs/iterator/test/static_assert_same.hpp create mode 100644 libs/iterator/test/test_cmake/CMakeLists.txt create mode 100644 libs/iterator/test/test_cmake/main.cpp create mode 100644 libs/iterator/test/transform_iterator_test.cpp create mode 100644 libs/iterator/test/unit_tests.cpp create mode 100644 libs/iterator/test/zip_iterator_test.cpp create mode 100644 libs/iterator/test/zip_iterator_test2_fusion_deque.cpp create mode 100644 libs/iterator/test/zip_iterator_test2_fusion_list.cpp create mode 100644 libs/iterator/test/zip_iterator_test2_fusion_vector.cpp create mode 100644 libs/iterator/test/zip_iterator_test2_std_tuple.cpp create mode 100644 libs/iterator/test/zip_iterator_test_fusion.cpp create mode 100644 libs/iterator/test/zip_iterator_test_std_pair.cpp create mode 100644 libs/iterator/test/zip_iterator_test_std_tuple.cpp create mode 100644 libs/optional/.drone.star create mode 100644 libs/optional/.drone/drone.sh create mode 100644 libs/optional/.gitattributes create mode 100644 libs/optional/.github/workflows/ci.yml create mode 100644 libs/optional/.travis.yml create mode 100644 libs/optional/CMakeLists.txt create mode 100644 libs/optional/README.md create mode 100644 libs/optional/doc/00_optional.qbk create mode 100644 libs/optional/doc/01_quick_start.qbk create mode 100644 libs/optional/doc/10_motivation.qbk create mode 100644 libs/optional/doc/11_development.qbk create mode 100644 libs/optional/doc/12_when_to_use.qbk create mode 100644 libs/optional/doc/13_relational_operators.qbk create mode 100644 libs/optional/doc/14_monadic_interface.qbk create mode 100644 libs/optional/doc/15_io.qbk create mode 100644 libs/optional/doc/16_optional_references.qbk create mode 100644 libs/optional/doc/17_in_place_factories.qbk create mode 100644 libs/optional/doc/18_gotchas.qbk create mode 100644 libs/optional/doc/19_exception_safety.qbk create mode 100644 libs/optional/doc/1A_type_requirements.qbk create mode 100644 libs/optional/doc/1B_on_performance.qbk create mode 100644 libs/optional/doc/21_ref_none.qbk create mode 100644 libs/optional/doc/22_ref_bad_optional_access.qbk create mode 100644 libs/optional/doc/23_ref_optional_io.qbk create mode 100644 libs/optional/doc/24_ref_optional_fwd.qbk create mode 100644 libs/optional/doc/27_ref_optional_synopsis.qbk create mode 100644 libs/optional/doc/28_ref_optional_semantics.qbk create mode 100644 libs/optional/doc/29_ref_optional_convenience.qbk create mode 100644 libs/optional/doc/90_dependencies.qbk create mode 100644 libs/optional/doc/91_relnotes.qbk create mode 100644 libs/optional/doc/92_acknowledgments.qbk create mode 100644 libs/optional/doc/Jamfile.v2 create mode 100644 libs/optional/doc/html/boost_optional/a_note_about_optional_bool_.html create mode 100644 libs/optional/doc/html/boost_optional/acknowledgements.html create mode 100644 libs/optional/doc/html/boost_optional/acknowledgments.html create mode 100644 libs/optional/doc/html/boost_optional/dependencies_and_portability.html create mode 100644 libs/optional/doc/html/boost_optional/dependencies_and_portability/emplace_operations_in_older_compilers.html create mode 100644 libs/optional/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html create mode 100644 libs/optional/doc/html/boost_optional/detailed_semantics.html create mode 100644 libs/optional/doc/html/boost_optional/development.html create mode 100644 libs/optional/doc/html/boost_optional/discussion.html create mode 100644 libs/optional/doc/html/boost_optional/examples.html create mode 100644 libs/optional/doc/html/boost_optional/exception_safety_guarantees.html create mode 100644 libs/optional/doc/html/boost_optional/implementation_notes.html create mode 100644 libs/optional/doc/html/boost_optional/in_place_factories.html create mode 100644 libs/optional/doc/html/boost_optional/motivation.html create mode 100644 libs/optional/doc/html/boost_optional/optional_references.html create mode 100644 libs/optional/doc/html/boost_optional/quick_start.html create mode 100644 libs/optional/doc/html/boost_optional/quick_start/bypassing_unnecessary_default_construction.html create mode 100644 libs/optional/doc/html/boost_optional/quick_start/optional_automatic_variables.html create mode 100644 libs/optional/doc/html/boost_optional/quick_start/optional_data_members.html create mode 100644 libs/optional/doc/html/boost_optional/quick_start/optional_return_values.html create mode 100644 libs/optional/doc/html/boost_optional/quick_start/storage_in_containers.html create mode 100644 libs/optional/doc/html/boost_optional/rebinding_semantics_for_assignment_of_optional_references.html create mode 100644 libs/optional/doc/html/boost_optional/reference/acknowledgements.html create mode 100644 libs/optional/doc/html/boost_optional/reference/dependencies_and_portability.html create mode 100644 libs/optional/doc/html/boost_optional/reference/dependencies_and_portability/optional_reference_binding.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_bad_optional_access_hpp_.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_bad_optional_access_hpp_/detailed_semantics.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_hpp_.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_fwd_hpp_.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____free_functions.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____optional_references.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____optional_values.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___free_functions.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_references.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header__boost_optional_hpp_.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_in_place_init.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_refs.html create mode 100644 libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html create mode 100644 libs/optional/doc/html/boost_optional/reference/io_header.html create mode 100644 libs/optional/doc/html/boost_optional/reference/io_header/io_semantics.html create mode 100644 libs/optional/doc/html/boost_optional/reference/relnotes.html create mode 100644 libs/optional/doc/html/boost_optional/relnotes.html create mode 100644 libs/optional/doc/html/boost_optional/synopsis.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/a_note_about_optional_bool_.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/design_overview.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/design_overview/the_interface.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/design_overview/the_semantics.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/exception_safety_guarantees.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/gotchas.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/gotchas/false_positive_with__wmaybe_uninitialized.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/gotchas/mixed_relational_comparisons.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/gotchas/moved_from__optional_.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/in_place_factories.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/io_operators.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/motivation.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/optional_references.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/optional_references/rebinding_semantics_for_assignment_of_optional_references.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/performance_considerations.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/rebinding_semantics_for_assignment_of_optional_references.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/relational_operators.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/type_requirements.html create mode 100644 libs/optional/doc/html/boost_optional/tutorial/when_to_use_optional.html create mode 100644 libs/optional/doc/html/boost_optional/type_requirements.html create mode 100644 libs/optional/doc/html/images/callouts/R.png create mode 100644 libs/optional/doc/html/images/opt_align1.png create mode 100644 libs/optional/doc/html/images/opt_align2.png create mode 100644 libs/optional/doc/html/images/opt_align3.png create mode 100644 libs/optional/doc/html/images/opt_align4.png create mode 100644 libs/optional/doc/html/images/space.png create mode 100644 libs/optional/doc/html/index.html create mode 100644 libs/optional/doc/html/optional/reference.html create mode 100644 libs/optional/doc/html/optional/reference/header__boost_optional_optional_hpp_.html create mode 100644 libs/optional/doc/html/optional/tutorial.html create mode 100644 libs/optional/doc/images/opt_align1.png create mode 100644 libs/optional/doc/images/opt_align2.png create mode 100644 libs/optional/doc/images/opt_align3.png create mode 100644 libs/optional/doc/images/opt_align4.png create mode 100644 libs/optional/include/boost/none.hpp create mode 100644 libs/optional/include/boost/none_t.hpp create mode 100644 libs/optional/include/boost/optional.hpp create mode 100644 libs/optional/include/boost/optional/bad_optional_access.hpp create mode 100644 libs/optional/include/boost/optional/detail/experimental_traits.hpp create mode 100644 libs/optional/include/boost/optional/detail/old_optional_implementation.hpp create mode 100644 libs/optional/include/boost/optional/detail/optional_aligned_storage.hpp create mode 100644 libs/optional/include/boost/optional/detail/optional_config.hpp create mode 100644 libs/optional/include/boost/optional/detail/optional_factory_support.hpp create mode 100644 libs/optional/include/boost/optional/detail/optional_hash.hpp create mode 100644 libs/optional/include/boost/optional/detail/optional_reference_spec.hpp create mode 100644 libs/optional/include/boost/optional/detail/optional_relops.hpp create mode 100644 libs/optional/include/boost/optional/detail/optional_swap.hpp create mode 100644 libs/optional/include/boost/optional/detail/optional_trivially_copyable_base.hpp create mode 100644 libs/optional/include/boost/optional/optional.hpp create mode 100644 libs/optional/include/boost/optional/optional_fwd.hpp create mode 100644 libs/optional/include/boost/optional/optional_io.hpp create mode 100644 libs/optional/index.html create mode 100644 libs/optional/meta/libraries.json create mode 100644 libs/optional/test/Jamfile.v2 create mode 100644 libs/optional/test/optional_ref_assign_test_defs.hpp create mode 100644 libs/optional/test/optional_test.cpp create mode 100644 libs/optional/test/optional_test_assign.cpp create mode 100644 libs/optional/test/optional_test_common.hpp create mode 100644 libs/optional/test/optional_test_constructible_from_other.cpp create mode 100644 libs/optional/test/optional_test_conversions_from_U.cpp create mode 100644 libs/optional/test/optional_test_convert_assign.cpp create mode 100644 libs/optional/test/optional_test_convert_from_T.cpp create mode 100644 libs/optional/test/optional_test_deleted_default_ctor.cpp create mode 100644 libs/optional/test/optional_test_emplace.cpp create mode 100644 libs/optional/test/optional_test_empty_braces.cpp create mode 100644 libs/optional/test/optional_test_equals_none.cpp create mode 100644 libs/optional/test/optional_test_experimental_traits.cpp create mode 100644 libs/optional/test/optional_test_fail1.cpp create mode 100644 libs/optional/test/optional_test_fail2.cpp create mode 100644 libs/optional/test/optional_test_fail3.cpp create mode 100644 libs/optional/test/optional_test_fail3a.cpp create mode 100644 libs/optional/test/optional_test_fail3b.cpp create mode 100644 libs/optional/test/optional_test_fail_const_swap.cpp create mode 100644 libs/optional/test/optional_test_fail_convert_assign_of_enums.cpp create mode 100644 libs/optional/test/optional_test_fail_convert_from_null.cpp create mode 100644 libs/optional/test/optional_test_fail_copying_a_moveable_type.cpp create mode 100644 libs/optional/test/optional_test_fail_explicit_convert_in_value_or.cpp create mode 100644 libs/optional/test/optional_test_fail_explicit_convert_in_value_or_call.cpp create mode 100644 libs/optional/test/optional_test_fail_implicit_bool_convert.cpp create mode 100644 libs/optional/test/optional_test_fail_io_without_io.cpp create mode 100644 libs/optional/test/optional_test_fail_none_io_without_io.cpp create mode 100644 libs/optional/test/optional_test_fail_optional_rvalue_ref.cpp create mode 100644 libs/optional/test/optional_test_flat_map.cpp create mode 100644 libs/optional/test/optional_test_hash.cpp create mode 100644 libs/optional/test/optional_test_inplace_factory.cpp create mode 100644 libs/optional/test/optional_test_inplace_fail.cpp create mode 100644 libs/optional/test/optional_test_inplace_fail2.cpp create mode 100644 libs/optional/test/optional_test_io.cpp create mode 100644 libs/optional/test/optional_test_make_optional.cpp create mode 100644 libs/optional/test/optional_test_map.cpp create mode 100644 libs/optional/test/optional_test_maybe_uninitialized_warning.cpp create mode 100644 libs/optional/test/optional_test_member_T.cpp create mode 100644 libs/optional/test/optional_test_minimum_requirements.cpp create mode 100644 libs/optional/test/optional_test_move.cpp create mode 100644 libs/optional/test/optional_test_msvc_bug_workaround.cpp create mode 100644 libs/optional/test/optional_test_noexcept_move.cpp create mode 100644 libs/optional/test/optional_test_old_impl.cpp create mode 100644 libs/optional/test/optional_test_path_assignment.cpp create mode 100644 libs/optional/test/optional_test_ref_assign_const_int.cpp create mode 100644 libs/optional/test/optional_test_ref_assign_mutable_int.cpp create mode 100644 libs/optional/test/optional_test_ref_assign_portable_minimum.cpp create mode 100644 libs/optional/test/optional_test_ref_convert_assign_const_int.cpp create mode 100644 libs/optional/test/optional_test_ref_convert_assign_const_int_prevented.cpp create mode 100644 libs/optional/test/optional_test_ref_convert_assign_mutable_int.cpp create mode 100644 libs/optional/test/optional_test_ref_convert_assign_non_int.cpp create mode 100644 libs/optional/test/optional_test_ref_converting_ctor.cpp create mode 100644 libs/optional/test/optional_test_ref_fail1.cpp create mode 100644 libs/optional/test/optional_test_ref_fail3.cpp create mode 100644 libs/optional/test/optional_test_ref_fail4.cpp create mode 100644 libs/optional/test/optional_test_ref_fail_assign_from_Trefref.cpp create mode 100644 libs/optional/test/optional_test_ref_fail_assign_from_Urefref.cpp create mode 100644 libs/optional/test/optional_test_ref_fail_init_from_Trefref.cpp create mode 100644 libs/optional/test/optional_test_ref_fail_init_from_Urefref.cpp create mode 100644 libs/optional/test/optional_test_ref_move.cpp create mode 100644 libs/optional/test/optional_test_ref_portable_minimum.cpp create mode 100644 libs/optional/test/optional_test_ref_to_val.cpp create mode 100644 libs/optional/test/optional_test_sfinae_friendly_ctor.cpp create mode 100644 libs/optional/test/optional_test_static_properties.cpp create mode 100644 libs/optional/test/optional_test_swap.cpp create mode 100644 libs/optional/test/optional_test_tc_base.cpp create mode 100644 libs/optional/test/optional_test_tie.cpp create mode 100644 libs/optional/test/optional_test_value_access.cpp create mode 100644 libs/optional/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp create mode 100644 libs/optional/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp create mode 100644 libs/optional/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp create mode 100644 libs/optional/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp create mode 100644 libs/optional/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp create mode 100644 libs/optional/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp create mode 100644 libs/optional/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp create mode 100644 libs/optional/test/testable_classes.hpp create mode 100644 libs/range/.gitattributes create mode 100644 libs/range/.travis.yml create mode 100644 libs/range/CMakeLists.txt create mode 100644 libs/range/doc/Jamfile.v2 create mode 100644 libs/range/doc/boost_range.qbk create mode 100644 libs/range/doc/concepts.qbk create mode 100644 libs/range/doc/example.cpp create mode 100644 libs/range/doc/examples.qbk create mode 100644 libs/range/doc/faq.qbk create mode 100644 libs/range/doc/headers.qbk create mode 100644 libs/range/doc/history_ack.qbk create mode 100644 libs/range/doc/introduction.qbk create mode 100644 libs/range/doc/mfc_atl.qbk create mode 100644 libs/range/doc/mfc_atl.rst create mode 100644 libs/range/doc/portability.qbk create mode 100644 libs/range/doc/reference.qbk create mode 100644 libs/range/doc/reference/adaptors.qbk create mode 100644 libs/range/doc/reference/adaptors/adjacent_filtered.qbk create mode 100644 libs/range/doc/reference/adaptors/copied.qbk create mode 100644 libs/range/doc/reference/adaptors/examples/indirected.cpp create mode 100644 libs/range/doc/reference/adaptors/filtered.qbk create mode 100644 libs/range/doc/reference/adaptors/formatted.qbk create mode 100644 libs/range/doc/reference/adaptors/indexed.qbk create mode 100644 libs/range/doc/reference/adaptors/indirected.qbk create mode 100644 libs/range/doc/reference/adaptors/map_keys.qbk create mode 100644 libs/range/doc/reference/adaptors/map_values.qbk create mode 100644 libs/range/doc/reference/adaptors/ref_unwrapped.qbk create mode 100644 libs/range/doc/reference/adaptors/replaced.qbk create mode 100644 libs/range/doc/reference/adaptors/replaced_if.qbk create mode 100644 libs/range/doc/reference/adaptors/reversed.qbk create mode 100644 libs/range/doc/reference/adaptors/sliced.qbk create mode 100644 libs/range/doc/reference/adaptors/strided.qbk create mode 100644 libs/range/doc/reference/adaptors/tokenized.qbk create mode 100644 libs/range/doc/reference/adaptors/transformed.qbk create mode 100644 libs/range/doc/reference/adaptors/type_erased.qbk create mode 100644 libs/range/doc/reference/adaptors/uniqued.qbk create mode 100644 libs/range/doc/reference/algorithm/adjacent_find.qbk create mode 100644 libs/range/doc/reference/algorithm/binary_search.qbk create mode 100644 libs/range/doc/reference/algorithm/copy.qbk create mode 100644 libs/range/doc/reference/algorithm/copy_backward.qbk create mode 100644 libs/range/doc/reference/algorithm/count.qbk create mode 100644 libs/range/doc/reference/algorithm/count_if.qbk create mode 100644 libs/range/doc/reference/algorithm/equal.qbk create mode 100644 libs/range/doc/reference/algorithm/equal_range.qbk create mode 100644 libs/range/doc/reference/algorithm/fill.qbk create mode 100644 libs/range/doc/reference/algorithm/fill_n.qbk create mode 100644 libs/range/doc/reference/algorithm/find.qbk create mode 100644 libs/range/doc/reference/algorithm/find_end.qbk create mode 100644 libs/range/doc/reference/algorithm/find_first_of.qbk create mode 100644 libs/range/doc/reference/algorithm/find_if.qbk create mode 100644 libs/range/doc/reference/algorithm/for_each.qbk create mode 100644 libs/range/doc/reference/algorithm/generate.qbk create mode 100644 libs/range/doc/reference/algorithm/includes.qbk create mode 100644 libs/range/doc/reference/algorithm/inplace_merge.qbk create mode 100644 libs/range/doc/reference/algorithm/lexicographical_compare.qbk create mode 100644 libs/range/doc/reference/algorithm/lower_bound.qbk create mode 100644 libs/range/doc/reference/algorithm/make_heap.qbk create mode 100644 libs/range/doc/reference/algorithm/max_element.qbk create mode 100644 libs/range/doc/reference/algorithm/merge.qbk create mode 100644 libs/range/doc/reference/algorithm/min_element.qbk create mode 100644 libs/range/doc/reference/algorithm/mismatch.qbk create mode 100644 libs/range/doc/reference/algorithm/next_permutation.qbk create mode 100644 libs/range/doc/reference/algorithm/nth_element.qbk create mode 100644 libs/range/doc/reference/algorithm/partial_sort.qbk create mode 100644 libs/range/doc/reference/algorithm/partition.qbk create mode 100644 libs/range/doc/reference/algorithm/pop_heap.qbk create mode 100644 libs/range/doc/reference/algorithm/prev_permutation.qbk create mode 100644 libs/range/doc/reference/algorithm/push_heap.qbk create mode 100644 libs/range/doc/reference/algorithm/random_shuffle.qbk create mode 100644 libs/range/doc/reference/algorithm/remove.qbk create mode 100644 libs/range/doc/reference/algorithm/remove_copy.qbk create mode 100644 libs/range/doc/reference/algorithm/remove_copy_if.qbk create mode 100644 libs/range/doc/reference/algorithm/remove_if.qbk create mode 100644 libs/range/doc/reference/algorithm/replace.qbk create mode 100644 libs/range/doc/reference/algorithm/replace_copy.qbk create mode 100644 libs/range/doc/reference/algorithm/replace_copy_if.qbk create mode 100644 libs/range/doc/reference/algorithm/replace_if.qbk create mode 100644 libs/range/doc/reference/algorithm/reverse.qbk create mode 100644 libs/range/doc/reference/algorithm/reverse_copy.qbk create mode 100644 libs/range/doc/reference/algorithm/rotate.qbk create mode 100644 libs/range/doc/reference/algorithm/rotate_copy.qbk create mode 100644 libs/range/doc/reference/algorithm/search.qbk create mode 100644 libs/range/doc/reference/algorithm/search_n.qbk create mode 100644 libs/range/doc/reference/algorithm/set_difference.qbk create mode 100644 libs/range/doc/reference/algorithm/set_intersection.qbk create mode 100644 libs/range/doc/reference/algorithm/set_symmetric_difference.qbk create mode 100644 libs/range/doc/reference/algorithm/set_union.qbk create mode 100644 libs/range/doc/reference/algorithm/sort.qbk create mode 100644 libs/range/doc/reference/algorithm/sort_heap.qbk create mode 100644 libs/range/doc/reference/algorithm/stable_partition.qbk create mode 100644 libs/range/doc/reference/algorithm/stable_sort.qbk create mode 100644 libs/range/doc/reference/algorithm/swap_ranges.qbk create mode 100644 libs/range/doc/reference/algorithm/transform.qbk create mode 100644 libs/range/doc/reference/algorithm/unique.qbk create mode 100644 libs/range/doc/reference/algorithm/unique_copy.qbk create mode 100644 libs/range/doc/reference/algorithm/upper_bound.qbk create mode 100644 libs/range/doc/reference/algorithm_ext/copy_n.qbk create mode 100644 libs/range/doc/reference/algorithm_ext/erase.qbk create mode 100644 libs/range/doc/reference/algorithm_ext/for_each.qbk create mode 100644 libs/range/doc/reference/algorithm_ext/insert.qbk create mode 100644 libs/range/doc/reference/algorithm_ext/iota.qbk create mode 100644 libs/range/doc/reference/algorithm_ext/is_sorted.qbk create mode 100644 libs/range/doc/reference/algorithm_ext/overwrite.qbk create mode 100644 libs/range/doc/reference/algorithm_ext/push_back.qbk create mode 100644 libs/range/doc/reference/algorithm_ext/push_front.qbk create mode 100644 libs/range/doc/reference/algorithm_ext/remove_erase.qbk create mode 100644 libs/range/doc/reference/algorithm_ext/remove_erase_if.qbk create mode 100644 libs/range/doc/reference/algorithms.qbk create mode 100644 libs/range/doc/reference/extending.qbk create mode 100644 libs/range/doc/reference/numeric/accumulate.qbk create mode 100644 libs/range/doc/reference/numeric/adjacent_difference.qbk create mode 100644 libs/range/doc/reference/numeric/inner_product.qbk create mode 100644 libs/range/doc/reference/numeric/partial_sum.qbk create mode 100644 libs/range/doc/reference/overview.qbk create mode 100644 libs/range/doc/reference/ranges.qbk create mode 100644 libs/range/doc/reference/ranges/any_range.qbk create mode 100644 libs/range/doc/reference/ranges/counting_range.qbk create mode 100644 libs/range/doc/reference/ranges/irange.qbk create mode 100644 libs/range/doc/reference/ranges/istream_range.qbk create mode 100644 libs/range/doc/reference/semantics.qbk create mode 100644 libs/range/doc/reference/synopsis.qbk create mode 100644 libs/range/doc/reference/utilities.qbk create mode 100644 libs/range/doc/style.qbk create mode 100644 libs/range/doc/upgrade.qbk create mode 100644 libs/range/include/boost/range.hpp create mode 100644 libs/range/include/boost/range/adaptor/adjacent_filtered.hpp create mode 100644 libs/range/include/boost/range/adaptor/argument_fwd.hpp create mode 100644 libs/range/include/boost/range/adaptor/copied.hpp create mode 100644 libs/range/include/boost/range/adaptor/define_adaptor.hpp create mode 100644 libs/range/include/boost/range/adaptor/filtered.hpp create mode 100644 libs/range/include/boost/range/adaptor/formatted.hpp create mode 100644 libs/range/include/boost/range/adaptor/indexed.hpp create mode 100644 libs/range/include/boost/range/adaptor/indirected.hpp create mode 100644 libs/range/include/boost/range/adaptor/map.hpp create mode 100644 libs/range/include/boost/range/adaptor/ref_unwrapped.hpp create mode 100644 libs/range/include/boost/range/adaptor/replaced.hpp create mode 100644 libs/range/include/boost/range/adaptor/replaced_if.hpp create mode 100644 libs/range/include/boost/range/adaptor/reversed.hpp create mode 100644 libs/range/include/boost/range/adaptor/sliced.hpp create mode 100644 libs/range/include/boost/range/adaptor/strided.hpp create mode 100644 libs/range/include/boost/range/adaptor/tokenized.hpp create mode 100644 libs/range/include/boost/range/adaptor/transformed.hpp create mode 100644 libs/range/include/boost/range/adaptor/type_erased.hpp create mode 100644 libs/range/include/boost/range/adaptor/uniqued.hpp create mode 100644 libs/range/include/boost/range/adaptors.hpp create mode 100644 libs/range/include/boost/range/algorithm.hpp create mode 100644 libs/range/include/boost/range/algorithm/adjacent_find.hpp create mode 100644 libs/range/include/boost/range/algorithm/binary_search.hpp create mode 100644 libs/range/include/boost/range/algorithm/copy.hpp create mode 100644 libs/range/include/boost/range/algorithm/copy_backward.hpp create mode 100644 libs/range/include/boost/range/algorithm/count.hpp create mode 100644 libs/range/include/boost/range/algorithm/count_if.hpp create mode 100644 libs/range/include/boost/range/algorithm/equal.hpp create mode 100644 libs/range/include/boost/range/algorithm/equal_range.hpp create mode 100644 libs/range/include/boost/range/algorithm/fill.hpp create mode 100644 libs/range/include/boost/range/algorithm/fill_n.hpp create mode 100644 libs/range/include/boost/range/algorithm/find.hpp create mode 100644 libs/range/include/boost/range/algorithm/find_end.hpp create mode 100644 libs/range/include/boost/range/algorithm/find_first_of.hpp create mode 100644 libs/range/include/boost/range/algorithm/find_if.hpp create mode 100644 libs/range/include/boost/range/algorithm/for_each.hpp create mode 100644 libs/range/include/boost/range/algorithm/generate.hpp create mode 100644 libs/range/include/boost/range/algorithm/heap_algorithm.hpp create mode 100644 libs/range/include/boost/range/algorithm/inplace_merge.hpp create mode 100644 libs/range/include/boost/range/algorithm/lexicographical_compare.hpp create mode 100644 libs/range/include/boost/range/algorithm/lower_bound.hpp create mode 100644 libs/range/include/boost/range/algorithm/max_element.hpp create mode 100644 libs/range/include/boost/range/algorithm/merge.hpp create mode 100644 libs/range/include/boost/range/algorithm/min_element.hpp create mode 100644 libs/range/include/boost/range/algorithm/mismatch.hpp create mode 100644 libs/range/include/boost/range/algorithm/nth_element.hpp create mode 100644 libs/range/include/boost/range/algorithm/partial_sort.hpp create mode 100644 libs/range/include/boost/range/algorithm/partial_sort_copy.hpp create mode 100644 libs/range/include/boost/range/algorithm/partition.hpp create mode 100644 libs/range/include/boost/range/algorithm/permutation.hpp create mode 100644 libs/range/include/boost/range/algorithm/random_shuffle.hpp create mode 100644 libs/range/include/boost/range/algorithm/remove.hpp create mode 100644 libs/range/include/boost/range/algorithm/remove_copy.hpp create mode 100644 libs/range/include/boost/range/algorithm/remove_copy_if.hpp create mode 100644 libs/range/include/boost/range/algorithm/remove_if.hpp create mode 100644 libs/range/include/boost/range/algorithm/replace.hpp create mode 100644 libs/range/include/boost/range/algorithm/replace_copy.hpp create mode 100644 libs/range/include/boost/range/algorithm/replace_copy_if.hpp create mode 100644 libs/range/include/boost/range/algorithm/replace_if.hpp create mode 100644 libs/range/include/boost/range/algorithm/reverse.hpp create mode 100644 libs/range/include/boost/range/algorithm/reverse_copy.hpp create mode 100644 libs/range/include/boost/range/algorithm/rotate.hpp create mode 100644 libs/range/include/boost/range/algorithm/rotate_copy.hpp create mode 100644 libs/range/include/boost/range/algorithm/search.hpp create mode 100644 libs/range/include/boost/range/algorithm/search_n.hpp create mode 100644 libs/range/include/boost/range/algorithm/set_algorithm.hpp create mode 100644 libs/range/include/boost/range/algorithm/sort.hpp create mode 100644 libs/range/include/boost/range/algorithm/stable_partition.hpp create mode 100644 libs/range/include/boost/range/algorithm/stable_sort.hpp create mode 100644 libs/range/include/boost/range/algorithm/swap_ranges.hpp create mode 100644 libs/range/include/boost/range/algorithm/transform.hpp create mode 100644 libs/range/include/boost/range/algorithm/unique.hpp create mode 100644 libs/range/include/boost/range/algorithm/unique_copy.hpp create mode 100644 libs/range/include/boost/range/algorithm/upper_bound.hpp create mode 100644 libs/range/include/boost/range/algorithm_ext.hpp create mode 100644 libs/range/include/boost/range/algorithm_ext/copy_n.hpp create mode 100644 libs/range/include/boost/range/algorithm_ext/erase.hpp create mode 100644 libs/range/include/boost/range/algorithm_ext/for_each.hpp create mode 100644 libs/range/include/boost/range/algorithm_ext/insert.hpp create mode 100644 libs/range/include/boost/range/algorithm_ext/iota.hpp create mode 100644 libs/range/include/boost/range/algorithm_ext/is_sorted.hpp create mode 100644 libs/range/include/boost/range/algorithm_ext/overwrite.hpp create mode 100644 libs/range/include/boost/range/algorithm_ext/push_back.hpp create mode 100644 libs/range/include/boost/range/algorithm_ext/push_front.hpp create mode 100644 libs/range/include/boost/range/any_range.hpp create mode 100644 libs/range/include/boost/range/as_array.hpp create mode 100644 libs/range/include/boost/range/as_literal.hpp create mode 100644 libs/range/include/boost/range/atl.hpp create mode 100644 libs/range/include/boost/range/begin.hpp create mode 100644 libs/range/include/boost/range/category.hpp create mode 100644 libs/range/include/boost/range/combine.hpp create mode 100644 libs/range/include/boost/range/concepts.hpp create mode 100644 libs/range/include/boost/range/config.hpp create mode 100644 libs/range/include/boost/range/const_iterator.hpp create mode 100644 libs/range/include/boost/range/const_reverse_iterator.hpp create mode 100644 libs/range/include/boost/range/counting_range.hpp create mode 100644 libs/range/include/boost/range/detail/any_iterator.hpp create mode 100644 libs/range/include/boost/range/detail/any_iterator_buffer.hpp create mode 100644 libs/range/include/boost/range/detail/any_iterator_interface.hpp create mode 100644 libs/range/include/boost/range/detail/any_iterator_wrapper.hpp create mode 100644 libs/range/include/boost/range/detail/collection_traits.hpp create mode 100644 libs/range/include/boost/range/detail/collection_traits_detail.hpp create mode 100644 libs/range/include/boost/range/detail/combine_cxx03.hpp create mode 100644 libs/range/include/boost/range/detail/combine_cxx11.hpp create mode 100644 libs/range/include/boost/range/detail/combine_no_rvalue.hpp create mode 100644 libs/range/include/boost/range/detail/combine_rvalue.hpp create mode 100644 libs/range/include/boost/range/detail/common.hpp create mode 100644 libs/range/include/boost/range/detail/default_constructible_unary_fn.hpp create mode 100644 libs/range/include/boost/range/detail/demote_iterator_traversal_tag.hpp create mode 100644 libs/range/include/boost/range/detail/difference_type.hpp create mode 100644 libs/range/include/boost/range/detail/empty.hpp create mode 100644 libs/range/include/boost/range/detail/extract_optional_type.hpp create mode 100644 libs/range/include/boost/range/detail/has_member_size.hpp create mode 100644 libs/range/include/boost/range/detail/implementation_help.hpp create mode 100644 libs/range/include/boost/range/detail/join_iterator.hpp create mode 100644 libs/range/include/boost/range/detail/less.hpp create mode 100644 libs/range/include/boost/range/detail/microsoft.hpp create mode 100644 libs/range/include/boost/range/detail/misc_concept.hpp create mode 100644 libs/range/include/boost/range/detail/msvc_has_iterator_workaround.hpp create mode 100644 libs/range/include/boost/range/detail/range_return.hpp create mode 100644 libs/range/include/boost/range/detail/safe_bool.hpp create mode 100644 libs/range/include/boost/range/detail/sfinae.hpp create mode 100644 libs/range/include/boost/range/detail/sizer.hpp create mode 100644 libs/range/include/boost/range/detail/str_types.hpp create mode 100644 libs/range/include/boost/range/difference_type.hpp create mode 100644 libs/range/include/boost/range/distance.hpp create mode 100644 libs/range/include/boost/range/empty.hpp create mode 100644 libs/range/include/boost/range/end.hpp create mode 100644 libs/range/include/boost/range/functions.hpp create mode 100644 libs/range/include/boost/range/has_range_iterator.hpp create mode 100644 libs/range/include/boost/range/irange.hpp create mode 100644 libs/range/include/boost/range/istream_range.hpp create mode 100644 libs/range/include/boost/range/iterator.hpp create mode 100644 libs/range/include/boost/range/iterator_range.hpp create mode 100644 libs/range/include/boost/range/iterator_range_core.hpp create mode 100644 libs/range/include/boost/range/iterator_range_hash.hpp create mode 100644 libs/range/include/boost/range/iterator_range_io.hpp create mode 100644 libs/range/include/boost/range/join.hpp create mode 100644 libs/range/include/boost/range/metafunctions.hpp create mode 100644 libs/range/include/boost/range/mfc.hpp create mode 100644 libs/range/include/boost/range/mfc_map.hpp create mode 100644 libs/range/include/boost/range/mutable_iterator.hpp create mode 100644 libs/range/include/boost/range/numeric.hpp create mode 100644 libs/range/include/boost/range/pointer.hpp create mode 100644 libs/range/include/boost/range/range_fwd.hpp create mode 100644 libs/range/include/boost/range/rbegin.hpp create mode 100644 libs/range/include/boost/range/reference.hpp create mode 100644 libs/range/include/boost/range/rend.hpp create mode 100644 libs/range/include/boost/range/result_iterator.hpp create mode 100644 libs/range/include/boost/range/reverse_iterator.hpp create mode 100644 libs/range/include/boost/range/reverse_result_iterator.hpp create mode 100644 libs/range/include/boost/range/size.hpp create mode 100644 libs/range/include/boost/range/size_type.hpp create mode 100644 libs/range/include/boost/range/sub_range.hpp create mode 100644 libs/range/include/boost/range/traversal.hpp create mode 100644 libs/range/include/boost/range/value_type.hpp create mode 100644 libs/range/index.html create mode 100644 libs/range/meta/libraries.json create mode 100644 libs/range/test/Jamfile.v2 create mode 100644 libs/range/test/adaptor_test/adjacent_filtered.cpp create mode 100644 libs/range/test/adaptor_test/adjacent_filtered_example.cpp create mode 100644 libs/range/test/adaptor_test/chained.cpp create mode 100644 libs/range/test/adaptor_test/copied.cpp create mode 100644 libs/range/test/adaptor_test/copied_example.cpp create mode 100644 libs/range/test/adaptor_test/filtered.cpp create mode 100644 libs/range/test/adaptor_test/filtered_example.cpp create mode 100644 libs/range/test/adaptor_test/formatted.cpp create mode 100644 libs/range/test/adaptor_test/formatted_example.cpp create mode 100644 libs/range/test/adaptor_test/indexed.cpp create mode 100644 libs/range/test/adaptor_test/indexed_example.cpp create mode 100644 libs/range/test/adaptor_test/indirected.cpp create mode 100644 libs/range/test/adaptor_test/indirected_example.cpp create mode 100644 libs/range/test/adaptor_test/map.cpp create mode 100644 libs/range/test/adaptor_test/map_keys_example.cpp create mode 100644 libs/range/test/adaptor_test/map_values_example.cpp create mode 100644 libs/range/test/adaptor_test/ref_unwrapped.cpp create mode 100644 libs/range/test/adaptor_test/ref_unwrapped_example.cpp create mode 100644 libs/range/test/adaptor_test/replaced.cpp create mode 100644 libs/range/test/adaptor_test/replaced_example.cpp create mode 100644 libs/range/test/adaptor_test/replaced_if.cpp create mode 100644 libs/range/test/adaptor_test/replaced_if_example.cpp create mode 100644 libs/range/test/adaptor_test/reversed.cpp create mode 100644 libs/range/test/adaptor_test/reversed_example.cpp create mode 100644 libs/range/test/adaptor_test/sliced.cpp create mode 100644 libs/range/test/adaptor_test/sliced_example.cpp create mode 100644 libs/range/test/adaptor_test/strided.cpp create mode 100644 libs/range/test/adaptor_test/strided2.cpp create mode 100644 libs/range/test/adaptor_test/strided_example.cpp create mode 100644 libs/range/test/adaptor_test/ticket_6742_transformed_c4789_warning.cpp create mode 100644 libs/range/test/adaptor_test/ticket_8676_sliced_transformed.cpp create mode 100644 libs/range/test/adaptor_test/ticket_9519_strided_reversed.cpp create mode 100644 libs/range/test/adaptor_test/tokenized.cpp create mode 100644 libs/range/test/adaptor_test/tokenized_example.cpp create mode 100644 libs/range/test/adaptor_test/transformed.cpp create mode 100644 libs/range/test/adaptor_test/transformed_example.cpp create mode 100644 libs/range/test/adaptor_test/type_erased.cpp create mode 100644 libs/range/test/adaptor_test/type_erased_abstract.cpp create mode 100644 libs/range/test/adaptor_test/type_erased_bidirectional.cpp create mode 100644 libs/range/test/adaptor_test/type_erased_brackets.cpp create mode 100644 libs/range/test/adaptor_test/type_erased_example.cpp create mode 100644 libs/range/test/adaptor_test/type_erased_forward.cpp create mode 100644 libs/range/test/adaptor_test/type_erased_mix_values.cpp create mode 100644 libs/range/test/adaptor_test/type_erased_random_access.cpp create mode 100644 libs/range/test/adaptor_test/type_erased_single_pass.cpp create mode 100644 libs/range/test/adaptor_test/type_erased_test.hpp create mode 100644 libs/range/test/adaptor_test/type_erased_tparam_conv.cpp create mode 100644 libs/range/test/adaptor_test/type_erased_transformed.cpp create mode 100644 libs/range/test/adaptor_test/uniqued.cpp create mode 100644 libs/range/test/adaptor_test/uniqued_example.cpp create mode 100644 libs/range/test/adaptors.cpp create mode 100644 libs/range/test/adl_conformance.cpp create mode 100644 libs/range/test/adl_conformance_no_using.cpp create mode 100644 libs/range/test/algorithm.cpp create mode 100644 libs/range/test/algorithm_example.cpp create mode 100644 libs/range/test/algorithm_ext_test/copy_n.cpp create mode 100644 libs/range/test/algorithm_ext_test/erase.cpp create mode 100644 libs/range/test/algorithm_ext_test/for_each_ext.cpp create mode 100644 libs/range/test/algorithm_ext_test/insert.cpp create mode 100644 libs/range/test/algorithm_ext_test/iota.cpp create mode 100644 libs/range/test/algorithm_ext_test/is_sorted.cpp create mode 100644 libs/range/test/algorithm_ext_test/overwrite.cpp create mode 100644 libs/range/test/algorithm_ext_test/push_back.cpp create mode 100644 libs/range/test/algorithm_ext_test/push_front.cpp create mode 100644 libs/range/test/algorithm_test/adjacent_find.cpp create mode 100644 libs/range/test/algorithm_test/binary_search.cpp create mode 100644 libs/range/test/algorithm_test/copy.cpp create mode 100644 libs/range/test/algorithm_test/copy_backward.cpp create mode 100644 libs/range/test/algorithm_test/copy_n.cpp create mode 100644 libs/range/test/algorithm_test/count.cpp create mode 100644 libs/range/test/algorithm_test/count_if.cpp create mode 100644 libs/range/test/algorithm_test/equal.cpp create mode 100644 libs/range/test/algorithm_test/equal_range.cpp create mode 100644 libs/range/test/algorithm_test/fill.cpp create mode 100644 libs/range/test/algorithm_test/find.cpp create mode 100644 libs/range/test/algorithm_test/find_end.cpp create mode 100644 libs/range/test/algorithm_test/find_first_of.cpp create mode 100644 libs/range/test/algorithm_test/find_if.cpp create mode 100644 libs/range/test/algorithm_test/for_each.cpp create mode 100644 libs/range/test/algorithm_test/generate.cpp create mode 100644 libs/range/test/algorithm_test/heap.cpp create mode 100644 libs/range/test/algorithm_test/includes.cpp create mode 100644 libs/range/test/algorithm_test/inplace_merge.cpp create mode 100644 libs/range/test/algorithm_test/lexicographical_compare.cpp create mode 100644 libs/range/test/algorithm_test/lower_bound.cpp create mode 100644 libs/range/test/algorithm_test/max_element.cpp create mode 100644 libs/range/test/algorithm_test/merge.cpp create mode 100644 libs/range/test/algorithm_test/min_element.cpp create mode 100644 libs/range/test/algorithm_test/mismatch.cpp create mode 100644 libs/range/test/algorithm_test/next_permutation.cpp create mode 100644 libs/range/test/algorithm_test/nth_element.cpp create mode 100644 libs/range/test/algorithm_test/partial_sort.cpp create mode 100644 libs/range/test/algorithm_test/partition.cpp create mode 100644 libs/range/test/algorithm_test/prev_permutation.cpp create mode 100644 libs/range/test/algorithm_test/random_shuffle.cpp create mode 100644 libs/range/test/algorithm_test/remove.cpp create mode 100644 libs/range/test/algorithm_test/remove_copy.cpp create mode 100644 libs/range/test/algorithm_test/remove_copy_if.cpp create mode 100644 libs/range/test/algorithm_test/remove_if.cpp create mode 100644 libs/range/test/algorithm_test/replace.cpp create mode 100644 libs/range/test/algorithm_test/replace_copy.cpp create mode 100644 libs/range/test/algorithm_test/replace_copy_if.cpp create mode 100644 libs/range/test/algorithm_test/replace_if.cpp create mode 100644 libs/range/test/algorithm_test/reverse.cpp create mode 100644 libs/range/test/algorithm_test/reverse_copy.cpp create mode 100644 libs/range/test/algorithm_test/rotate.cpp create mode 100644 libs/range/test/algorithm_test/rotate_copy.cpp create mode 100644 libs/range/test/algorithm_test/search.cpp create mode 100644 libs/range/test/algorithm_test/search_n.cpp create mode 100644 libs/range/test/algorithm_test/set_difference.cpp create mode 100644 libs/range/test/algorithm_test/set_intersection.cpp create mode 100644 libs/range/test/algorithm_test/set_symmetric_difference.cpp create mode 100644 libs/range/test/algorithm_test/set_union.cpp create mode 100644 libs/range/test/algorithm_test/sort.cpp create mode 100644 libs/range/test/algorithm_test/stable_partition.cpp create mode 100644 libs/range/test/algorithm_test/stable_sort.cpp create mode 100644 libs/range/test/algorithm_test/swap_ranges.cpp create mode 100644 libs/range/test/algorithm_test/transform.cpp create mode 100644 libs/range/test/algorithm_test/unique.cpp create mode 100644 libs/range/test/algorithm_test/unique_copy.cpp create mode 100644 libs/range/test/algorithm_test/upper_bound.cpp create mode 100644 libs/range/test/array.cpp create mode 100644 libs/range/test/atl.cpp create mode 100644 libs/range/test/begin.cpp create mode 100644 libs/range/test/category.cpp create mode 100644 libs/range/test/combine.cpp create mode 100644 libs/range/test/compat2.cpp create mode 100644 libs/range/test/compat3.cpp create mode 100644 libs/range/test/compile_fail/adaptor/adjacent_filtered_concept.cpp create mode 100644 libs/range/test/compile_fail/adaptor/adjacent_filtered_concept2.cpp create mode 100644 libs/range/test/compile_fail/adaptor/adjacent_filtered_concept3.cpp create mode 100644 libs/range/test/compile_fail/adaptor/adjacent_filtered_concept4.cpp create mode 100644 libs/range/test/compile_fail/adaptor/copied_concept.cpp create mode 100644 libs/range/test/compile_fail/adaptor/copied_concept2.cpp create mode 100644 libs/range/test/compile_fail/adaptor/copied_concept3.cpp create mode 100644 libs/range/test/compile_fail/adaptor/copied_concept4.cpp create mode 100644 libs/range/test/compile_fail/adaptor/mock_iterator.hpp create mode 100644 libs/range/test/compile_fail/adaptor/mock_range.hpp create mode 100644 libs/range/test/compile_fail/adaptor/reversed_concept.cpp create mode 100644 libs/range/test/compile_fail/adaptor/reversed_concept2.cpp create mode 100644 libs/range/test/compile_fail/adaptor/reversed_concept3.cpp create mode 100644 libs/range/test/compile_fail/adaptor/reversed_concept4.cpp create mode 100644 libs/range/test/compile_fail/adaptor/sliced_concept.cpp create mode 100644 libs/range/test/compile_fail/adaptor/sliced_concept2.cpp create mode 100644 libs/range/test/compile_fail/adaptor/sliced_concept3.cpp create mode 100644 libs/range/test/compile_fail/adaptor/sliced_concept4.cpp create mode 100644 libs/range/test/compile_fail/adaptor/uniqued_concept.cpp create mode 100644 libs/range/test/compile_fail/adaptor/uniqued_concept2.cpp create mode 100644 libs/range/test/compile_fail/adaptor/uniqued_concept3.cpp create mode 100644 libs/range/test/compile_fail/adaptor/uniqued_concept4.cpp create mode 100644 libs/range/test/compile_fail/iterator_range1.cpp create mode 100644 libs/range/test/const_iterator.cpp create mode 100644 libs/range/test/const_ranges.cpp create mode 100644 libs/range/test/const_reverse_iterator.cpp create mode 100644 libs/range/test/counting_range.cpp create mode 100644 libs/range/test/difference_type.cpp create mode 100644 libs/range/test/end.cpp create mode 100644 libs/range/test/extension_mechanism.cpp create mode 100644 libs/range/test/extension_size.cpp create mode 100644 libs/range/test/has_range_iterator.cpp create mode 100644 libs/range/test/irange.cpp create mode 100644 libs/range/test/istream_range.cpp create mode 100644 libs/range/test/iterator.cpp create mode 100644 libs/range/test/iterator_ext.cpp create mode 100644 libs/range/test/iterator_pair.cpp create mode 100644 libs/range/test/iterator_range.cpp create mode 100644 libs/range/test/iterator_range_drop.cpp create mode 100644 libs/range/test/iterator_range_equality_bug.cpp create mode 100644 libs/range/test/iterator_range_hash.cpp create mode 100644 libs/range/test/iterator_range_variant.cpp create mode 100644 libs/range/test/join.cpp create mode 100644 libs/range/test/mfc.cpp create mode 100644 libs/range/test/mutable_iterator.cpp create mode 100644 libs/range/test/partial_workaround.cpp create mode 100644 libs/range/test/pointer.cpp create mode 100644 libs/range/test/pointer_as_iterator.cpp create mode 100644 libs/range/test/reference.cpp create mode 100644 libs/range/test/result_iterator.cpp create mode 100644 libs/range/test/reverse_iterator.cpp create mode 100644 libs/range/test/reverse_result_iterator.cpp create mode 100644 libs/range/test/reversible_range.cpp create mode 100644 libs/range/test/size_type.cpp create mode 100644 libs/range/test/std_container.cpp create mode 100644 libs/range/test/string.cpp create mode 100644 libs/range/test/sub_range.cpp create mode 100644 libs/range/test/test_driver/range_overload_test_driver.hpp create mode 100644 libs/range/test/test_driver/range_return_test_driver.hpp create mode 100644 libs/range/test/test_function/check_equal_fn.hpp create mode 100644 libs/range/test/test_function/counted_function.hpp create mode 100644 libs/range/test/test_function/equal_to_x.hpp create mode 100644 libs/range/test/test_function/false_predicate.hpp create mode 100644 libs/range/test/test_function/greater_than_x.hpp create mode 100644 libs/range/test/test_function/multiply_by_x.hpp create mode 100644 libs/range/test/test_function/true_predicate.hpp create mode 100644 libs/range/test/test_utils.hpp create mode 100644 libs/range/test/ticket_10336.cpp create mode 100644 libs/range/test/ticket_5486.cpp create mode 100644 libs/range/test/ticket_5544_terminate_irange.cpp create mode 100644 libs/range/test/ticket_5547.cpp create mode 100644 libs/range/test/ticket_5556_is_sorted_namespace.cpp create mode 100644 libs/range/test/ticket_5811_indirected_optional.cpp create mode 100644 libs/range/test/ticket_6715_iterator_range_equality.cpp create mode 100644 libs/range/test/ticket_6944.cpp create mode 100644 libs/range/test/value_type.cpp create mode 100644 libs/regex/build/Jamfile.v2 create mode 100644 libs/regex/build/has_icu_test.cpp create mode 100644 libs/regex/build/is_legacy_03.cpp create mode 100644 libs/regex/src/internals.hpp create mode 100644 libs/regex/src/posix_api.cpp create mode 100644 libs/regex/src/regex.cpp create mode 100644 libs/regex/src/regex_debug.cpp create mode 100644 libs/regex/src/static_mutex.cpp create mode 100644 libs/regex/src/wide_posix_api.cpp create mode 100644 libs/regex/test/config_info/regex_config_info.cpp create mode 100644 libs/tuple/.gitattributes create mode 100644 libs/tuple/.github/workflows/ci.yml create mode 100644 libs/tuple/.travis.yml create mode 100644 libs/tuple/CMakeLists.txt create mode 100644 libs/tuple/doc/Jamfile.v2 create mode 100644 libs/tuple/doc/design_decisions_rationale.qbk create mode 100644 libs/tuple/doc/tuple_advanced_interface.qbk create mode 100644 libs/tuple/doc/tuple_users_guide.qbk create mode 100644 libs/tuple/include/boost/tuple/detail/tuple_basic.hpp create mode 100644 libs/tuple/include/boost/tuple/tuple.hpp create mode 100644 libs/tuple/include/boost/tuple/tuple_comparison.hpp create mode 100644 libs/tuple/include/boost/tuple/tuple_io.hpp create mode 100644 libs/tuple/index.html create mode 100644 libs/tuple/meta/libraries.json create mode 100644 libs/tuple/test/CMakeLists.txt create mode 100644 libs/tuple/test/Jamfile create mode 100644 libs/tuple/test/README create mode 100644 libs/tuple/test/another_tuple_test_bench.cpp create mode 100644 libs/tuple/test/cmake_install_test/CMakeLists.txt create mode 100644 libs/tuple/test/cmake_install_test/main.cpp create mode 100644 libs/tuple/test/cmake_subdir_test/CMakeLists.txt create mode 100644 libs/tuple/test/io_test.cpp create mode 100644 libs/tuple/test/quick.cpp create mode 100644 libs/tuple/test/std_tuple_element.cpp create mode 100644 libs/tuple/test/std_tuple_size.cpp create mode 100644 libs/tuple/test/structured_bindings.cpp create mode 100644 libs/tuple/test/tuple_test_bench.cpp create mode 100644 libs/type_traits/test/check_type.hpp create mode 100644 libs/type_traits/test/test.hpp create mode 100644 libs/utility/.gitattributes create mode 100644 libs/utility/.github/workflows/ci.yml create mode 100644 libs/utility/Assignable.html create mode 100644 libs/utility/CMakeLists.txt create mode 100644 libs/utility/Collection.html create mode 100644 libs/utility/CopyConstructible.html create mode 100644 libs/utility/LessThanComparable.html create mode 100644 libs/utility/MultiPassInputIterator.html create mode 100644 libs/utility/OptionalPointee.html create mode 100644 libs/utility/README.md create mode 100644 libs/utility/appveyor.yml create mode 100644 libs/utility/call_traits.htm create mode 100644 libs/utility/checked_delete.html create mode 100644 libs/utility/compressed_pair.htm create mode 100644 libs/utility/doc/BOOST_BINARY.qbk create mode 100644 libs/utility/doc/Jamfile.v2 create mode 100644 libs/utility/doc/base_from_member.qbk create mode 100644 libs/utility/doc/call_traits.qbk create mode 100644 libs/utility/doc/compressed_pair.qbk create mode 100644 libs/utility/doc/in_place_factory.qbk create mode 100644 libs/utility/doc/logo.png create mode 100644 libs/utility/doc/logo.svg create mode 100644 libs/utility/doc/main.qbk create mode 100644 libs/utility/doc/operators.qbk create mode 100644 libs/utility/doc/other.qbk create mode 100644 libs/utility/doc/overview.qbk create mode 100644 libs/utility/doc/quickref.xml create mode 100644 libs/utility/doc/result_of.qbk create mode 100644 libs/utility/doc/string_view.qbk create mode 100644 libs/utility/doc/utilities.qbk create mode 100644 libs/utility/doc/value_init.qbk create mode 100644 libs/utility/enable_if.html create mode 100644 libs/utility/identity_type/doc/Jamfile.v2 create mode 100644 libs/utility/identity_type/doc/html/index.html create mode 100644 libs/utility/identity_type/doc/identity_type.qbk create mode 100644 libs/utility/identity_type/index.html create mode 100644 libs/utility/identity_type/test/Jamfile.v2 create mode 100644 libs/utility/identity_type/test/abstract.cpp create mode 100644 libs/utility/identity_type/test/noncopyable.cpp create mode 100644 libs/utility/identity_type/test/paren.cpp create mode 100644 libs/utility/identity_type/test/template.cpp create mode 100644 libs/utility/identity_type/test/var.cpp create mode 100644 libs/utility/identity_type/test/var_error.cpp create mode 100644 libs/utility/in_place_factories.html create mode 100644 libs/utility/include/boost/call_traits.hpp create mode 100644 libs/utility/include/boost/compressed_pair.hpp create mode 100644 libs/utility/include/boost/detail/call_traits.hpp create mode 100644 libs/utility/include/boost/detail/compressed_pair.hpp create mode 100644 libs/utility/include/boost/detail/ob_compressed_pair.hpp create mode 100644 libs/utility/include/boost/operators.hpp create mode 100644 libs/utility/include/boost/operators_v1.hpp create mode 100644 libs/utility/include/boost/utility.hpp create mode 100644 libs/utility/include/boost/utility/base_from_member.hpp create mode 100644 libs/utility/include/boost/utility/binary.hpp create mode 100644 libs/utility/include/boost/utility/compare_pointees.hpp create mode 100644 libs/utility/include/boost/utility/detail/in_place_factory_prefix.hpp create mode 100644 libs/utility/include/boost/utility/detail/in_place_factory_suffix.hpp create mode 100644 libs/utility/include/boost/utility/detail/minstd_rand.hpp create mode 100644 libs/utility/include/boost/utility/detail/result_of_iterate.hpp create mode 100644 libs/utility/include/boost/utility/detail/result_of_variadic.hpp create mode 100644 libs/utility/include/boost/utility/identity_type.hpp create mode 100644 libs/utility/include/boost/utility/in_place_factory.hpp create mode 100644 libs/utility/include/boost/utility/result_of.hpp create mode 100644 libs/utility/include/boost/utility/string_ref.hpp create mode 100644 libs/utility/include/boost/utility/string_ref_fwd.hpp create mode 100644 libs/utility/include/boost/utility/string_view.hpp create mode 100644 libs/utility/include/boost/utility/string_view_fwd.hpp create mode 100644 libs/utility/include/boost/utility/typed_in_place_factory.hpp create mode 100644 libs/utility/include/boost/utility/value_init.hpp create mode 100644 libs/utility/index.html create mode 100644 libs/utility/iterator_adaptors.htm create mode 100644 libs/utility/meta/libraries.json create mode 100644 libs/utility/operators.htm create mode 100644 libs/utility/sublibs create mode 100644 libs/utility/test/Jamfile.v2 create mode 100644 libs/utility/test/base_from_member_ref_test.cpp create mode 100644 libs/utility/test/base_from_member_test.cpp create mode 100644 libs/utility/test/binary_test.cpp create mode 100644 libs/utility/test/call_traits_test.cpp create mode 100644 libs/utility/test/compressed_pair_final_test.cpp create mode 100644 libs/utility/test/compressed_pair_test.cpp create mode 100644 libs/utility/test/initialized_test.cpp create mode 100644 libs/utility/test/initialized_test_fail1.cpp create mode 100644 libs/utility/test/initialized_test_fail2.cpp create mode 100644 libs/utility/test/iterators_test.cpp create mode 100644 libs/utility/test/operators_constexpr_test.cpp create mode 100644 libs/utility/test/operators_test.cpp create mode 100644 libs/utility/test/result_of_test.cpp create mode 100644 libs/utility/test/string_ref_from_rvalue.cpp create mode 100644 libs/utility/test/string_ref_test1.cpp create mode 100644 libs/utility/test/string_ref_test2.cpp create mode 100644 libs/utility/test/string_ref_test_io.cpp create mode 100644 libs/utility/test/string_view_constexpr_test1.cpp create mode 100644 libs/utility/test/string_view_from_rvalue.cpp create mode 100644 libs/utility/test/string_view_test1.cpp create mode 100644 libs/utility/test/string_view_test2.cpp create mode 100644 libs/utility/test/string_view_test_io.cpp create mode 100644 libs/utility/test/value_init_test.cpp create mode 100644 libs/utility/test/value_init_test2.cpp create mode 100644 libs/utility/test/value_init_test3.cpp create mode 100644 libs/utility/test/value_init_test_fail1.cpp create mode 100644 libs/utility/test/value_init_test_fail2.cpp create mode 100644 libs/utility/test/value_init_test_fail3.cpp create mode 100644 libs/utility/test/value_init_workaround_test.cpp create mode 100644 libs/utility/throw_exception.html create mode 100644 libs/utility/utility.htm create mode 100644 libs/utility/value_init.htm create mode 100644 rst.css diff --git a/CMakeLists.txt b/CMakeLists.txt index 68fe4624..156b9159 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,9 @@ add_library(boost INTERFACE) target_include_directories(boost SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/libs/align/include/) +target_include_directories(boost SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/libs/range/include/) +target_include_directories(boost SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/libs/optional/include/) +target_include_directories(boost SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/libs/utility/include/) +target_include_directories(boost SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/libs/tuple/include/) +target_include_directories(boost SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/libs/iterator/include/) target_include_directories(boost SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) add_library(Boost::headers ALIAS boost) \ No newline at end of file diff --git a/boost.png b/boost.png new file mode 100644 index 0000000000000000000000000000000000000000..b4d51fcd5c9149fd77f5ca6ed2b6b1b70e8fe24f GIT binary patch literal 6308 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 +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +// container +#include +#include //new_allocator +#include +// container/detail +#include +#include +#include +#include +#include +#include +#include +#include +// move +#include +#include +#include +// move/detail +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +# include +#endif +#include +#include + +// intrusive +#include +#include +// other +#include +// std +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) +#include +#endif + +namespace boost { +namespace container { + +#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED +namespace dtl { + +template +struct list_hook +{ + typedef typename dtl::bi::make_list_base_hook + , dtl::bi::link_mode >::type type; +}; + +template +struct iiterator_node_value_type< base_node > > +{ + typedef T type; +}; + +template +struct intrusive_list_type +{ + typedef boost::container::allocator_traits allocator_traits_type; + typedef typename allocator_traits_type::value_type value_type; + typedef typename boost::intrusive::pointer_traits + ::template + rebind_pointer::type + void_pointer; + typedef base_node > node_type; + typedef typename dtl::bi::make_list + < node_type + , dtl::bi::base_hook::type> + , dtl::bi::constant_time_size + , dtl::bi::size_type + + >::type container_type; + typedef container_type type ; +}; + +} //namespace dtl { +#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + +//! A list is a doubly linked list. That is, it is a Sequence that supports both +//! forward and backward traversal, and (amortized) constant time insertion and +//! removal of elements at the beginning or the end, or in the middle. Lists have +//! the important property that insertion and splicing do not invalidate iterators +//! to list elements, and that even removal invalidates only the iterators that point +//! to the elements that are removed. The ordering of iterators may be changed +//! (that is, list::iterator might have a different predecessor or successor +//! after a list operation than it did before), but the iterators themselves will +//! not be invalidated or made to point to different elements unless that invalidation +//! or mutation is explicit. +//! +//! \tparam T The type of object that is stored in the list +//! \tparam Allocator The allocator used for all internal memory management, use void +//! for the default allocator +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template +#else +template +#endif +class list + : protected dtl::node_alloc_holder + < typename real_allocator::type + , typename dtl::intrusive_list_type::type>::type> +{ + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + typedef typename real_allocator::type ValueAllocator; + typedef typename + dtl::intrusive_list_type::type Icont; + typedef dtl::node_alloc_holder AllocHolder; + typedef typename AllocHolder::NodePtr NodePtr; + typedef typename AllocHolder::NodeAlloc NodeAlloc; + typedef typename AllocHolder::ValAlloc ValAlloc; + typedef typename AllocHolder::Node Node; + typedef dtl::allocator_node_destroyer Destroyer; + typedef typename AllocHolder::alloc_version alloc_version; + typedef boost::container::allocator_traits allocator_traits_type; + typedef boost::container::equal_to_value + equal_to_value_type; + + BOOST_COPYABLE_AND_MOVABLE(list) + + typedef dtl::iterator_from_iiterator iterator_impl; + typedef dtl::iterator_from_iiterator const_iterator_impl; + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + + public: + ////////////////////////////////////////////// + // + // types + // + ////////////////////////////////////////////// + + typedef T value_type; + typedef typename ::boost::container::allocator_traits::pointer pointer; + typedef typename ::boost::container::allocator_traits::const_pointer const_pointer; + typedef typename ::boost::container::allocator_traits::reference reference; + typedef typename ::boost::container::allocator_traits::const_reference const_reference; + typedef typename ::boost::container::allocator_traits::size_type size_type; + typedef typename ::boost::container::allocator_traits::difference_type difference_type; + typedef ValueAllocator allocator_type; + typedef BOOST_CONTAINER_IMPDEF(NodeAlloc) stored_allocator_type; + typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; + typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator; + typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator) reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator) const_reverse_iterator; + + ////////////////////////////////////////////// + // + // construct/copy/destroy + // + ////////////////////////////////////////////// + + //! Effects: Default constructs a list. + //! + //! Throws: If allocator_type's default constructor throws. + //! + //! Complexity: Constant. + list() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible::value) + : AllocHolder() + {} + + //! Effects: Constructs a list taking the allocator as parameter. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + explicit list(const allocator_type &a) BOOST_NOEXCEPT_OR_NOTHROW + : AllocHolder(a) + {} + + //! Effects: Constructs a list + //! and inserts n value-initialized value_types. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + explicit list(size_type n) + : AllocHolder(ValueAllocator()) + { this->resize(n); } + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + list(size_type n, const allocator_type &a) + : AllocHolder(a) + { this->resize(n); } + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + list(size_type n, const T& value, const ValueAllocator& a = ValueAllocator()) + : AllocHolder(a) + { this->insert(this->cbegin(), n, value); } + + //! Effects: Copy constructs a list. + //! + //! Postcondition: x == *this. + //! + //! Throws: If allocator_type's default constructor throws. + //! + //! Complexity: Linear to the elements x contains. + list(const list& x) + : AllocHolder(x) + { this->insert(this->cbegin(), x.begin(), x.end()); } + + //! Effects: Move constructor. Moves x's resources to *this. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + list(BOOST_RV_REF(list) x) BOOST_NOEXCEPT_OR_NOTHROW + : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x)) + {} + + //! Effects: Copy constructs a list using the specified allocator. + //! + //! Postcondition: x == *this. + //! + //! Throws: If allocator_type's default constructor or copy constructor throws. + //! + //! Complexity: Linear to the elements x contains. + list(const list& x, const allocator_type &a) + : AllocHolder(a) + { this->insert(this->cbegin(), x.begin(), x.end()); } + + //! Effects: Move constructor sing the specified allocator. + //! Moves x's resources to *this. + //! + //! Throws: If allocation or value_type's copy constructor throws. + //! + //! Complexity: Constant if a == x.get_allocator(), linear otherwise. + list(BOOST_RV_REF(list) x, const allocator_type &a) + : AllocHolder(a) + { + if(this->node_alloc() == x.node_alloc()){ + this->icont().swap(x.icont()); + } + else{ + this->insert(this->cbegin(), boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end())); + } + } + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts a copy of the range [first, last) in the list. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's constructor taking a dereferenced InIt throws. + //! + //! Complexity: Linear to the range [first, last). + template + list(InpIt first, InpIt last, const ValueAllocator &a = ValueAllocator()) + : AllocHolder(a) + { this->insert(this->cbegin(), first, last); } + + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts a copy of the range [il.begin(), il.end()) in the list. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's constructor taking a dereferenced + //! std::initializer_list iterator throws. + //! + //! Complexity: Linear to the range [il.begin(), il.end()). + list(std::initializer_list il, const ValueAllocator &a = ValueAllocator()) + : AllocHolder(a) + { this->insert(this->cbegin(), il.begin(), il.end()); } +#endif + + //! Effects: Destroys the list. All stored values are destroyed + //! and used memory is deallocated. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements. + BOOST_CONTAINER_FORCEINLINE ~list() BOOST_NOEXCEPT_OR_NOTHROW + {} //AllocHolder clears the list + + //! Effects: Makes *this contain the same elements as x. + //! + //! Postcondition: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to the number of elements in x. + list& operator=(BOOST_COPY_ASSIGN_REF(list) x) + { + if (BOOST_LIKELY(this != &x)) { + NodeAlloc &this_alloc = this->node_alloc(); + const NodeAlloc &x_alloc = x.node_alloc(); + dtl::bool_ flag; + if(flag && this_alloc != x_alloc){ + this->clear(); + } + this->AllocHolder::copy_assign_alloc(x); + this->assign(x.begin(), x.end()); + } + return *this; + } + + //! Effects: Move assignment. All x's values are transferred to *this. + //! + //! Postcondition: x.empty(). *this contains a the elements x had + //! before the function. + //! + //! Throws: If allocator_traits_type::propagate_on_container_move_assignment + //! is false and (allocation throws or value_type's move constructor throws) + //! + //! Complexity: Constant if allocator_traits_type:: + //! propagate_on_container_move_assignment is true or + //! this->get>allocator() == x.get_allocator(). Linear otherwise. + list& operator=(BOOST_RV_REF(list) x) + BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) + { + if (BOOST_LIKELY(this != &x)) { + NodeAlloc &this_alloc = this->node_alloc(); + NodeAlloc &x_alloc = x.node_alloc(); + const bool propagate_alloc = allocator_traits_type:: + propagate_on_container_move_assignment::value; + const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal; + //Resources can be transferred if both allocators are + //going to be equal after this function (either propagated or already equal) + if(propagate_alloc || allocators_equal){ + //Destroy + this->clear(); + //Move allocator if needed + this->AllocHolder::move_assign_alloc(x); + //Obtain resources + this->icont() = boost::move(x.icont()); + } + //Else do a one by one move + else{ + this->assign( boost::make_move_iterator(x.begin()) + , boost::make_move_iterator(x.end())); + } + } + return *this; + } + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! Effects: Makes *this contain the same elements as il. + //! + //! Postcondition: this->size() == il.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to the number of elements in x. + BOOST_CONTAINER_FORCEINLINE list& operator=(std::initializer_list il) + { + this->assign(il.begin(), il.end()); + return *this; + } +#endif + + //! Effects: Assigns the n copies of val to *this. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + BOOST_CONTAINER_FORCEINLINE void assign(size_type n, const T& val) + { + typedef constant_iterator cvalue_iterator; + return this->assign(cvalue_iterator(val, n), cvalue_iterator()); + } + + //! Effects: Assigns the range [first, last) to *this. + //! + //! Throws: If memory allocation throws or + //! T's constructor from dereferencing InpIt throws. + //! + //! Complexity: Linear to n. + template + void assign(InpIt first, InpIt last + #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + , typename dtl::disable_if_convertible::type * = 0 + #endif + ) + { + iterator first1 = this->begin(); + const iterator last1 = this->end(); + for ( ; first1 != last1 && first != last; ++first1, ++first) + *first1 = *first; + if (first == last) + this->erase(first1, last1); + else{ + this->insert(last1, first, last); + } + } + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! Effects: Assigns the range [il.begin(), il.end()) to *this. + //! + //! Throws: If memory allocation throws or + //! T's constructor from dereferencing std::initializer_list iterator throws. + //! + //! Complexity: Linear to n. + BOOST_CONTAINER_FORCEINLINE void assign(std::initializer_list il) + { this->assign(il.begin(), il.end()); } +#endif + + //! Effects: Returns a copy of the internal allocator. + //! + //! Throws: If allocator's copy constructor throws. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW + { return allocator_type(this->node_alloc()); } + + //! Effects: Returns a reference to the internal allocator. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Non-standard extension. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW + { return this->node_alloc(); } + + //! Effects: Returns a reference to the internal allocator. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Non-standard extension. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW + { return this->node_alloc(); } + + ////////////////////////////////////////////// + // + // iterators + // + ////////////////////////////////////////////// + + //! Effects: Returns an iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + iterator begin() BOOST_NOEXCEPT_OR_NOTHROW + { return iterator(this->icont().begin()); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW + { return this->cbegin(); } + + //! Effects: Returns an iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + iterator end() BOOST_NOEXCEPT_OR_NOTHROW + { return iterator(this->icont().end()); } + + //! Effects: Returns a const_iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW + { return this->cend(); } + + //! Effects: Returns a reverse_iterator pointing to the beginning + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW + { return reverse_iterator(end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW + { return this->crbegin(); } + + //! Effects: Returns a reverse_iterator pointing to the end + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW + { return reverse_iterator(begin()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW + { return this->crend(); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW + { return const_iterator(this->non_const_icont().begin()); } + + //! Effects: Returns a const_iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW + { return const_iterator(this->non_const_icont().end()); } + + //! Effects: Returns a const_reverse_iterator pointing to the beginning + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW + { return const_reverse_iterator(this->cend()); } + + //! Effects: Returns a const_reverse_iterator pointing to the end + //! of the reversed list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW + { return const_reverse_iterator(this->cbegin()); } + + ////////////////////////////////////////////// + // + // capacity + // + ////////////////////////////////////////////// + + //! Effects: Returns true if the list contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + bool empty() const BOOST_NOEXCEPT_OR_NOTHROW + { return !this->size(); } + + //! Effects: Returns the number of the elements contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + size_type size() const BOOST_NOEXCEPT_OR_NOTHROW + { return this->icont().size(); } + + //! Effects: Returns the largest possible size of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW + { return AllocHolder::max_size(); } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are value initialized. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size) + { + if(!priv_try_shrink(new_size)){ + typedef value_init_construct_iterator value_init_iterator; + this->insert(this->cend(), value_init_iterator(new_size - this->size()), value_init_iterator()); + } + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are copy constructed from x. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size, const T& x) + { + if(!priv_try_shrink(new_size)){ + this->insert(this->cend(), new_size - this->size(), x); + } + } + + ////////////////////////////////////////////// + // + // element access + // + ////////////////////////////////////////////// + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + reference front() BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(!this->empty()); + return *this->begin(); + } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(!this->empty()); + return *this->begin(); + } + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + reference back() BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(!this->empty()); + return *(--this->end()); + } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(!this->empty()); + return *(--this->end()); + } + + ////////////////////////////////////////////// + // + // modifiers + // + ////////////////////////////////////////////// + + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the end of the list. + //! + //! Returns: A reference to the created object. + //! + //! Throws: If memory allocation throws or + //! T's in-place constructor throws. + //! + //! Complexity: Constant + template + reference emplace_back(BOOST_FWD_REF(Args)... args) + { return *this->emplace(this->cend(), boost::forward(args)...); } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the beginning of the list. + //! + //! Returns: A reference to the created object. + //! + //! Throws: If memory allocation throws or + //! T's in-place constructor throws. + //! + //! Complexity: Constant + template + reference emplace_front(BOOST_FWD_REF(Args)... args) + { return *this->emplace(this->cbegin(), boost::forward(args)...); } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... before p. + //! + //! Throws: If memory allocation throws or + //! T's in-place constructor throws. + //! + //! Complexity: Constant + template + iterator emplace(const_iterator position, BOOST_FWD_REF(Args)... args) + { + BOOST_ASSERT((priv_is_linked)(position)); + NodePtr pnode(AllocHolder::create_node(boost::forward(args)...)); + return iterator(this->icont().insert(position.get(), *pnode)); + } + + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #define BOOST_CONTAINER_LIST_EMPLACE_CODE(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + reference emplace_back(BOOST_MOVE_UREF##N)\ + { return *this->emplace(this->cend() BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + reference emplace_front(BOOST_MOVE_UREF##N)\ + { return *this->emplace(this->cbegin() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);}\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace(const_iterator position BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + BOOST_ASSERT(position == this->cend() || (--(++position) == position) );\ + NodePtr pnode (AllocHolder::create_node(BOOST_MOVE_FWD##N));\ + return iterator(this->icont().insert(position.get(), *pnode));\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_LIST_EMPLACE_CODE) + #undef BOOST_CONTAINER_LIST_EMPLACE_CODE + + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! Effects: Inserts a copy of x at the beginning of the list. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + void push_front(const T &x); + + //! Effects: Constructs a new element in the beginning of the list + //! and moves the resources of x to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + void push_front(T &&x); + #else + BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front) + #endif + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! Effects: Inserts a copy of x at the end of the list. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + void push_back(const T &x); + + //! Effects: Constructs a new element in the end of the list + //! and moves the resources of x to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + void push_back(T &&x); + #else + BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back) + #endif + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a copy of x before p. + //! + //! Returns: an iterator to the inserted element. + //! + //! Throws: If memory allocation throws or x's copy constructor throws. + //! + //! Complexity: Amortized constant time. + iterator insert(const_iterator p, const T &x); + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a new element before p with x's resources. + //! + //! Returns: an iterator to the inserted element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + iterator insert(const_iterator p, T &&x); + #else + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator) + #endif + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Inserts n copies of x before p. + //! + //! Returns: an iterator to the first inserted element or p if n is 0. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + iterator insert(const_iterator position, size_type n, const T& x) + { + //range check is done by insert + typedef constant_iterator cvalue_iterator; + return this->insert(position, cvalue_iterator(x, n), cvalue_iterator()); + } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a copy of the [first, last) range before p. + //! + //! Returns: an iterator to the first inserted element or p if first == last. + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws. + //! + //! Complexity: Linear to distance [first, last). + template + iterator insert(const_iterator p, InpIt first, InpIt last + #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + , typename dtl::enable_if_c + < !dtl::is_convertible::value + && (dtl::is_input_iterator::value + || dtl::is_same::value + ) + >::type * = 0 + #endif + ) + { + BOOST_ASSERT((priv_is_linked)(p)); + const typename Icont::iterator ipos(p.get()); + iterator ret_it(ipos); + if(first != last){ + ret_it = iterator(this->icont().insert(ipos, *this->create_node_from_it(first))); + ++first; + } + for (; first != last; ++first){ + this->icont().insert(ipos, *this->create_node_from_it(first)); + } + return ret_it; + } + + #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + template + iterator insert(const_iterator position, FwdIt first, FwdIt last + , typename dtl::enable_if_c + < !dtl::is_convertible::value + && !(dtl::is_input_iterator::value + || dtl::is_same::value + ) + >::type * = 0 + ) + { + BOOST_ASSERT((priv_is_linked)(position)); + //Optimized allocation and construction + insertion_functor func(this->icont(), position.get()); + iterator before_p(position.get()); + --before_p; + this->allocate_many_and_construct(first, boost::container::iterator_udistance(first, last), func); + return ++before_p; + } + #endif + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a copy of the [il.begin(), il.end()) range before p. + //! + //! Returns: an iterator to the first inserted element or p if if.begin() == il.end(). + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced std::initializer_list iterator throws. + //! + //! Complexity: Linear to distance [il.begin(), il.end()). + iterator insert(const_iterator p, std::initializer_list il) + { + //position range check is done by insert() + return insert(p, il.begin(), il.end()); + } +#endif + + //! Effects: Removes the first element from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + void pop_front() BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(!this->empty()); + this->erase(this->cbegin()); + } + + //! Effects: Removes the last element from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + void pop_back() BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(!this->empty()); + const_iterator tmp = this->cend(); + this->erase(--tmp); + } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Erases the element at p. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(p != this->cend() && (priv_is_linked)(p)); + return iterator(this->icont().erase_and_dispose(p.get(), Destroyer(this->node_alloc()))); + } + + //! Requires: first and last must be valid iterator to elements in *this. + //! + //! Effects: Erases the elements pointed by [first, last). + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the distance between first and last. + iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(first == last || (first != this->cend() && (priv_is_linked)(first))); + BOOST_ASSERT(first == last || (priv_is_linked)(last)); + return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); + } + + //! Effects: Swaps the contents of *this and x. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + void swap(list& x) + BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) + { + BOOST_ASSERT(allocator_traits_type::propagate_on_container_swap::value || + allocator_traits_type::is_always_equal::value || + this->get_stored_allocator() == x.get_stored_allocator()); + AllocHolder::swap(x); + } + + //! Effects: Erases all the elements of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements in the list. + void clear() BOOST_NOEXCEPT_OR_NOTHROW + { AllocHolder::clear(alloc_version()); } + + ////////////////////////////////////////////// + // + // slist operations + // + ////////////////////////////////////////////// + + //! Requires: p must point to an element contained + //! by the list. x != *this. this' allocator and x's allocator shall compare equal + //! + //! Effects: Transfers all the elements of list x to this list, before the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of + //! this list. Iterators of this list and all the references are not invalidated. + void splice(const_iterator p, list& x) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT((priv_is_linked)(p)); + BOOST_ASSERT(this != &x); + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); + this->icont().splice(p.get(), x.icont()); + } + + //! Requires: p must point to an element contained + //! by the list. x != *this. this' allocator and x's allocator shall compare equal + //! + //! Effects: Transfers all the elements of list x to this list, before the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of + //! this list. Iterators of this list and all the references are not invalidated. + void splice(const_iterator p, BOOST_RV_REF(list) x) BOOST_NOEXCEPT_OR_NOTHROW + { + //Checks done in splice + this->splice(p, static_cast(x)); + } + + //! Requires: p must point to an element contained + //! by this list. i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal + //! + //! Effects: Transfers the value pointed by i, from list x to this list, + //! before the element pointed by p. No destructors or copy constructors are called. + //! If p == i or p == ++i, this function is a null operation. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(const_iterator p, list &x, const_iterator i) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT((priv_is_linked)(p)); + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); + this->icont().splice(p.get(), x.icont(), i.get()); + } + + //! Requires: p must point to an element contained + //! by this list. i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal. + //! + //! Effects: Transfers the value pointed by i, from list x to this list, + //! before the element pointed by p. No destructors or copy constructors are called. + //! If p == i or p == ++i, this function is a null operation. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(const_iterator p, BOOST_RV_REF(list) x, const_iterator i) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this != &x); + //Additional checks done in splice() + this->splice(p, static_cast(x), i); + } + + //! Requires: p must point to an element contained + //! by this list. first and last must point to elements contained in list x. + //! this' allocator and x's allocator shall compare equal + //! + //! Effects: Transfers the range pointed by first and last from list x to this list, + //! before the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing + //! + //! Complexity: Linear to the number of elements transferred. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(const_iterator p, list &x, const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT((priv_is_linked)(p)); + BOOST_ASSERT(first == last || (first != x.cend() && x.priv_is_linked(first))); + BOOST_ASSERT(first == last || x.priv_is_linked(last)); + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); + this->icont().splice(p.get(), x.icont(), first.get(), last.get()); + } + + //! Requires: p must point to an element contained + //! by this list. first and last must point to elements contained in list x. + //! this' allocator and x's allocator shall compare equal. + //! + //! Effects: Transfers the range pointed by first and last from list x to this list, + //! before the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing + //! + //! Complexity: Linear to the number of elements transferred. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(const_iterator p, BOOST_RV_REF(list) x, const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this != &x); + //Additional checks done in splice() + this->splice(p, static_cast(x), first, last); + } + + //! Requires: p must point to an element contained + //! by this list. first and last must point to elements contained in list x. + //! n == distance(first, last). this' allocator and x's allocator shall compare equal + //! + //! Effects: Transfers the range pointed by first and last from list x to this list, + //! before the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + //! + //! Note: Non-standard extension + void splice(const_iterator p, list &x, const_iterator first, const_iterator last, size_type n) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); + this->icont().splice(p.get(), x.icont(), first.get(), last.get(), n); + } + + //! Requires: p must point to an element contained + //! by this list. first and last must point to elements contained in list x. + //! n == distance(first, last). this' allocator and x's allocator shall compare equal + //! + //! Effects: Transfers the range pointed by first and last from list x to this list, + //! before the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + //! + //! Note: Non-standard extension + void splice(const_iterator p, BOOST_RV_REF(list) x, const_iterator first, const_iterator last, size_type n) BOOST_NOEXCEPT_OR_NOTHROW + { this->splice(p, static_cast(x), first, last, n); } + + //! Effects: Removes all the elements that compare equal to value. + //! + //! Throws: If comparison throws. + //! + //! Complexity: Linear time. It performs exactly size() comparisons for equality. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + void remove(const T& value) + { this->remove_if(equal_to_value_type(value)); } + + //! Effects: Removes all the elements for which a specified + //! predicate is satisfied. + //! + //! Throws: If pred throws. + //! + //! Complexity: Linear time. It performs exactly size() calls to the predicate. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void remove_if(Pred pred) + { + typedef value_to_node_compare value_to_node_compare_type; + this->icont().remove_and_dispose_if(value_to_node_compare_type(pred), Destroyer(this->node_alloc())); + } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that are equal from the list. + //! + //! Throws: If comparison throws. + //! + //! Complexity: Linear time (size()-1 comparisons equality comparisons). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + void unique() + { this->unique(value_equal_t()); } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that satisfy some binary predicate from the list. + //! + //! Throws: If pred throws. + //! + //! Complexity: Linear time (size()-1 comparisons calls to pred()). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void unique(BinaryPredicate binary_pred) + { + typedef value_to_node_compare value_to_node_compare_type; + this->icont().unique_and_dispose(value_to_node_compare_type(binary_pred), Destroyer(this->node_alloc())); + } + + //! Requires: The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this according to std::less. The merge is stable; + //! that is, if an element from *this is equivalent to one from x, then the element + //! from *this will precede the one from x. + //! + //! Throws: If comparison throws. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + void merge(list &x) + { this->merge(x, value_less_t()); } + + //! Requires: The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this according to std::less. The merge is stable; + //! that is, if an element from *this is equivalent to one from x, then the element + //! from *this will precede the one from x. + //! + //! Throws: If comparison throws. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + void merge(BOOST_RV_REF(list) x) + { this->merge(static_cast(x)); } + + //! Requires: p must be a comparison function that induces a strict weak + //! ordering and both *this and x must be sorted according to that ordering + //! The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this. The merge is stable; that is, if an element from *this is + //! equivalent to one from x, then the element from *this will precede the one from x. + //! + //! Throws: If comp throws. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references to *this are not invalidated. + template + void merge(list &x, const StrictWeakOrdering &comp) + { + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); + typedef value_to_node_compare value_to_node_compare_type; + this->icont().merge(x.icont(), value_to_node_compare_type(comp)); + } + + //! Requires: p must be a comparison function that induces a strict weak + //! ordering and both *this and x must be sorted according to that ordering + //! The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this. The merge is stable; that is, if an element from *this is + //! equivalent to one from x, then the element from *this will precede the one from x. + //! + //! Throws: If comp throws. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references to *this are not invalidated. + template + void merge(BOOST_RV_REF(list) x, StrictWeakOrdering comp) + { this->merge(static_cast(x), comp); } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: If comparison throws. + //! + //! Notes: Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + void sort() + { this->sort(value_less_t()); } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: If comp throws. + //! + //! Notes: Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + template + void sort(StrictWeakOrdering comp) + { + // nothing if the list has length 0 or 1. + if (this->size() < 2) + return; + typedef value_to_node_compare value_to_node_compare_type; + this->icont().sort(value_to_node_compare_type(comp)); + } + + //! Effects: Reverses the order of elements in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time. + //! + //! Note: Iterators and references are not invalidated + void reverse() BOOST_NOEXCEPT_OR_NOTHROW + { this->icont().reverse(); } + + //! Effects: Returns true if x and y are equal + //! + //! Complexity: Linear to the number of elements in the container. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + friend bool operator==(const list& x, const list& y) + { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); } + + //! Effects: Returns true if x and y are unequal + //! + //! Complexity: Linear to the number of elements in the container. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + friend bool operator!=(const list& x, const list& y) + { return !(x == y); } + + //! Effects: Returns true if x is less than y + //! + //! Complexity: Linear to the number of elements in the container. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + friend bool operator<(const list& x, const list& y) + { return boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + + //! Effects: Returns true if x is greater than y + //! + //! Complexity: Linear to the number of elements in the container. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + friend bool operator>(const list& x, const list& y) + { return y < x; } + + //! Effects: Returns true if x is equal or less than y + //! + //! Complexity: Linear to the number of elements in the container. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + friend bool operator<=(const list& x, const list& y) + { return !(y < x); } + + //! Effects: Returns true if x is equal or greater than y + //! + //! Complexity: Linear to the number of elements in the container. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + friend bool operator>=(const list& x, const list& y) + { return !(x < y); } + + //! Effects: x.swap(y) + //! + //! Complexity: Constant. + BOOST_CONTAINER_FORCEINLINE friend void swap(list& x, list& y) + BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y))) + { x.swap(y); } + + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + private: + + static bool priv_is_linked(const_iterator const position) + { + const_iterator cur(position); + //This list is circular including end nodes + return (--(++cur)) == position && (++(--cur)) == position; + } + + bool priv_try_shrink(size_type new_size) + { + const size_type len = this->size(); + if(len > new_size){ + const const_iterator iend = this->cend(); + size_type to_erase = len - new_size; + const_iterator ifirst; + if(to_erase < len/2u){ + ifirst = iend; + while(to_erase--){ + --ifirst; + } + } + else{ + ifirst = this->cbegin(); + size_type to_skip = len - to_erase; + while(to_skip--){ + ++ifirst; + } + } + this->erase(ifirst, iend); + return true; + } + else{ + return false; + } + } + + iterator priv_insert(const_iterator p, const T &x) + { + BOOST_ASSERT((priv_is_linked)(p)); + NodePtr tmp = AllocHolder::create_node(x); + return iterator(this->icont().insert(p.get(), *tmp)); + } + + iterator priv_insert(const_iterator p, BOOST_RV_REF(T) x) + { + BOOST_ASSERT((priv_is_linked)(p)); + NodePtr tmp = AllocHolder::create_node(boost::move(x)); + return iterator(this->icont().insert(p.get(), *tmp)); + } + + template + void priv_push_back(BOOST_FWD_REF(U) x) + { this->icont().push_back(*this->create_node(::boost::forward(x))); } + + template + void priv_push_front(BOOST_FWD_REF(U) x) + { this->icont().push_front(*this->create_node(::boost::forward(x))); } + + class insertion_functor; + friend class insertion_functor; + + class insertion_functor + { + Icont &icont_; + typedef typename Icont::const_iterator iconst_iterator; + const iconst_iterator pos_; + + public: + insertion_functor(Icont &icont, typename Icont::const_iterator pos) + : icont_(icont), pos_(pos) + {} + + void operator()(Node &n) + { + this->icont_.insert(pos_, n); + } + }; + + typedef value_less value_less_t; + typedef value_equal value_equal_t; + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + +}; + +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD +template +list(InputIterator, InputIterator) -> + list::value_type>; + +template +list(InputIterator, InputIterator, ValueAllocator const&) -> + list::value_type, ValueAllocator>; +#endif + +#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + +} //namespace container { + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + typedef typename boost::container::list::allocator_type allocator_type; + typedef typename ::boost::container::allocator_traits::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move::value && + ::boost::has_trivial_destructor_after_move::value; +}; + +namespace container { + +#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + +}} + +#include + +#endif // BOOST_CONTAINER_LIST_HPP diff --git a/boost/container/slist.hpp b/boost/container/slist.hpp new file mode 100644 index 00000000..b6601726 --- /dev/null +++ b/boost/container/slist.hpp @@ -0,0 +1,1724 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2015. 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) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_CONTAINER_SLIST_HPP +#define BOOST_CONTAINER_SLIST_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +// container +#include +#include //new_allocator +#include +// container/detail +#include //algo_equal(), algo_lexicographical_compare +#include +#include +#include +#include +#include +#include +#include +// intrusive +#include +#include +// move +#include +#include +#include +// move/detail +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include +#endif +#include +#include +// std +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) +#include +#endif + +namespace boost { +namespace container { + +#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + +template +class slist; + +namespace dtl { + +template +struct slist_hook +{ + typedef typename dtl::bi::make_slist_base_hook + , dtl::bi::link_mode >::type type; +}; + +template +struct iiterator_node_value_type< base_node > > +{ + typedef T type; +}; + +template +struct intrusive_slist_type +{ + typedef boost::container::allocator_traits allocator_traits_type; + typedef typename allocator_traits_type::value_type value_type; + typedef typename boost::intrusive::pointer_traits + ::template + rebind_pointer::type + void_pointer; + typedef base_node > node_type; + + typedef typename dtl::bi::make_slist + ::type> + ,dtl::bi::constant_time_size + , dtl::bi::size_type + + >::type container_type; + typedef container_type type ; +}; + +} //namespace dtl { + +#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + +//! An slist is a singly linked list: a list where each element is linked to the next +//! element, but not to the previous element. That is, it is a Sequence that +//! supports forward but not backward traversal, and (amortized) constant time +//! insertion and removal of elements. Slists, like lists, have the important +//! property that insertion and splicing do not invalidate iterators to list elements, +//! and that even removal invalidates only the iterators that point to the elements +//! that are removed. The ordering of iterators may be changed (that is, +//! slist::iterator might have a different predecessor or successor after a list +//! operation than it did before), but the iterators themselves will not be invalidated +//! or made to point to different elements unless that invalidation or mutation is explicit. +//! +//! The main difference between slist and list is that list's iterators are bidirectional +//! iterators, while slist's iterators are forward iterators. This means that slist is +//! less versatile than list; frequently, however, bidirectional iterators are +//! unnecessary. You should usually use slist unless you actually need the extra +//! functionality of list, because singly linked lists are smaller and faster than double +//! linked lists. +//! +//! Important performance note: like every other Sequence, slist defines the member +//! functions insert and erase. Using these member functions carelessly, however, can +//! result in disastrously slow programs. The problem is that insert's first argument is +//! an iterator p, and that it inserts the new element(s) before p. This means that +//! insert must find the iterator just before p; this is a constant-time operation +//! for list, since list has bidirectional iterators, but for slist it must find that +//! iterator by traversing the list from the beginning up to p. In other words: +//! insert and erase are slow operations anywhere but near the beginning of the slist. +//! +//! Slist provides the member functions insert_after and erase_after, which are constant +//! time operations: you should always use insert_after and erase_after whenever +//! possible. If you find that insert_after and erase_after aren't adequate for your +//! needs, and that you often need to use insert and erase in the middle of the list, +//! then you should probably use list instead of slist. +//! +//! \tparam T The type of object that is stored in the list +//! \tparam Allocator The allocator used for all internal memory management, use void +//! for the default allocator +#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED +template +#else +template +#endif +class slist + : protected dtl::node_alloc_holder + < typename real_allocator::type + , typename dtl::intrusive_slist_type::type>::type> +{ + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + typedef typename real_allocator::type ValueAllocator; + typedef typename + dtl::intrusive_slist_type::type Icont; + typedef dtl::node_alloc_holder AllocHolder; + typedef typename AllocHolder::NodePtr NodePtr; + typedef typename AllocHolder::NodeAlloc NodeAlloc; + typedef typename AllocHolder::ValAlloc ValAlloc; + typedef typename AllocHolder::Node Node; + typedef dtl::allocator_node_destroyer Destroyer; + typedef typename AllocHolder::alloc_version alloc_version; + typedef boost::container:: + allocator_traits allocator_traits_type; + typedef boost::container::equal_to_value + equal_to_value_type; + + BOOST_COPYABLE_AND_MOVABLE(slist) + typedef dtl::iterator_from_iiterator iterator_impl; + typedef dtl::iterator_from_iiterator const_iterator_impl; + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + + public: + ////////////////////////////////////////////// + // + // types + // + ////////////////////////////////////////////// + + typedef T value_type; + typedef typename ::boost::container::allocator_traits::pointer pointer; + typedef typename ::boost::container::allocator_traits::const_pointer const_pointer; + typedef typename ::boost::container::allocator_traits::reference reference; + typedef typename ::boost::container::allocator_traits::const_reference const_reference; + typedef typename ::boost::container::allocator_traits::size_type size_type; + typedef typename ::boost::container::allocator_traits::difference_type difference_type; + typedef ValueAllocator allocator_type; + typedef BOOST_CONTAINER_IMPDEF(NodeAlloc) stored_allocator_type; + typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; + typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator; + + public: + + ////////////////////////////////////////////// + // + // constructFr/copy/destroy + // + ////////////////////////////////////////////// + + //! Effects: Constructs a list taking the allocator as parameter. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + slist() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible::value) + : AllocHolder() + {} + + //! Effects: Constructs a list taking the allocator as parameter. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + explicit slist(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW + : AllocHolder(a) + {} + + //! Effects: Constructs a list + //! and inserts n value-initialized value_types. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + explicit slist(size_type n) + : AllocHolder(allocator_type()) + { this->resize(n); } + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + slist(size_type n, const allocator_type &a) + : AllocHolder(a) + { this->resize(n); } + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! Complexity: Linear to n. + explicit slist(size_type n, const value_type& x, const allocator_type& a = allocator_type()) + : AllocHolder(a) + { this->insert_after(this->cbefore_begin(), n, x); } + + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts a copy of the range [first, last) in the list. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's constructor taking a dereferenced InIt throws. + //! + //! Complexity: Linear to the range [first, last). + template + slist(InpIt first, InpIt last, const allocator_type& a = allocator_type()) + : AllocHolder(a) + { this->insert_after(this->cbefore_begin(), first, last); } + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! Effects: Constructs a list that will use a copy of allocator a + //! and inserts a copy of the range [il.begin(), il.end()) in the list. + //! + //! Throws: If allocator_type's default constructor + //! throws or T's constructor taking a dereferenced std::initializer_list iterator throws. + //! + //! Complexity: Linear to the range [il.begin(), il.end()). + slist(std::initializer_list il, const allocator_type& a = allocator_type()) + : AllocHolder(a) + { this->insert_after(this->cbefore_begin(), il.begin(), il.end()); } +#endif + + //! Effects: Copy constructs a list. + //! + //! Postcondition: x == *this. + //! + //! Throws: If allocator_type's default constructor + //! + //! Complexity: Linear to the elements x contains. + slist(const slist& x) + : AllocHolder(x) + { this->insert_after(this->cbefore_begin(), x.begin(), x.end()); } + + //! Effects: Move constructor. Moves x's resources to *this. + //! + //! Throws: If allocator_type's copy constructor throws. + //! + //! Complexity: Constant. + slist(BOOST_RV_REF(slist) x) BOOST_NOEXCEPT_OR_NOTHROW + : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x)) + {} + + //! Effects: Copy constructs a list using the specified allocator. + //! + //! Postcondition: x == *this. + //! + //! Throws: If allocator_type's default constructor + //! + //! Complexity: Linear to the elements x contains. + slist(const slist& x, const allocator_type &a) + : AllocHolder(a) + { this->insert_after(this->cbefore_begin(), x.begin(), x.end()); } + + //! Effects: Move constructor using the specified allocator. + //! Moves x's resources to *this. + //! + //! Throws: If allocation or value_type's copy constructor throws. + //! + //! Complexity: Constant if a == x.get_allocator(), linear otherwise. + slist(BOOST_RV_REF(slist) x, const allocator_type &a) + : AllocHolder(a) + { + slist & sr = x; + if(this->node_alloc() == sr.node_alloc()){ + this->icont().swap(sr.icont()); + } + else{ + this->insert_after(this->cbefore_begin(), boost::make_move_iterator(sr.begin()), boost::make_move_iterator(sr.end())); + } + } + + //! Effects: Destroys the list. All stored values are destroyed + //! and used memory is deallocated. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements. + ~slist() BOOST_NOEXCEPT_OR_NOTHROW + {} //AllocHolder clears the slist + + //! Effects: Makes *this contain the same elements as x. + //! + //! Postcondition: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to the number of elements in x. + slist& operator= (BOOST_COPY_ASSIGN_REF(slist) x) + { + if (BOOST_LIKELY(this != &x)) { + NodeAlloc &this_alloc = this->node_alloc(); + const NodeAlloc &x_alloc = x.node_alloc(); + dtl::bool_ flag; + if(flag && this_alloc != x_alloc){ + this->clear(); + } + this->AllocHolder::copy_assign_alloc(x); + this->assign(x.begin(), x.end()); + } + return *this; + } + + //! Effects: Makes *this contain the same elements as x. + //! + //! Postcondition: this->size() == x.size(). *this contains a copy + //! of each of x's elements. + //! + //! Throws: If allocator_traits_type::propagate_on_container_move_assignment + //! is false and (allocation throws or value_type's move constructor throws) + //! + //! Complexity: Constant if allocator_traits_type:: + //! propagate_on_container_move_assignment is true or + //! this->get>allocator() == x.get_allocator(). Linear otherwise. + slist& operator=(BOOST_RV_REF(slist) x) + BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) + { + slist & sr = x; + if (BOOST_LIKELY(this != &sr)) { + NodeAlloc &this_alloc = this->node_alloc(); + NodeAlloc &x_alloc = sr.node_alloc(); + const bool propagate_alloc = allocator_traits_type:: + propagate_on_container_move_assignment::value; + const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal; + //Resources can be transferred if both allocators are + //going to be equal after this function (either propagated or already equal) + if(propagate_alloc || allocators_equal){ + //Destroy + this->clear(); + //Move allocator if needed + this->AllocHolder::move_assign_alloc(sr); + //Obtain resources + this->icont() = boost::move(sr.icont()); + } + //Else do a one by one move + else{ + this->assign( boost::make_move_iterator(sr.begin()) + , boost::make_move_iterator(sr.end())); + } + } + return *this; + } + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! Effects: Makes *this contain the same elements as in il. + //! + //! Postcondition: this->size() == il.size(). *this contains a copy + //! of each of il's elements. + //! + //! Throws: If allocator_traits_type::propagate_on_container_move_assignment + //! is false and (allocation throws or value_type's move constructor throws) + slist& operator=(std::initializer_list il) + { + assign(il.begin(), il.end()); + return *this; + } +#endif + + //! Effects: Assigns the n copies of val to *this. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n. + void assign(size_type n, const T& val) + { + typedef constant_iterator cvalue_iterator; + return this->assign(cvalue_iterator(val, n), cvalue_iterator()); + } + + //! Effects: Assigns the range [first, last) to *this. + //! + //! Throws: If memory allocation throws or + //! T's constructor from dereferencing InpIt throws. + //! + //! Complexity: Linear to n. + template + void assign(InpIt first, InpIt last + #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + , typename dtl::disable_if_convertible::type * = 0 + #endif + ) + { + iterator end_n(this->end()); + iterator prev(this->before_begin()); + iterator node(this->begin()); + while (node != end_n && first != last){ + *node = *first; + prev = node; + ++node; + ++first; + } + if (first != last) + this->insert_after(prev, first, last); + else + this->erase_after(prev, end_n); + } + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! Effects: Assigns the range [il.begin(), il.end()) to *this. + //! + //! Throws: If memory allocation throws or + //! T's constructor from dereferencing std::initializer_list iterator throws. + //! + //! Complexity: Linear to range [il.begin(), il.end()). + + void assign(std::initializer_list il) + { + assign(il.begin(), il.end()); + } +#endif + //! Effects: Returns a copy of the internal allocator. + //! + //! Throws: If allocator's copy constructor throws. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW + { return allocator_type(this->node_alloc()); } + + //! Effects: Returns a reference to the internal allocator. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Non-standard extension. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW + { return this->node_alloc(); } + + //! Effects: Returns a reference to the internal allocator. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Non-standard extension. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW + { return this->node_alloc(); } + + ////////////////////////////////////////////// + // + // iterators + // + ////////////////////////////////////////////// + + //! Effects: Returns a non-dereferenceable iterator that, + //! when incremented, yields begin(). This iterator may be used + //! as the argument to insert_after, erase_after, etc. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + iterator before_begin() BOOST_NOEXCEPT_OR_NOTHROW + { return iterator(end()); } + + //! Effects: Returns a non-dereferenceable const_iterator + //! that, when incremented, yields begin(). This iterator may be used + //! as the argument to insert_after, erase_after, etc. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_iterator before_begin() const BOOST_NOEXCEPT_OR_NOTHROW + { return this->cbefore_begin(); } + + //! Effects: Returns an iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + iterator begin() BOOST_NOEXCEPT_OR_NOTHROW + { return iterator(this->icont().begin()); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW + { return this->cbegin(); } + + //! Effects: Returns an iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + iterator end() BOOST_NOEXCEPT_OR_NOTHROW + { return iterator(this->icont().end()); } + + //! Effects: Returns a const_iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW + { return this->cend(); } + + //! Effects: Returns a non-dereferenceable const_iterator + //! that, when incremented, yields begin(). This iterator may be used + //! as the argument to insert_after, erase_after, etc. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_iterator cbefore_begin() const BOOST_NOEXCEPT_OR_NOTHROW + { return const_iterator(end()); } + + //! Effects: Returns a const_iterator to the first element contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW + { return const_iterator(this->non_const_icont().begin()); } + + //! Effects: Returns a const_iterator to the end of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW + { return const_iterator(this->non_const_icont().end()); } + + //! Returns: The iterator to the element before i in the sequence. + //! Returns the end-iterator, if either i is the begin-iterator or the + //! sequence is empty. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before i. + //! + //! Note: Non-standard extension. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + iterator previous(iterator p) BOOST_NOEXCEPT_OR_NOTHROW + { return iterator(this->icont().previous(p.get())); } + + //! Returns: The const_iterator to the element before i in the sequence. + //! Returns the end-const_iterator, if either i is the begin-const_iterator or + //! the sequence is empty. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before i. + //! + //! Note: Non-standard extension. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_iterator previous(const_iterator p) + { return const_iterator(this->icont().previous(p.get())); } + + ////////////////////////////////////////////// + // + // capacity + // + ////////////////////////////////////////////// + + //! Effects: Returns true if the list contains no elements. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + bool empty() const + { return !this->size(); } + + //! Effects: Returns the number of the elements contained in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + size_type size() const + { return this->icont().size(); } + + //! Effects: Returns the largest possible size of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + size_type max_size() const + { return AllocHolder::max_size(); } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are value initialized. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size) + { + const_iterator last_pos; + if(!priv_try_shrink(new_size, last_pos)){ + typedef value_init_construct_iterator value_init_iterator; + this->insert_after(last_pos, value_init_iterator(new_size - this->size()), value_init_iterator()); + } + } + + //! Effects: Inserts or erases elements at the end such that + //! the size becomes n. New elements are copy constructed from x. + //! + //! Throws: If memory allocation throws, or T's copy constructor throws. + //! + //! Complexity: Linear to the difference between size() and new_size. + void resize(size_type new_size, const T& x) + { + const_iterator last_pos; + if(!priv_try_shrink(new_size, last_pos)){ + this->insert_after(last_pos, new_size, x); + } + } + + ////////////////////////////////////////////// + // + // element access + // + ////////////////////////////////////////////// + + //! Requires: !empty() + //! + //! Effects: Returns a reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + reference front() + { + BOOST_ASSERT(!this->empty()); + return *this->begin(); + } + + //! Requires: !empty() + //! + //! Effects: Returns a const reference to the first element + //! from the beginning of the container. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + const_reference front() const + { + BOOST_ASSERT(!this->empty()); + return *this->begin(); + } + + ////////////////////////////////////////////// + // + // modifiers + // + ////////////////////////////////////////////// + + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... in the front of the list + //! + //! Returns: A reference to the created object. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + template + reference emplace_front(BOOST_FWD_REF(Args)... args) + { return *this->emplace_after(this->cbefore_begin(), boost::forward(args)...); } + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... after prev + //! + //! Throws: If memory allocation throws or + //! T's in-place constructor throws. + //! + //! Complexity: Constant + template + iterator emplace_after(const_iterator prev, BOOST_FWD_REF(Args)... args) + { + NodePtr pnode(AllocHolder::create_node(boost::forward(args)...)); + return iterator(this->icont().insert_after(prev.get(), *pnode)); + } + + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #define BOOST_CONTAINER_SLIST_EMPLACE_CODE(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + reference emplace_front(BOOST_MOVE_UREF##N)\ + { return *this->emplace_after(this->cbefore_begin() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);}\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace_after(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + NodePtr pnode (AllocHolder::create_node(BOOST_MOVE_FWD##N));\ + return iterator(this->icont().insert_after(p.get(), *pnode));\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SLIST_EMPLACE_CODE) + #undef BOOST_CONTAINER_SLIST_EMPLACE_CODE + + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! Effects: Inserts a copy of x at the beginning of the list. + //! + //! Throws: If memory allocation throws or + //! T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + void push_front(const T &x); + + //! Effects: Constructs a new element in the beginning of the list + //! and moves the resources of x to this new element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + void push_front(T &&x); + #else + BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front) + #endif + + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Inserts a copy of the value after prev_p. + //! + //! Returns: An iterator to the inserted element. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Amortized constant time. + //! + //! Note: Does not affect the validity of iterators and references of + //! previous values. + iterator insert_after(const_iterator prev_p, const T &x); + + //! Requires: prev_p must be a valid iterator of *this. + //! + //! Effects: Inserts a move constructed copy object from the value after the + //! element pointed by prev_p. + //! + //! Returns: An iterator to the inserted element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Amortized constant time. + //! + //! Note: Does not affect the validity of iterators and references of + //! previous values. + iterator insert_after(const_iterator prev_p, T &&x); + #else + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_after, T, iterator, priv_insert_after, const_iterator, const_iterator) + #endif + + //! Requires: prev_p must be a valid iterator of *this. + //! + //! Effects: Inserts n copies of x after prev_p. + //! + //! Returns: an iterator to the last inserted element or prev_p if n is 0. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! + //! Complexity: Linear to n. + //! + //! Note: Does not affect the validity of iterators and references of + //! previous values. + iterator insert_after(const_iterator prev_p, size_type n, const value_type& x) + { + typedef constant_iterator cvalue_iterator; + return this->insert_after(prev_p, cvalue_iterator(x, n), cvalue_iterator()); + } + + //! Requires: prev_p must be a valid iterator of *this. + //! + //! Effects: Inserts the range pointed by [first, last) after prev_p. + //! + //! Returns: an iterator to the last inserted element or prev_p if first == last. + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws. + //! + //! Complexity: Linear to the number of elements inserted. + //! + //! Note: Does not affect the validity of iterators and references of + //! previous values. + template + iterator insert_after(const_iterator prev_p, InpIt first, InpIt last + #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + , typename dtl::enable_if_c + < !dtl::is_convertible::value + && (dtl::is_input_iterator::value + || dtl::is_same::value + ) + >::type * = 0 + #endif + ) + { + iterator ret_it(prev_p.get()); + for (; first != last; ++first){ + ret_it = iterator(this->icont().insert_after(ret_it.get(), *this->create_node_from_it(first))); + } + return ret_it; + } + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! Requires: prev_p must be a valid iterator of *this. + //! + //! Effects: Inserts the range pointed by [il.begin(), il.end()) after prev_p. + //! + //! Returns: an iterator to the last inserted element or prev_p if il.begin() == il.end(). + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced std::initializer_list iterator throws. + //! + //! Complexity: Linear to the number of elements inserted. + //! + //! Note: Does not affect the validity of iterators and references of + //! previous values. + iterator insert_after(const_iterator prev_p, std::initializer_list il) + { + return insert_after(prev_p, il.begin(), il.end()); + } +#endif + #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + template + iterator insert_after(const_iterator prev, FwdIt first, FwdIt last + , typename dtl::enable_if_c + < !dtl::is_convertible::value + && !(dtl::is_input_iterator::value + || dtl::is_same::value + ) + >::type * = 0 + ) + { + //Optimized allocation and construction + insertion_functor func(this->icont(), prev.get()); + this->allocate_many_and_construct(first, boost::container::iterator_udistance(first, last), func); + return iterator(func.inserted_first()); + } + #endif + + //! Effects: Removes the first element from the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Amortized constant time. + void pop_front() + { + BOOST_ASSERT(!this->empty()); + this->icont().pop_front_and_dispose(Destroyer(this->node_alloc())); + } + + //! Effects: Erases the element after the element pointed by prev_p + //! of the list. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Constant. + //! + //! Note: Does not invalidate iterators or references to non erased elements. + iterator erase_after(const_iterator prev_p) + { + return iterator(this->icont().erase_after_and_dispose(prev_p.get(), Destroyer(this->node_alloc()))); + } + + //! Effects: Erases the range (before_first, last) from + //! the list. + //! + //! Returns: the first element remaining beyond the removed elements, + //! or end() if no such element exists. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of erased elements. + //! + //! Note: Does not invalidate iterators or references to non erased elements. + iterator erase_after(const_iterator before_first, const_iterator last) + { + return iterator(this->icont().erase_after_and_dispose(before_first.get(), last.get(), Destroyer(this->node_alloc()))); + } + + //! Effects: Swaps the contents of *this and x. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements on *this and x. + void swap(slist& x) + BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) + { + BOOST_ASSERT(allocator_traits_type::propagate_on_container_swap::value || + allocator_traits_type::is_always_equal::value || + this->get_stored_allocator() == x.get_stored_allocator()); + AllocHolder::swap(x); + } + + //! Effects: Erases all the elements of the list. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements in the list. + void clear() + { this->icont().clear_and_dispose(Destroyer(this->node_alloc())); } + + ////////////////////////////////////////////// + // + // slist operations + // + ////////////////////////////////////////////// + + //! Requires: p must point to an element contained + //! by the list. x != *this + //! + //! Effects: Transfers all the elements of list x to this list, after the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear to the elements in x. + //! + //! Note: Iterators of values obtained from list x now point to elements of + //! this list. Iterators of this list and all the references are not invalidated. + void splice_after(const_iterator prev_p, slist& x) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this != &x); + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); + this->icont().splice_after(prev_p.get(), x.icont()); + } + + //! Requires: p must point to an element contained + //! by the list. x != *this + //! + //! Effects: Transfers all the elements of list x to this list, after the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: runtime_error if this' allocator and x's allocator + //! are not equal. + //! + //! Complexity: Linear to the elements in x. + //! + //! Note: Iterators of values obtained from list x now point to elements of + //! this list. Iterators of this list and all the references are not invalidated. + void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x) BOOST_NOEXCEPT_OR_NOTHROW + { this->splice_after(prev_p, BOOST_MOVE_TO_LV(x)); } + + //! Requires: prev_p must be a valid iterator of this. + //! i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal. + //! + //! Effects: Transfers the value pointed by i, from list x to this list, + //! after the element pointed by prev_p. + //! If prev_p == prev or prev_p == ++prev, this function is a null operation. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice_after(const_iterator prev_p, slist& x, const_iterator prev) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); + this->icont().splice_after(prev_p.get(), x.icont(), prev.get()); + } + + //! Requires: prev_p must be a valid iterator of this. + //! i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal. + //! + //! Effects: Transfers the value pointed by i, from list x to this list, + //! after the element pointed by prev_p. + //! If prev_p == prev or prev_p == ++prev, this function is a null operation. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x, const_iterator prev) BOOST_NOEXCEPT_OR_NOTHROW + { this->splice_after(prev_p, BOOST_MOVE_TO_LV(x), prev); } + + //! Requires: prev_p must be a valid iterator of this. + //! before_first and before_last must be valid iterators of x. + //! prev_p must not be contained in [before_first, before_last) range. + //! this' allocator and x's allocator shall compare equal. + //! + //! Effects: Transfers the range [before_first + 1, before_last + 1) + //! from list x to this list, after the element pointed by prev_p. + //! + //! Throws: Nothing + //! + //! Complexity: Linear to the number of transferred elements. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice_after(const_iterator prev_p, slist& x, + const_iterator before_first, const_iterator before_last) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); + this->icont().splice_after + (prev_p.get(), x.icont(), before_first.get(), before_last.get()); + } + + //! Requires: prev_p must be a valid iterator of this. + //! before_first and before_last must be valid iterators of x. + //! prev_p must not be contained in [before_first, before_last) range. + //! this' allocator and x's allocator shall compare equal. + //! + //! Effects: Transfers the range [before_first + 1, before_last + 1) + //! from list x to this list, after the element pointed by prev_p. + //! + //! Throws: Nothing + //! + //! Complexity: Linear to the number of transferred elements. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x, + const_iterator before_first, const_iterator before_last) BOOST_NOEXCEPT_OR_NOTHROW + { this->splice_after(prev_p, BOOST_MOVE_TO_LV(x), before_first, before_last); } + + //! Requires: prev_p must be a valid iterator of this. + //! before_first and before_last must be valid iterators of x. + //! prev_p must not be contained in [before_first, before_last) range. + //! n == distance(before_first, before_last). + //! this' allocator and x's allocator shall compare equal. + //! + //! Effects: Transfers the range [before_first + 1, before_last + 1) + //! from list x to this list, after the element pointed by prev_p. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice_after(const_iterator prev_p, slist& x, + const_iterator before_first, const_iterator before_last, + size_type n) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); + this->icont().splice_after + (prev_p.get(), x.icont(), before_first.get(), before_last.get(), n); + } + + //! Requires: prev_p must be a valid iterator of this. + //! before_first and before_last must be valid iterators of x. + //! prev_p must not be contained in [before_first, before_last) range. + //! n == distance(before_first, before_last). + //! this' allocator and x's allocator shall compare equal. + //! + //! Effects: Transfers the range [before_first + 1, before_last + 1) + //! from list x to this list, after the element pointed by prev_p. + //! + //! Throws: Nothing + //! + //! Complexity: Constant. + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x, + const_iterator before_first, const_iterator before_last, + size_type n) BOOST_NOEXCEPT_OR_NOTHROW + { this->splice_after(prev_p, BOOST_MOVE_TO_LV(x), before_first, before_last, n); } + + //! Effects: Removes all the elements that compare equal to value. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear time. It performs exactly size() comparisons for equality. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + void remove(const T& value) + { this->remove_if(equal_to_value_type(value)); } + + //! Effects: Removes all the elements for which a specified + //! predicate is satisfied. + //! + //! Throws: If pred throws. + //! + //! Complexity: Linear time. It performs exactly size() calls to the predicate. + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void remove_if(Pred pred) + { + typedef value_to_node_compare value_to_node_compare_type; + this->icont().remove_and_dispose_if(value_to_node_compare_type(pred), Destroyer(this->node_alloc())); + } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that are equal from the list. + //! + //! Throws: If comparison throws. + //! + //! Complexity: Linear time (size()-1 comparisons equality comparisons). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + void unique() + { this->unique(value_equal_t()); } + + //! Effects: Removes adjacent duplicate elements or adjacent + //! elements that satisfy some binary predicate from the list. + //! + //! Throws: If pred throws. + //! + //! Complexity: Linear time (size()-1 comparisons calls to pred()). + //! + //! Note: The relative order of elements that are not removed is unchanged, + //! and iterators to elements that are not removed remain valid. + template + void unique(Pred pred) + { + typedef value_to_node_compare value_to_node_compare_type; + this->icont().unique_and_dispose(value_to_node_compare_type(pred), Destroyer(this->node_alloc())); + } + + //! Requires: The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this according to std::less. The merge is stable; + //! that is, if an element from *this is equivalent to one from x, then the element + //! from *this will precede the one from x. + //! + //! Throws: If comparison throws. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + void merge(slist & x) + { this->merge(x, value_less_t()); } + + //! Requires: The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this according to std::less. The merge is stable; + //! that is, if an element from *this is equivalent to one from x, then the element + //! from *this will precede the one from x. + //! + //! Throws: If comparison throws. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + void merge(BOOST_RV_REF(slist) x) + { this->merge(BOOST_MOVE_TO_LV(x)); } + + //! Requires: p must be a comparison function that induces a strict weak + //! ordering and both *this and x must be sorted according to that ordering + //! The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this. The merge is stable; that is, if an element from *this is + //! equivalent to one from x, then the element from *this will precede the one from x. + //! + //! Throws: If comp throws. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references to *this are not invalidated. + template + void merge(slist& x, StrictWeakOrdering comp) + { + typedef value_to_node_compare value_to_node_compare_type; + BOOST_ASSERT(this->node_alloc() == x.node_alloc()); + this->icont().merge(x.icont(), value_to_node_compare_type(comp)); + } + + //! Requires: p must be a comparison function that induces a strict weak + //! ordering and both *this and x must be sorted according to that ordering + //! The lists x and *this must be distinct. + //! + //! Effects: This function removes all of x's elements and inserts them + //! in order into *this. The merge is stable; that is, if an element from *this is + //! equivalent to one from x, then the element from *this will precede the one from x. + //! + //! Throws: If comp throws. + //! + //! Complexity: This function is linear time: it performs at most + //! size() + x.size() - 1 comparisons. + //! + //! Note: Iterators and references to *this are not invalidated. + template + void merge(BOOST_RV_REF(slist) x, StrictWeakOrdering comp) + { this->merge(BOOST_MOVE_TO_LV(x), comp); } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: If comparison throws. + //! + //! Notes: Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + void sort() + { this->sort(value_less_t()); } + + //! Effects: This function sorts the list *this according to std::less. + //! The sort is stable, that is, the relative order of equivalent elements is preserved. + //! + //! Throws: If comp throws. + //! + //! Notes: Iterators and references are not invalidated. + //! + //! Complexity: The number of comparisons is approximately N log N, where N + //! is the list's size. + template + void sort(StrictWeakOrdering comp) + { + typedef value_to_node_compare value_to_node_compare_type; + // nothing if the slist has length 0 or 1. + if (this->size() < 2) + return; + this->icont().sort(value_to_node_compare_type(comp)); + } + + //! Effects: Reverses the order of elements in the list. + //! + //! Throws: Nothing. + //! + //! Complexity: This function is linear time. + //! + //! Note: Iterators and references are not invalidated + void reverse() BOOST_NOEXCEPT_OR_NOTHROW + { this->icont().reverse(); } + + ////////////////////////////////////////////// + // + // list compatibility interface + // + ////////////////////////////////////////////// + + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + + //! Effects: Inserts an object of type T constructed with + //! std::forward(args)... before p + //! + //! Throws: If memory allocation throws or + //! T's in-place constructor throws. + //! + //! Complexity: Linear to the elements before p + template + iterator emplace(const_iterator p, BOOST_FWD_REF(Args)... args) + { return this->emplace_after(this->previous(p), boost::forward(args)...); } + + #else + + #define BOOST_CONTAINER_SLIST_EMPLACE_CODE(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + return this->emplace_after(this->previous(p) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SLIST_EMPLACE_CODE) + #undef BOOST_CONTAINER_SLIST_EMPLACE_CODE + + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a copy of x before p. + //! + //! Returns: an iterator to the inserted element. + //! + //! Throws: If memory allocation throws or x's copy constructor throws. + //! + //! Complexity: Linear to the elements before p. + iterator insert(const_iterator p, const T &x); + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a new element before p with x's resources. + //! + //! Returns: an iterator to the inserted element. + //! + //! Throws: If memory allocation throws. + //! + //! Complexity: Linear to the elements before p. + iterator insert(const_iterator prev_p, T &&x); + #else + BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator) + #endif + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Inserts n copies of x before p. + //! + //! Returns: an iterator to the first inserted element or p if n == 0. + //! + //! Throws: If memory allocation throws or T's copy constructor throws. + //! + //! Complexity: Linear to n plus linear to the elements before p. + iterator insert(const_iterator p, size_type n, const value_type& x) + { + const_iterator prev(this->previous(p)); + this->insert_after(prev, n, x); + return ++iterator(prev.get()); + } + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a copy of the [first, last) range before p. + //! + //! Returns: an iterator to the first inserted element or p if first == last. + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced InpIt throws. + //! + //! Complexity: Linear to distance [first, last) plus + //! linear to the elements before p. + template + iterator insert(const_iterator p, InIter first, InIter last) + { + const_iterator prev(this->previous(p)); + this->insert_after(prev, first, last); + return ++iterator(prev.get()); + } + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Insert a copy of the [il.begin(), il.end()) range before p. + //! + //! Returns: an iterator to the first inserted element or p if il.begin() == il.end(). + //! + //! Throws: If memory allocation throws, T's constructor from a + //! dereferenced std::initializer_list iterator throws. + //! + //! Complexity: Linear to the range [il.begin(), il.end()) plus + //! linear to the elements before p. + iterator insert(const_iterator p, std::initializer_list il) + { + return insert(p, il.begin(), il.end()); + } +#endif + + //! Requires: p must be a valid iterator of *this. + //! + //! Effects: Erases the element at p. + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the number of elements before p. + iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW + { return iterator(this->erase_after(previous(p))); } + + //! Requires: first and last must be valid iterator to elements in *this. + //! + //! Effects: Erases the elements pointed by [first, last). + //! + //! Throws: Nothing. + //! + //! Complexity: Linear to the distance between first and last plus + //! linear to the elements before first. + iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW + { return iterator(this->erase_after(previous(first), last)); } + + //! Requires: p must point to an element contained + //! by the list. x != *this. this' allocator and x's allocator shall compare equal + //! + //! Effects: Transfers all the elements of list x to this list, before the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing + //! + //! Complexity: Linear in distance(begin(), p), and linear in x.size(). + //! + //! Note: Iterators of values obtained from list x now point to elements of + //! this list. Iterators of this list and all the references are not invalidated. + void splice(const_iterator p, slist& x) BOOST_NOEXCEPT_OR_NOTHROW + { this->splice_after(this->previous(p), x); } + + //! Requires: p must point to an element contained + //! by the list. x != *this. this' allocator and x's allocator shall compare equal + //! + //! Effects: Transfers all the elements of list x to this list, before the + //! the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing + //! + //! Complexity: Linear in distance(begin(), p), and linear in x.size(). + //! + //! Note: Iterators of values obtained from list x now point to elements of + //! this list. Iterators of this list and all the references are not invalidated. + void splice(const_iterator p, BOOST_RV_REF(slist) x) BOOST_NOEXCEPT_OR_NOTHROW + { this->splice(p, BOOST_MOVE_TO_LV(x)); } + + //! Requires: p must point to an element contained + //! by this list. i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal + //! + //! Effects: Transfers the value pointed by i, from list x to this list, + //! before the element pointed by p. No destructors or copy constructors are called. + //! If p == i or p == ++i, this function is a null operation. + //! + //! Throws: Nothing + //! + //! Complexity: Linear in distance(begin(), p), and in distance(x.begin(), i). + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(const_iterator p, slist& x, const_iterator i) BOOST_NOEXCEPT_OR_NOTHROW + { this->splice_after(this->previous(p), x, x.previous(i)); } + + //! Requires: p must point to an element contained + //! by this list. i must point to an element contained in list x. + //! this' allocator and x's allocator shall compare equal. + //! + //! Effects: Transfers the value pointed by i, from list x to this list, + //! before the element pointed by p. No destructors or copy constructors are called. + //! If p == i or p == ++i, this function is a null operation. + //! + //! Throws: Nothing + //! + //! Complexity: Linear in distance(begin(), p), and in distance(x.begin(), i). + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator i) BOOST_NOEXCEPT_OR_NOTHROW + { this->splice(p, BOOST_MOVE_TO_LV(x), i); } + + //! Requires: p must point to an element contained + //! by this list. first and last must point to elements contained in list x. + //! + //! Effects: Transfers the range pointed by first and last from list x to this list, + //! before the element pointed by p. No destructors or copy constructors are called. + //! this' allocator and x's allocator shall compare equal. + //! + //! Throws: Nothing + //! + //! Complexity: Linear in distance(begin(), p), in distance(x.begin(), first), + //! and in distance(first, last). + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(const_iterator p, slist& x, const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW + { this->splice_after(this->previous(p), x, x.previous(first), x.previous(last)); } + + //! Requires: p must point to an element contained + //! by this list. first and last must point to elements contained in list x. + //! this' allocator and x's allocator shall compare equal + //! + //! Effects: Transfers the range pointed by first and last from list x to this list, + //! before the element pointed by p. No destructors or copy constructors are called. + //! + //! Throws: Nothing + //! + //! Complexity: Linear in distance(begin(), p), in distance(x.begin(), first), + //! and in distance(first, last). + //! + //! Note: Iterators of values obtained from list x now point to elements of this + //! list. Iterators of this list and all the references are not invalidated. + void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW + { this->splice(p, BOOST_MOVE_TO_LV(x), first, last); } + + //! Effects: Returns true if x and y are equal + //! + //! Complexity: Linear to the number of elements in the container. + friend bool operator==(const slist& x, const slist& y) + { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); } + + //! Effects: Returns true if x and y are unequal + //! + //! Complexity: Linear to the number of elements in the container. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + friend bool operator!=(const slist& x, const slist& y) + { return !(x == y); } + + //! Effects: Returns true if x is less than y + //! + //! Complexity: Linear to the number of elements in the container. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + friend bool operator<(const slist& x, const slist& y) + { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + + //! Effects: Returns true if x is greater than y + //! + //! Complexity: Linear to the number of elements in the container. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + friend bool operator>(const slist& x, const slist& y) + { return y < x; } + + //! Effects: Returns true if x is equal or less than y + //! + //! Complexity: Linear to the number of elements in the container. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + friend bool operator<=(const slist& x, const slist& y) + { return !(y < x); } + + //! Effects: Returns true if x is equal or greater than y + //! + //! Complexity: Linear to the number of elements in the container. + BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE + friend bool operator>=(const slist& x, const slist& y) + { return !(x < y); } + + //! Effects: x.swap(y) + //! + //! Complexity: Constant. + friend void swap(slist& x, slist& y) + BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y))) + { x.swap(y); } + + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + private: + + template + void priv_push_front(BOOST_FWD_REF(U) x) + { this->icont().push_front(*this->create_node(::boost::forward(x))); } + + bool priv_try_shrink(size_type new_size, const_iterator &last_pos) + { + typename Icont::iterator end_n(this->icont().end()), cur(this->icont().before_begin()), cur_next; + while (++(cur_next = cur) != end_n && new_size > 0){ + --new_size; + cur = cur_next; + } + last_pos = const_iterator(cur); + if (cur_next != end_n){ + this->erase_after(last_pos, const_iterator(end_n)); + return true; + } + else{ + return false; + } + } + + template + iterator priv_insert(const_iterator p, BOOST_FWD_REF(U) x) + { return this->insert_after(previous(p), ::boost::forward(x)); } + + template + iterator priv_insert_after(const_iterator prev_p, BOOST_FWD_REF(U) x) + { return iterator(this->icont().insert_after(prev_p.get(), *this->create_node(::boost::forward(x)))); } + + class insertion_functor; + friend class insertion_functor; + + class insertion_functor + { + Icont &icont_; + typedef typename Icont::iterator iiterator; + typedef typename Icont::const_iterator iconst_iterator; + const iconst_iterator prev_; + iiterator ret_; + + public: + insertion_functor(Icont &icont, typename Icont::const_iterator prev) + : icont_(icont), prev_(prev), ret_(prev.unconst()) + {} + + void operator()(Node &n) + { + ret_ = this->icont_.insert_after(prev_, n); + } + + iiterator inserted_first() const + { return ret_; } + }; + + //Functors for member algorithm defaults + typedef value_less value_less_t; + typedef value_equal value_equal_t; + + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED +}; + +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + +template +slist(InpIt, InpIt) -> + slist::value_type>; + +template +slist(InpIt, InpIt, Allocator const&) -> + slist::value_type, Allocator>; + +#endif + +}} + +#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + +namespace boost { + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template +struct has_trivial_destructor_after_move > +{ + typedef typename boost::container::slist::allocator_type allocator_type; + typedef typename ::boost::container::allocator_traits::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move::value && + ::boost::has_trivial_destructor_after_move::value; +}; + +namespace container { + +}} //namespace boost{ namespace container { + +#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + +// Specialization of insert_iterator so that insertions will be constant +// time rather than linear time. + +#include +BOOST_CONTAINER_DOC1ST(namespace std {, BOOST_MOVE_STD_NS_BEG) + +//! A specialization of insert_iterator +//! that works with slist +template +class insert_iterator > +{ + private: + typedef boost::container::slist Container; + Container* container; + typename Container::iterator iter; + + public: + typedef Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(Container& x, + typename Container::iterator i, + bool is_previous = false) + : container(&x), iter(is_previous ? i : x.previous(i)){ } + + insert_iterator& + operator=(const typename Container::value_type& value) + { + iter = container->insert_after(iter, value); + return *this; + } + insert_iterator& operator*(){ return *this; } + insert_iterator& operator++(){ return *this; } + insert_iterator& operator++(int){ return *this; } +}; + +BOOST_CONTAINER_DOC1ST( }, BOOST_MOVE_STD_NS_END) +#include + +#include + +#endif // BOOST_CONTAINER_SLIST_HPP diff --git a/boost/container_hash/detail/hash_integral.hpp b/boost/container_hash/detail/hash_integral.hpp new file mode 100644 index 00000000..3b0be63f --- /dev/null +++ b/boost/container_hash/detail/hash_integral.hpp @@ -0,0 +1,146 @@ +// Copyright 2021-2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_HASH_DETAIL_HASH_INTEGRAL_HPP +#define BOOST_HASH_DETAIL_HASH_INTEGRAL_HPP + +#include +#include +#include +#include + +namespace boost +{ +namespace hash_detail +{ + +// libstdc++ doesn't provide support for __int128 in the standard traits + +template struct is_integral: public std::is_integral +{ +}; + +template struct is_unsigned: public std::is_unsigned +{ +}; + +template struct make_unsigned: public std::make_unsigned +{ +}; + +#if defined(__SIZEOF_INT128__) + +template<> struct is_integral<__int128_t>: public std::true_type +{ +}; + +template<> struct is_integral<__uint128_t>: public std::true_type +{ +}; + +template<> struct is_unsigned<__int128_t>: public std::false_type +{ +}; + +template<> struct is_unsigned<__uint128_t>: public std::true_type +{ +}; + +template<> struct make_unsigned<__int128_t> +{ + typedef __uint128_t type; +}; + +template<> struct make_unsigned<__uint128_t> +{ + typedef __uint128_t type; +}; + +#endif + +template sizeof(std::size_t)), + bool is_unsigned = is_unsigned::value, + std::size_t size_t_bits = sizeof(std::size_t) * CHAR_BIT, + std::size_t type_bits = sizeof(T) * CHAR_BIT> +struct hash_integral_impl; + +template struct hash_integral_impl +{ + static std::size_t fn( T v ) + { + return static_cast( v ); + } +}; + +template struct hash_integral_impl +{ + static std::size_t fn( T v ) + { + typedef typename make_unsigned::type U; + + if( v >= 0 ) + { + return hash_integral_impl::fn( static_cast( v ) ); + } + else + { + return ~hash_integral_impl::fn( static_cast( ~static_cast( v ) ) ); + } + } +}; + +template struct hash_integral_impl +{ + static std::size_t fn( T v ) + { + std::size_t seed = 0; + + seed = static_cast( v >> 32 ) + hash_detail::hash_mix( seed ); + seed = static_cast( v & 0xFFFFFFFF ) + hash_detail::hash_mix( seed ); + + return seed; + } +}; + +template struct hash_integral_impl +{ + static std::size_t fn( T v ) + { + std::size_t seed = 0; + + seed = static_cast( v >> 96 ) + hash_detail::hash_mix( seed ); + seed = static_cast( v >> 64 ) + hash_detail::hash_mix( seed ); + seed = static_cast( v >> 32 ) + hash_detail::hash_mix( seed ); + seed = static_cast( v ) + hash_detail::hash_mix( seed ); + + return seed; + } +}; + +template struct hash_integral_impl +{ + static std::size_t fn( T v ) + { + std::size_t seed = 0; + + seed = static_cast( v >> 64 ) + hash_detail::hash_mix( seed ); + seed = static_cast( v ) + hash_detail::hash_mix( seed ); + + return seed; + } +}; + +} // namespace hash_detail + +template +typename std::enable_if::value, std::size_t>::type + hash_value( T v ) +{ + return hash_detail::hash_integral_impl::fn( v ); +} + +} // namespace boost + +#endif // #ifndef BOOST_HASH_DETAIL_HASH_INTEGRAL_HPP diff --git a/boost/container_hash/detail/hash_mix.hpp b/boost/container_hash/detail/hash_mix.hpp new file mode 100644 index 00000000..088dd75d --- /dev/null +++ b/boost/container_hash/detail/hash_mix.hpp @@ -0,0 +1,113 @@ +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_HASH_DETAIL_HASH_MIX_HPP +#define BOOST_HASH_DETAIL_HASH_MIX_HPP + +#include +#include +#include + +namespace boost +{ +namespace hash_detail +{ + +template struct hash_mix_impl; + +// hash_mix for 64 bit size_t +// +// The general "xmxmx" form of state of the art 64 bit mixers originates +// from Murmur3 by Austin Appleby, which uses the following function as +// its "final mix": +// +// k ^= k >> 33; +// k *= 0xff51afd7ed558ccd; +// k ^= k >> 33; +// k *= 0xc4ceb9fe1a85ec53; +// k ^= k >> 33; +// +// (https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp) +// +// It has subsequently been improved multiple times by different authors +// by changing the constants. The most well known improvement is the +// so-called "variant 13" function by David Stafford: +// +// k ^= k >> 30; +// k *= 0xbf58476d1ce4e5b9; +// k ^= k >> 27; +// k *= 0x94d049bb133111eb; +// k ^= k >> 31; +// +// (https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html) +// +// This mixing function is used in the splitmix64 RNG: +// http://xorshift.di.unimi.it/splitmix64.c +// +// We use Jon Maiga's implementation from +// http://jonkagstrom.com/mx3/mx3_rev2.html +// +// x ^= x >> 32; +// x *= 0xe9846af9b1a615d; +// x ^= x >> 32; +// x *= 0xe9846af9b1a615d; +// x ^= x >> 28; +// +// An equally good alternative is Pelle Evensen's Moremur: +// +// x ^= x >> 27; +// x *= 0x3C79AC492BA7B653; +// x ^= x >> 33; +// x *= 0x1C69B3F74AC4AE35; +// x ^= x >> 27; +// +// (https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html) + +template<> struct hash_mix_impl<64> +{ + inline static std::uint64_t fn( std::uint64_t x ) + { + std::uint64_t const m = 0xe9846af9b1a615d; + + x ^= x >> 32; + x *= m; + x ^= x >> 32; + x *= m; + x ^= x >> 28; + + return x; + } +}; + +// hash_mix for 32 bit size_t +// +// We use the "best xmxmx" implementation from +// https://github.com/skeeto/hash-prospector/issues/19 + +template<> struct hash_mix_impl<32> +{ + inline static std::uint32_t fn( std::uint32_t x ) + { + std::uint32_t const m1 = 0x21f0aaad; + std::uint32_t const m2 = 0x735a2d97; + + x ^= x >> 16; + x *= m1; + x ^= x >> 15; + x *= m2; + x ^= x >> 15; + + return x; + } +}; + +inline std::size_t hash_mix( std::size_t v ) +{ + return hash_mix_impl::fn( v ); +} + +} // namespace hash_detail +} // namespace boost + +#endif // #ifndef BOOST_HASH_DETAIL_HASH_MIX_HPP diff --git a/boost/container_hash/detail/hash_range.hpp b/boost/container_hash/detail/hash_range.hpp new file mode 100644 index 00000000..74bfe384 --- /dev/null +++ b/boost/container_hash/detail/hash_range.hpp @@ -0,0 +1,408 @@ +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_HASH_DETAIL_HASH_RANGE_HPP +#define BOOST_HASH_DETAIL_HASH_RANGE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ +namespace hash_detail +{ + +template struct is_char_type: public std::false_type {}; + +#if CHAR_BIT == 8 + +template<> struct is_char_type: public std::true_type {}; +template<> struct is_char_type: public std::true_type {}; +template<> struct is_char_type: public std::true_type {}; + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L +template<> struct is_char_type: public std::true_type {}; +#endif + +#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L +template<> struct is_char_type: public std::true_type {}; +#endif + +#endif + +// generic version + +template +inline typename std::enable_if< + !is_char_type::value_type>::value, +std::size_t >::type + hash_range( std::size_t seed, It first, It last ) +{ + for( ; first != last; ++first ) + { + hash_combine::value_type>( seed, *first ); + } + + return seed; +} + +// specialized char[] version, 32 bit + +template inline std::uint32_t read32le( It p ) +{ + // clang 5+, gcc 5+ figure out this pattern and use a single mov on x86 + // gcc on s390x and power BE even knows how to use load-reverse + + std::uint32_t w = + static_cast( static_cast( p[0] ) ) | + static_cast( static_cast( p[1] ) ) << 8 | + static_cast( static_cast( p[2] ) ) << 16 | + static_cast( static_cast( p[3] ) ) << 24; + + return w; +} + +#if defined(_MSC_VER) && !defined(__clang__) + +template inline std::uint32_t read32le( T* p ) +{ + std::uint32_t w; + + std::memcpy( &w, p, 4 ); + return w; +} + +#endif + +inline std::uint64_t mul32( std::uint32_t x, std::uint32_t y ) +{ + return static_cast( x ) * y; +} + +template +inline typename std::enable_if< + is_char_type::value_type>::value && + std::is_same::iterator_category, std::random_access_iterator_tag>::value && + std::numeric_limits::digits <= 32, +std::size_t>::type + hash_range( std::size_t seed, It first, It last ) +{ + It p = first; + std::size_t n = static_cast( last - first ); + + std::uint32_t const q = 0x9e3779b9U; + std::uint32_t const k = 0xe35e67b1U; // q * q + + std::uint64_t h = mul32( static_cast( seed ) + q, k ); + std::uint32_t w = static_cast( h & 0xFFFFFFFF ); + + h ^= n; + + while( n >= 4 ) + { + std::uint32_t v1 = read32le( p ); + + w += q; + h ^= mul32( v1 + w, k ); + + p += 4; + n -= 4; + } + + { + std::uint32_t v1 = 0; + + if( n >= 1 ) + { + std::size_t const x1 = ( n - 1 ) & 2; // 1: 0, 2: 0, 3: 2 + std::size_t const x2 = n >> 1; // 1: 0, 2: 1, 3: 1 + + v1 = + static_cast( static_cast( p[ static_cast( x1 ) ] ) ) << x1 * 8 | + static_cast( static_cast( p[ static_cast( x2 ) ] ) ) << x2 * 8 | + static_cast( static_cast( p[ 0 ] ) ); + } + + w += q; + h ^= mul32( v1 + w, k ); + } + + w += q; + h ^= mul32( static_cast( h & 0xFFFFFFFF ) + w, static_cast( h >> 32 ) + w + k ); + + return static_cast( h & 0xFFFFFFFF ) ^ static_cast( h >> 32 ); +} + +template +inline typename std::enable_if< + is_char_type::value_type>::value && + !std::is_same::iterator_category, std::random_access_iterator_tag>::value && + std::numeric_limits::digits <= 32, +std::size_t>::type + hash_range( std::size_t seed, It first, It last ) +{ + std::size_t n = 0; + + std::uint32_t const q = 0x9e3779b9U; + std::uint32_t const k = 0xe35e67b1U; // q * q + + std::uint64_t h = mul32( static_cast( seed ) + q, k ); + std::uint32_t w = static_cast( h & 0xFFFFFFFF ); + + std::uint32_t v1 = 0; + + for( ;; ) + { + v1 = 0; + + if( first == last ) + { + break; + } + + v1 |= static_cast( static_cast( *first ) ); + ++first; + ++n; + + if( first == last ) + { + break; + } + + v1 |= static_cast( static_cast( *first ) ) << 8; + ++first; + ++n; + + if( first == last ) + { + break; + } + + v1 |= static_cast( static_cast( *first ) ) << 16; + ++first; + ++n; + + if( first == last ) + { + break; + } + + v1 |= static_cast( static_cast( *first ) ) << 24; + ++first; + ++n; + + w += q; + h ^= mul32( v1 + w, k ); + } + + h ^= n; + + w += q; + h ^= mul32( v1 + w, k ); + + w += q; + h ^= mul32( static_cast( h & 0xFFFFFFFF ) + w, static_cast( h >> 32 ) + w + k ); + + return static_cast( h & 0xFFFFFFFF ) ^ static_cast( h >> 32 ); +} + +// specialized char[] version, 64 bit + +template inline std::uint64_t read64le( It p ) +{ + std::uint64_t w = + static_cast( static_cast( p[0] ) ) | + static_cast( static_cast( p[1] ) ) << 8 | + static_cast( static_cast( p[2] ) ) << 16 | + static_cast( static_cast( p[3] ) ) << 24 | + static_cast( static_cast( p[4] ) ) << 32 | + static_cast( static_cast( p[5] ) ) << 40 | + static_cast( static_cast( p[6] ) ) << 48 | + static_cast( static_cast( p[7] ) ) << 56; + + return w; +} + +#if defined(_MSC_VER) && !defined(__clang__) + +template inline std::uint64_t read64le( T* p ) +{ + std::uint64_t w; + + std::memcpy( &w, p, 8 ); + return w; +} + +#endif + +template +inline typename std::enable_if< + is_char_type::value_type>::value && + std::is_same::iterator_category, std::random_access_iterator_tag>::value && + (std::numeric_limits::digits > 32), +std::size_t>::type + hash_range( std::size_t seed, It first, It last ) +{ + It p = first; + std::size_t n = static_cast( last - first ); + + std::uint64_t const q = 0x9e3779b97f4a7c15; + std::uint64_t const k = 0xdf442d22ce4859b9; // q * q + + std::uint64_t w = mulx( seed + q, k ); + std::uint64_t h = w ^ n; + + while( n >= 8 ) + { + std::uint64_t v1 = read64le( p ); + + w += q; + h ^= mulx( v1 + w, k ); + + p += 8; + n -= 8; + } + + { + std::uint64_t v1 = 0; + + if( n >= 4 ) + { + v1 = static_cast( read32le( p + static_cast( n - 4 ) ) ) << ( n - 4 ) * 8 | read32le( p ); + } + else if( n >= 1 ) + { + std::size_t const x1 = ( n - 1 ) & 2; // 1: 0, 2: 0, 3: 2 + std::size_t const x2 = n >> 1; // 1: 0, 2: 1, 3: 1 + + v1 = + static_cast( static_cast( p[ static_cast( x1 ) ] ) ) << x1 * 8 | + static_cast( static_cast( p[ static_cast( x2 ) ] ) ) << x2 * 8 | + static_cast( static_cast( p[ 0 ] ) ); + } + + w += q; + h ^= mulx( v1 + w, k ); + } + + return mulx( h + w, k ); +} + +template +inline typename std::enable_if< + is_char_type::value_type>::value && + !std::is_same::iterator_category, std::random_access_iterator_tag>::value && + (std::numeric_limits::digits > 32), +std::size_t>::type + hash_range( std::size_t seed, It first, It last ) +{ + std::size_t n = 0; + + std::uint64_t const q = 0x9e3779b97f4a7c15; + std::uint64_t const k = 0xdf442d22ce4859b9; // q * q + + std::uint64_t w = mulx( seed + q, k ); + std::uint64_t h = w; + + std::uint64_t v1 = 0; + + for( ;; ) + { + v1 = 0; + + if( first == last ) + { + break; + } + + v1 |= static_cast( static_cast( *first ) ); + ++first; + ++n; + + if( first == last ) + { + break; + } + + v1 |= static_cast( static_cast( *first ) ) << 8; + ++first; + ++n; + + if( first == last ) + { + break; + } + + v1 |= static_cast( static_cast( *first ) ) << 16; + ++first; + ++n; + + if( first == last ) + { + break; + } + + v1 |= static_cast( static_cast( *first ) ) << 24; + ++first; + ++n; + + if( first == last ) + { + break; + } + + v1 |= static_cast( static_cast( *first ) ) << 32; + ++first; + ++n; + + if( first == last ) + { + break; + } + + v1 |= static_cast( static_cast( *first ) ) << 40; + ++first; + ++n; + + if( first == last ) + { + break; + } + + v1 |= static_cast( static_cast( *first ) ) << 48; + ++first; + ++n; + + if( first == last ) + { + break; + } + + v1 |= static_cast( static_cast( *first ) ) << 56; + ++first; + ++n; + + w += q; + h ^= mulx( v1 + w, k ); + } + + h ^= n; + + w += q; + h ^= mulx( v1 + w, k ); + + return mulx( h + w, k ); +} + +} // namespace hash_detail +} // namespace boost + +#endif // #ifndef BOOST_HASH_DETAIL_HASH_RANGE_HPP diff --git a/boost/container_hash/detail/hash_tuple_like.hpp b/boost/container_hash/detail/hash_tuple_like.hpp new file mode 100644 index 00000000..c7f881c1 --- /dev/null +++ b/boost/container_hash/detail/hash_tuple_like.hpp @@ -0,0 +1,62 @@ +// Copyright 2005-2009 Daniel James. +// Copyright 2021 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP +#define BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP + +#include +#include +#include +#include +#include + +namespace boost +{ +namespace hash_detail +{ + +template +inline +typename std::enable_if<(I == std::tuple_size::value), void>::type + hash_combine_tuple_like( std::size_t&, T const& ) +{ +} + +template +inline +typename std::enable_if<(I < std::tuple_size::value), void>::type + hash_combine_tuple_like( std::size_t& seed, T const& v ) +{ + using std::get; + boost::hash_combine( seed, get( v ) ); + + boost::hash_detail::hash_combine_tuple_like( seed, v ); +} + +template +inline std::size_t hash_tuple_like( T const& v ) +{ + std::size_t seed = 0; + + boost::hash_detail::hash_combine_tuple_like<0>( seed, v ); + + return seed; +} + +} // namespace hash_detail + +template +inline +typename std::enable_if< + container_hash::is_tuple_like::value && !container_hash::is_range::value, +std::size_t>::type + hash_value( T const& v ) +{ + return boost::hash_detail::hash_tuple_like( v ); +} + +} // namespace boost + +#endif // #ifndef BOOST_HASH_DETAIL_HASH_TUPLE_LIKE_HPP diff --git a/boost/container_hash/detail/mulx.hpp b/boost/container_hash/detail/mulx.hpp new file mode 100644 index 00000000..a99a7dd3 --- /dev/null +++ b/boost/container_hash/detail/mulx.hpp @@ -0,0 +1,79 @@ +// Copyright 2022, 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_HASH_DETAIL_MULX_HPP +#define BOOST_HASH_DETAIL_MULX_HPP + +#include +#if defined(_MSC_VER) +# include +#endif + +namespace boost +{ +namespace hash_detail +{ + +#if defined(_MSC_VER) && defined(_M_X64) && !defined(__clang__) + +__forceinline std::uint64_t mulx( std::uint64_t x, std::uint64_t y ) +{ + std::uint64_t r2; + std::uint64_t r = _umul128( x, y, &r2 ); + return r ^ r2; +} + +#elif defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__) + +__forceinline std::uint64_t mulx( std::uint64_t x, std::uint64_t y ) +{ + std::uint64_t r = x * y; + std::uint64_t r2 = __umulh( x, y ); + return r ^ r2; +} + +#elif defined(__SIZEOF_INT128__) + +inline std::uint64_t mulx( std::uint64_t x, std::uint64_t y ) +{ + __uint128_t r = static_cast<__uint128_t>( x ) * y; + return static_cast( r ) ^ static_cast( r >> 64 ); +} + +#else + +inline std::uint64_t mulx( std::uint64_t x, std::uint64_t y ) +{ + std::uint64_t x1 = static_cast( x ); + std::uint64_t x2 = x >> 32; + + std::uint64_t y1 = static_cast( y ); + std::uint64_t y2 = y >> 32; + + std::uint64_t r3 = x2 * y2; + + std::uint64_t r2a = x1 * y2; + + r3 += r2a >> 32; + + std::uint64_t r2b = x2 * y1; + + r3 += r2b >> 32; + + std::uint64_t r1 = x1 * y1; + + std::uint64_t r2 = (r1 >> 32) + static_cast( r2a ) + static_cast( r2b ); + + r1 = (r2 << 32) + static_cast( r1 ); + r3 += r2 >> 32; + + return r1 ^ r3; +} + +#endif + +} // namespace hash_detail +} // namespace boost + +#endif // #ifndef BOOST_HASH_DETAIL_MULX_HPP diff --git a/boost/container_hash/hash.hpp b/boost/container_hash/hash.hpp new file mode 100644 index 00000000..8305a22c --- /dev/null +++ b/boost/container_hash/hash.hpp @@ -0,0 +1,576 @@ +// Copyright 2005-2014 Daniel James. +// Copyright 2021, 2022 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// Based on Peter Dimov's proposal +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf +// issue 6.18. + +#ifndef BOOST_FUNCTIONAL_HASH_HASH_HPP +#define BOOST_FUNCTIONAL_HASH_HASH_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_DESCRIBE_CXX14) +# include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_NO_CXX11_SMART_PTR) +# include +#endif + +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) +#include +#endif + +#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) +#include +#endif + +#if !defined(BOOST_NO_CXX17_HDR_OPTIONAL) +#include +#endif + +#if !defined(BOOST_NO_CXX17_HDR_VARIANT) +#include +#endif + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +# include +#endif + +namespace boost +{ + + // + // boost::hash_value + // + + // integral types + // in detail/hash_integral.hpp + + // enumeration types + + template + typename std::enable_if::value, std::size_t>::type + hash_value( T v ) + { + // This should in principle return the equivalent of + // + // boost::hash_value( to_underlying(v) ); + // + // However, the C++03 implementation of underlying_type, + // + // conditional, make_signed, make_unsigned>::type::type + // + // generates a legitimate -Wconversion warning in is_signed, + // because -1 is not a valid enum value when all the enumerators + // are nonnegative. + // + // So the legacy implementation will have to do for now. + + return static_cast( v ); + } + + // floating point types + + namespace hash_detail + { + template::digits> + struct hash_float_impl; + + // float + template struct hash_float_impl + { + static std::size_t fn( T v ) + { + std::uint32_t w; + std::memcpy( &w, &v, sizeof( v ) ); + + return w; + } + }; + + // double + template struct hash_float_impl + { + static std::size_t fn( T v ) + { + std::uint64_t w; + std::memcpy( &w, &v, sizeof( v ) ); + + return hash_value( w ); + } + }; + + // 80 bit long double in 12 bytes + template struct hash_float_impl + { + static std::size_t fn( T v ) + { + std::uint64_t w[ 2 ] = {}; + std::memcpy( &w, &v, 80 / CHAR_BIT ); + + std::size_t seed = 0; + + seed = hash_value( w[0] ) + hash_detail::hash_mix( seed ); + seed = hash_value( w[1] ) + hash_detail::hash_mix( seed ); + + return seed; + } + }; + + // 80 bit long double in 16 bytes + template struct hash_float_impl + { + static std::size_t fn( T v ) + { + std::uint64_t w[ 2 ] = {}; + std::memcpy( &w, &v, 80 / CHAR_BIT ); + + std::size_t seed = 0; + + seed = hash_value( w[0] ) + hash_detail::hash_mix( seed ); + seed = hash_value( w[1] ) + hash_detail::hash_mix( seed ); + + return seed; + } + }; + + // 128 bit long double + template struct hash_float_impl + { + static std::size_t fn( T v ) + { + std::uint64_t w[ 2 ]; + std::memcpy( &w, &v, sizeof( v ) ); + + std::size_t seed = 0; + +#if defined(__FLOAT_WORD_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__ + + seed = hash_value( w[1] ) + hash_detail::hash_mix( seed ); + seed = hash_value( w[0] ) + hash_detail::hash_mix( seed ); + +#else + + seed = hash_value( w[0] ) + hash_detail::hash_mix( seed ); + seed = hash_value( w[1] ) + hash_detail::hash_mix( seed ); + +#endif + return seed; + } + }; + + } // namespace hash_detail + + template + typename std::enable_if::value, std::size_t>::type + hash_value( T v ) + { + return boost::hash_detail::hash_float_impl::fn( v + 0 ); + } + + // pointer types + + // `x + (x >> 3)` adjustment by Alberto Barbati and Dave Harris. + template std::size_t hash_value( T* const& v ) + { + std::uintptr_t x = reinterpret_cast( v ); + return boost::hash_value( x + (x >> 3) ); + } + + // array types + + template + inline std::size_t hash_value( T const (&x)[ N ] ) + { + return boost::hash_range( x, x + N ); + } + + template + inline std::size_t hash_value( T (&x)[ N ] ) + { + return boost::hash_range( x, x + N ); + } + + // complex + + template + std::size_t hash_value( std::complex const& v ) + { + std::size_t re = boost::hash()( v.real() ); + std::size_t im = boost::hash()( v.imag() ); + + return re + hash_detail::hash_mix( im ); + } + + // pair + + template + std::size_t hash_value( std::pair const& v ) + { + std::size_t seed = 0; + + boost::hash_combine( seed, v.first ); + boost::hash_combine( seed, v.second ); + + return seed; + } + + // ranges (list, set, deque...) + + template + typename std::enable_if::value && !container_hash::is_contiguous_range::value && !container_hash::is_unordered_range::value, std::size_t>::type + hash_value( T const& v ) + { + return boost::hash_range( v.begin(), v.end() ); + } + + // contiguous ranges (string, vector, array) + + template + typename std::enable_if::value, std::size_t>::type + hash_value( T const& v ) + { + return boost::hash_range( v.data(), v.data() + v.size() ); + } + + // unordered ranges (unordered_set, unordered_map) + + template + typename std::enable_if::value, std::size_t>::type + hash_value( T const& v ) + { + return boost::hash_unordered_range( v.begin(), v.end() ); + } + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ( \ + ( defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION < 142 ) || \ + ( !defined(_MSVC_STL_VERSION) && defined(_CPPLIB_VER) && _CPPLIB_VER >= 520 ) ) + + // resolve ambiguity with unconstrained stdext::hash_value in :-/ + + template class L, class... T> + typename std::enable_if>::value && !container_hash::is_contiguous_range>::value && !container_hash::is_unordered_range>::value, std::size_t>::type + hash_value( L const& v ) + { + return boost::hash_range( v.begin(), v.end() ); + } + + // contiguous ranges (string, vector, array) + + template class L, class... T> + typename std::enable_if>::value, std::size_t>::type + hash_value( L const& v ) + { + return boost::hash_range( v.data(), v.data() + v.size() ); + } + + template class L, class T, std::size_t N> + typename std::enable_if>::value, std::size_t>::type + hash_value( L const& v ) + { + return boost::hash_range( v.data(), v.data() + v.size() ); + } + + // unordered ranges (unordered_set, unordered_map) + + template class L, class... T> + typename std::enable_if>::value, std::size_t>::type + hash_value( L const& v ) + { + return boost::hash_unordered_range( v.begin(), v.end() ); + } + +#endif + + // described classes + +#if defined(BOOST_DESCRIBE_CXX14) + +#if defined(_MSC_VER) && _MSC_VER == 1900 +# pragma warning(push) +# pragma warning(disable: 4100) // unreferenced formal parameter +#endif + + template + typename std::enable_if::value, std::size_t>::type + hash_value( T const& v ) + { + static_assert( !std::is_union::value, "described unions are not supported" ); + + std::size_t r = 0; + + using Bd = describe::describe_bases; + + mp11::mp_for_each([&](auto D){ + + using B = typename decltype(D)::type; + boost::hash_combine( r, (B const&)v ); + + }); + + using Md = describe::describe_members; + + mp11::mp_for_each([&](auto D){ + + boost::hash_combine( r, v.*D.pointer ); + + }); + + return r; + } + +#if defined(_MSC_VER) && _MSC_VER == 1900 +# pragma warning(pop) +#endif + +#endif + + // std::unique_ptr, std::shared_ptr + +#if !defined(BOOST_NO_CXX11_SMART_PTR) + + template + std::size_t hash_value( std::shared_ptr const& x ) + { + return boost::hash_value( x.get() ); + } + + template + std::size_t hash_value( std::unique_ptr const& x ) + { + return boost::hash_value( x.get() ); + } + +#endif + + // std::type_index + +#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) + + inline std::size_t hash_value( std::type_index const& v ) + { + return v.hash_code(); + } + +#endif + + // std::error_code, std::error_condition + +#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) + + inline std::size_t hash_value( std::error_code const& v ) + { + std::size_t seed = 0; + + boost::hash_combine( seed, v.value() ); + boost::hash_combine( seed, &v.category() ); + + return seed; + } + + inline std::size_t hash_value( std::error_condition const& v ) + { + std::size_t seed = 0; + + boost::hash_combine( seed, v.value() ); + boost::hash_combine( seed, &v.category() ); + + return seed; + } + +#endif + + // std::nullptr_t + +#if !defined(BOOST_NO_CXX11_NULLPTR) + + template + typename std::enable_if::value, std::size_t>::type + hash_value( T const& /*v*/ ) + { + return boost::hash_value( static_cast( nullptr ) ); + } + +#endif + + // std::optional + +#if !defined(BOOST_NO_CXX17_HDR_OPTIONAL) + + template + std::size_t hash_value( std::optional const& v ) + { + if( !v ) + { + // Arbitrary value for empty optional. + return 0x12345678; + } + else + { + return boost::hash()(*v); + } + } + +#endif + + // std::variant + +#if !defined(BOOST_NO_CXX17_HDR_VARIANT) + + inline std::size_t hash_value( std::monostate ) + { + return 0x87654321; + } + + template + std::size_t hash_value( std::variant const& v ) + { + std::size_t seed = 0; + + hash_combine( seed, v.index() ); + std::visit( [&seed](auto&& x) { hash_combine(seed, x); }, v ); + + return seed; + } + +#endif + + // + // boost::hash_combine + // + + template + inline void hash_combine( std::size_t& seed, T const& v ) + { + seed = boost::hash_detail::hash_mix( seed + 0x9e3779b9 + boost::hash()( v ) ); + } + + // + // boost::hash_range + // + + template + inline void hash_range( std::size_t& seed, It first, It last ) + { + seed = hash_detail::hash_range( seed, first, last ); + } + + template + inline std::size_t hash_range( It first, It last ) + { + std::size_t seed = 0; + + hash_range( seed, first, last ); + + return seed; + } + + // + // boost::hash_unordered_range + // + + template + inline void hash_unordered_range( std::size_t& seed, It first, It last ) + { + std::size_t r = 0; + std::size_t const s2( seed ); + + for( ; first != last; ++first ) + { + std::size_t s3( s2 ); + + hash_combine::value_type>( s3, *first ); + + r += s3; + } + + seed += r; + } + + template + inline std::size_t hash_unordered_range( It first, It last ) + { + std::size_t seed = 0; + + hash_unordered_range( seed, first, last ); + + return seed; + } + + // + // boost::hash + // + + template struct hash + { + typedef T argument_type; + typedef std::size_t result_type; + + std::size_t operator()( T const& val ) const + { + return hash_value( val ); + } + }; + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ( \ + ( defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION < 142 ) || \ + ( !defined(_MSVC_STL_VERSION) && defined(_CPPLIB_VER) && _CPPLIB_VER >= 520 ) ) + + // Dinkumware has stdext::hash_value for basic_string in :-/ + + template struct hash< std::basic_string > + { + typedef std::basic_string argument_type; + typedef std::size_t result_type; + + std::size_t operator()( std::basic_string const& val ) const + { + return boost::hash_value( val ); + } + }; + +#endif + + // boost::unordered::hash_is_avalanching + + namespace unordered + { + template struct hash_is_avalanching; + template struct hash_is_avalanching< boost::hash< std::basic_string > >: std::is_integral {}; + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + + template struct hash_is_avalanching< boost::hash< std::basic_string_view > >: std::is_integral {}; + +#endif + } // namespace unordered + +} // namespace boost + +#endif // #ifndef BOOST_FUNCTIONAL_HASH_HASH_HPP diff --git a/boost/container_hash/hash_fwd.hpp b/boost/container_hash/hash_fwd.hpp new file mode 100644 index 00000000..32388ac5 --- /dev/null +++ b/boost/container_hash/hash_fwd.hpp @@ -0,0 +1,37 @@ +// Copyright 2005-2009 Daniel James. +// Copyright 2021, 2022 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_FUNCTIONAL_HASH_FWD_HPP +#define BOOST_FUNCTIONAL_HASH_FWD_HPP + +#include + +namespace boost +{ + +namespace container_hash +{ + +template struct is_range; +template struct is_contiguous_range; +template struct is_unordered_range; +template struct is_described_class; +template struct is_tuple_like; + +} // namespace container_hash + +template struct hash; + +template void hash_combine( std::size_t& seed, T const& v ); + +template void hash_range( std::size_t&, It, It ); +template std::size_t hash_range( It, It ); + +template void hash_unordered_range( std::size_t&, It, It ); +template std::size_t hash_unordered_range( It, It ); + +} // namespace boost + +#endif // #ifndef BOOST_FUNCTIONAL_HASH_FWD_HPP diff --git a/boost/container_hash/is_contiguous_range.hpp b/boost/container_hash/is_contiguous_range.hpp new file mode 100644 index 00000000..c18db6b2 --- /dev/null +++ b/boost/container_hash/is_contiguous_range.hpp @@ -0,0 +1,98 @@ +// Copyright 2017, 2018 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_HASH_IS_CONTIGUOUS_RANGE_HPP_INCLUDED +#define BOOST_HASH_IS_CONTIGUOUS_RANGE_HPP_INCLUDED + +#include +#include +#include +#include + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1910) + +#include + +namespace boost +{ +namespace hash_detail +{ + +template + std::integral_constant< bool, std::is_same::value_type, T>::value && std::is_integral::value > + is_contiguous_range_check( It first, It last, T const*, T const*, S ); + +template decltype( is_contiguous_range_check( std::declval().begin(), std::declval().end(), std::declval().data(), std::declval().data() + std::declval().size(), std::declval().size() ) ) is_contiguous_range_( int ); +template std::false_type is_contiguous_range_( ... ); + +template struct is_contiguous_range: decltype( hash_detail::is_contiguous_range_( 0 ) ) +{ +}; + +} // namespace hash_detail + +namespace container_hash +{ + +template struct is_contiguous_range: std::integral_constant< bool, is_range::value && hash_detail::is_contiguous_range::value > +{ +}; + +} // namespace container_hash +} // namespace boost + +#else // !BOOST_WORKAROUND(BOOST_MSVC, < 1910) + +#include +#include +#include +#include + +namespace boost +{ +namespace container_hash +{ + +template struct is_contiguous_range: std::false_type +{ +}; + +template struct is_contiguous_range< std::basic_string >: std::true_type +{ +}; + +template struct is_contiguous_range< std::basic_string const >: std::true_type +{ +}; + +template struct is_contiguous_range< std::vector >: std::true_type +{ +}; + +template struct is_contiguous_range< std::vector const >: std::true_type +{ +}; + +template struct is_contiguous_range< std::vector >: std::false_type +{ +}; + +template struct is_contiguous_range< std::vector const >: std::false_type +{ +}; + +template struct is_contiguous_range< std::array >: std::true_type +{ +}; + +template struct is_contiguous_range< std::array const >: std::true_type +{ +}; + +} // namespace container_hash +} // namespace boost + +#endif // !BOOST_WORKAROUND(BOOST_MSVC, < 1910) + +#endif // #ifndef BOOST_HASH_IS_CONTIGUOUS_RANGE_HPP_INCLUDED diff --git a/boost/container_hash/is_described_class.hpp b/boost/container_hash/is_described_class.hpp new file mode 100644 index 00000000..88f8ed37 --- /dev/null +++ b/boost/container_hash/is_described_class.hpp @@ -0,0 +1,37 @@ +// Copyright 2022 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_HASH_IS_DESCRIBED_CLASS_HPP_INCLUDED +#define BOOST_HASH_IS_DESCRIBED_CLASS_HPP_INCLUDED + +#include +#include +#include + +namespace boost +{ +namespace container_hash +{ + +#if defined(BOOST_DESCRIBE_CXX11) + +template struct is_described_class: std::integral_constant::value && + describe::has_describe_members::value && + !std::is_union::value> +{ +}; + +#else + +template struct is_described_class: std::false_type +{ +}; + +#endif + +} // namespace container_hash +} // namespace boost + +#endif // #ifndef BOOST_HASH_IS_DESCRIBED_CLASS_HPP_INCLUDED diff --git a/boost/container_hash/is_range.hpp b/boost/container_hash/is_range.hpp new file mode 100644 index 00000000..f0b067ff --- /dev/null +++ b/boost/container_hash/is_range.hpp @@ -0,0 +1,37 @@ +// Copyright 2017 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_HASH_IS_RANGE_HPP_INCLUDED +#define BOOST_HASH_IS_RANGE_HPP_INCLUDED + +#include +#include + +namespace boost +{ + +namespace hash_detail +{ + +template + std::integral_constant< bool, !std::is_same::type, typename std::iterator_traits::value_type>::value > + is_range_check( It first, It last ); + +template decltype( is_range_check( std::declval().begin(), std::declval().end() ) ) is_range_( int ); +template std::false_type is_range_( ... ); + +} // namespace hash_detail + +namespace container_hash +{ + +template struct is_range: decltype( hash_detail::is_range_( 0 ) ) +{ +}; + +} // namespace container_hash + +} // namespace boost + +#endif // #ifndef BOOST_HASH_IS_RANGE_HPP_INCLUDED diff --git a/boost/container_hash/is_tuple_like.hpp b/boost/container_hash/is_tuple_like.hpp new file mode 100644 index 00000000..48728cd9 --- /dev/null +++ b/boost/container_hash/is_tuple_like.hpp @@ -0,0 +1,36 @@ +#ifndef BOOST_HASH_IS_TUPLE_LIKE_HPP_INCLUDED +#define BOOST_HASH_IS_TUPLE_LIKE_HPP_INCLUDED + +// Copyright 2017, 2022 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +namespace boost +{ +namespace hash_detail +{ + +template struct is_tuple_like_: std::false_type +{ +}; + +template struct is_tuple_like_::value == std::tuple_size::value> >: std::true_type +{ +}; + +} // namespace hash_detail + +namespace container_hash +{ + +template struct is_tuple_like: hash_detail::is_tuple_like_ +{ +}; + +} // namespace container_hash +} // namespace boost + +#endif // #ifndef BOOST_HASH_IS_TUPLE_LIKE_HPP_INCLUDED diff --git a/boost/container_hash/is_unordered_range.hpp b/boost/container_hash/is_unordered_range.hpp new file mode 100644 index 00000000..5a81b7d5 --- /dev/null +++ b/boost/container_hash/is_unordered_range.hpp @@ -0,0 +1,38 @@ +// Copyright 2017 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_HASH_IS_UNORDERED_RANGE_HPP_INCLUDED +#define BOOST_HASH_IS_UNORDERED_RANGE_HPP_INCLUDED + +#include +#include + +namespace boost +{ +namespace hash_detail +{ + +template struct has_hasher_: std::false_type +{ +}; + +template struct has_hasher_< T, std::integral_constant< bool, + std::is_same::value + > >: std::true_type +{ +}; + +} // namespace hash_detail + +namespace container_hash +{ + +template struct is_unordered_range: std::integral_constant< bool, is_range::value && hash_detail::has_hasher_::value > +{ +}; + +} // namespace container_hash +} // namespace boost + +#endif // #ifndef BOOST_HASH_IS_UNORDERED_RANGE_HPP_INCLUDED diff --git a/boost/core/detail/is_same.hpp b/boost/core/detail/is_same.hpp new file mode 100644 index 00000000..634d3004 --- /dev/null +++ b/boost/core/detail/is_same.hpp @@ -0,0 +1,39 @@ +#ifndef BOOST_CORE_DETAIL_IS_SAME_HPP_INCLUDED +#define BOOST_CORE_DETAIL_IS_SAME_HPP_INCLUDED + +// is_same::value is true when T1 == T2 +// +// Copyright 2014 Peter Dimov +// +// 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 + +#include + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +namespace boost +{ +namespace core +{ +namespace detail +{ + +template< class T1, class T2 > struct is_same +{ + BOOST_STATIC_CONSTANT( bool, value = false ); +}; + +template< class T > struct is_same< T, T > +{ + BOOST_STATIC_CONSTANT( bool, value = true ); +}; + +} // namespace detail +} // namespace core +} // namespace boost + +#endif // #ifndef BOOST_CORE_DETAIL_IS_SAME_HPP_INCLUDED diff --git a/boost/core/explicit_operator_bool.hpp b/boost/core/explicit_operator_bool.hpp new file mode 100644 index 00000000..d689f114 --- /dev/null +++ b/boost/core/explicit_operator_bool.hpp @@ -0,0 +1,163 @@ +/* + * Copyright Andrey Semashev 2007 - 2013. + * 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) + */ + +/*! + * \file explicit_operator_bool.hpp + * \author Andrey Semashev + * \date 08.03.2009 + * + * This header defines a compatibility macro that implements an unspecified + * \c bool operator idiom, which is superseded with explicit conversion operators in + * C++11. + */ + +#ifndef BOOST_CORE_EXPLICIT_OPERATOR_BOOL_HPP +#define BOOST_CORE_EXPLICIT_OPERATOR_BOOL_HPP + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + +/*! + * \brief The macro defines an explicit operator of conversion to \c bool + * + * The macro should be used inside the definition of a class that has to + * support the conversion. The class should also implement operator!, + * in terms of which the conversion operator will be implemented. + */ +#define BOOST_EXPLICIT_OPERATOR_BOOL()\ + BOOST_FORCEINLINE explicit operator bool () const\ + {\ + return !this->operator! ();\ + } + +/*! + * \brief The macro defines a noexcept explicit operator of conversion to \c bool + * + * The macro should be used inside the definition of a class that has to + * support the conversion. The class should also implement operator!, + * in terms of which the conversion operator will be implemented. + */ +#define BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()\ + BOOST_FORCEINLINE explicit operator bool () const BOOST_NOEXCEPT\ + {\ + return !this->operator! ();\ + } + +#if !BOOST_WORKAROUND(BOOST_GCC, < 40700) + +/*! + * \brief The macro defines a constexpr explicit operator of conversion to \c bool + * + * The macro should be used inside the definition of a class that has to + * support the conversion. The class should also implement operator!, + * in terms of which the conversion operator will be implemented. + */ +#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\ + BOOST_FORCEINLINE BOOST_CONSTEXPR explicit operator bool () const BOOST_NOEXCEPT\ + {\ + return !this->operator! ();\ + } + +#else + +#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL() BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + +#endif + +#else // !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + +#if (defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG) +// Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it +#define BOOST_NO_UNSPECIFIED_BOOL +#endif // (defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG) + +#if !defined(BOOST_NO_UNSPECIFIED_BOOL) + +namespace boost { + +namespace detail { + +#if !defined(_MSC_VER) && !defined(__IBMCPP__) + + struct unspecified_bool + { + // NOTE TO THE USER: If you see this in error messages then you tried + // to apply an unsupported operator on the object that supports + // explicit conversion to bool. + struct OPERATORS_NOT_ALLOWED; + static void true_value(OPERATORS_NOT_ALLOWED*) {} + }; + typedef void (*unspecified_bool_type)(unspecified_bool::OPERATORS_NOT_ALLOWED*); + +#else + + // MSVC and VACPP are too eager to convert pointer to function to void* even though they shouldn't + struct unspecified_bool + { + // NOTE TO THE USER: If you see this in error messages then you tried + // to apply an unsupported operator on the object that supports + // explicit conversion to bool. + struct OPERATORS_NOT_ALLOWED; + void true_value(OPERATORS_NOT_ALLOWED*) {} + }; + typedef void (unspecified_bool::*unspecified_bool_type)(unspecified_bool::OPERATORS_NOT_ALLOWED*); + +#endif + +} // namespace detail + +} // namespace boost + +#define BOOST_EXPLICIT_OPERATOR_BOOL()\ + BOOST_FORCEINLINE operator boost::detail::unspecified_bool_type () const\ + {\ + return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\ + } + +#define BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()\ + BOOST_FORCEINLINE operator boost::detail::unspecified_bool_type () const BOOST_NOEXCEPT\ + {\ + return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\ + } + +#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\ + BOOST_FORCEINLINE BOOST_CONSTEXPR operator boost::detail::unspecified_bool_type () const BOOST_NOEXCEPT\ + {\ + return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\ + } + +#else // !defined(BOOST_NO_UNSPECIFIED_BOOL) + +#define BOOST_EXPLICIT_OPERATOR_BOOL()\ + BOOST_FORCEINLINE operator bool () const\ + {\ + return !this->operator! ();\ + } + +#define BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()\ + BOOST_FORCEINLINE operator bool () const BOOST_NOEXCEPT\ + {\ + return !this->operator! ();\ + } + +#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\ + BOOST_FORCEINLINE BOOST_CONSTEXPR operator bool () const BOOST_NOEXCEPT\ + {\ + return !this->operator! ();\ + } + +#endif // !defined(BOOST_NO_UNSPECIFIED_BOOL) + +#endif // !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + +#endif // BOOST_CORE_EXPLICIT_OPERATOR_BOOL_HPP diff --git a/boost/core/invoke_swap.hpp b/boost/core/invoke_swap.hpp new file mode 100644 index 00000000..80562895 --- /dev/null +++ b/boost/core/invoke_swap.hpp @@ -0,0 +1,93 @@ +// Copyright (C) 2007, 2008 Steven Watanabe, Joseph Gauterin, Niels Dekker +// Copyright (C) 2023 Andrey Semashev +// +// 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) +// For more information, see http://www.boost.org + +#ifndef BOOST_CORE_INVOKE_SWAP_HPP +#define BOOST_CORE_INVOKE_SWAP_HPP + +// Note: the implementation of this utility contains various workarounds: +// - invoke_swap_impl is put outside the boost namespace, to avoid infinite +// recursion (causing stack overflow) when swapping objects of a primitive +// type. +// - std::swap is imported with a using-directive, rather than +// a using-declaration, because some compilers (including MSVC 7.1, +// Borland 5.9.3, and Intel 8.1) don't do argument-dependent lookup +// when it has a using-declaration instead. +// - The main entry function is called invoke_swap rather than swap +// to avoid forming an infinite recursion when the arguments are not +// swappable. + +#include +#include +#if __cplusplus >= 201103L || defined(BOOST_DINKUMWARE_STDLIB) +#include // for std::swap (C++11) +#else +#include // for std::swap (C++98) +#endif +#include // for std::size_t + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(BOOST_GCC) && (BOOST_GCC < 40700) +// gcc 4.6 ICEs on noexcept specifications below +#define BOOST_CORE_SWAP_NOEXCEPT_IF(x) +#else +#define BOOST_CORE_SWAP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x) +#endif + +namespace boost_swap_impl { + +// we can't use type_traits here + +template struct is_const { enum _vt { value = 0 }; }; +template struct is_const { enum _vt { value = 1 }; }; + +// Use std::swap if argument dependent lookup fails. +// We need to have this at namespace scope to be able to use unqualified swap() call +// in noexcept specification. +using namespace std; + +template +BOOST_GPU_ENABLED +inline void invoke_swap_impl(T& left, T& right) BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(swap(left, right))) +{ + swap(left, right); +} + +template +BOOST_GPU_ENABLED +inline void invoke_swap_impl(T (& left)[N], T (& right)[N]) + BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(::boost_swap_impl::invoke_swap_impl(left[0], right[0]))) +{ + for (std::size_t i = 0; i < N; ++i) + { + ::boost_swap_impl::invoke_swap_impl(left[i], right[i]); + } +} + +} // namespace boost_swap_impl + +namespace boost { +namespace core { + +template +BOOST_GPU_ENABLED +inline typename enable_if_c< !::boost_swap_impl::is_const::value >::type +invoke_swap(T& left, T& right) + BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(::boost_swap_impl::invoke_swap_impl(left, right))) +{ + ::boost_swap_impl::invoke_swap_impl(left, right); +} + +} // namespace core +} // namespace boost + +#undef BOOST_CORE_SWAP_NOEXCEPT_IF + +#endif // BOOST_CORE_INVOKE_SWAP_HPP diff --git a/boost/core/lightweight_test_trait.hpp b/boost/core/lightweight_test_trait.hpp new file mode 100644 index 00000000..eea23717 --- /dev/null +++ b/boost/core/lightweight_test_trait.hpp @@ -0,0 +1,91 @@ +#ifndef BOOST_CORE_LIGHTWEIGHT_TEST_TRAIT_HPP +#define BOOST_CORE_LIGHTWEIGHT_TEST_TRAIT_HPP + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) +# pragma once +#endif + +// boost/core/lightweight_test_trait.hpp +// +// BOOST_TEST_TRAIT_TRUE, BOOST_TEST_TRAIT_FALSE, BOOST_TEST_TRAIT_SAME +// +// Copyright 2014, 2021 Peter Dimov +// +// Copyright 2019 Glen Joseph Fernandes +// (glenjofe@gmail.com) +// +// 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 + +#include +#include +#include +#include + +namespace boost +{ +namespace detail +{ + +template< class T > inline void test_trait_impl( char const * trait, void (*)( T ), + bool expected, char const * file, int line, char const * function ) +{ + if( T::value == expected ) + { + test_results(); + } + else + { + BOOST_LIGHTWEIGHT_TEST_OSTREAM + << file << "(" << line << "): predicate '" << trait << "' [" + << boost::core::type_name() << "]" + << " test failed in function '" << function + << "' (should have been " << ( expected? "true": "false" ) << ")" + << std::endl; + + ++test_results().errors(); + } +} + +template inline bool test_trait_same_impl_( T ) +{ + return T::value; +} + +template inline void test_trait_same_impl( char const * types, + boost::core::detail::is_same same, char const * file, int line, char const * function ) +{ + if( test_trait_same_impl_( same ) ) + { + test_results(); + } + else + { + BOOST_LIGHTWEIGHT_TEST_OSTREAM + << file << "(" << line << "): test 'is_same<" << types << ">'" + << " failed in function '" << function + << "' ('" << boost::core::type_name() + << "' != '" << boost::core::type_name() << "')" + << std::endl; + + ++test_results().errors(); + } +} + +} // namespace detail +} // namespace boost + +#define BOOST_TEST_TRAIT_TRUE(type) ( ::boost::detail::test_trait_impl(#type, (void(*)type)0, true, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) ) +#define BOOST_TEST_TRAIT_FALSE(type) ( ::boost::detail::test_trait_impl(#type, (void(*)type)0, false, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) ) + +#if defined(__GNUC__) +// ignoring -Wvariadic-macros with #pragma doesn't work under GCC +# pragma GCC system_header +#endif + +#define BOOST_TEST_TRAIT_SAME(...) ( ::boost::detail::test_trait_same_impl(#__VA_ARGS__, ::boost::core::detail::is_same< __VA_ARGS__ >(), __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) ) + +#endif // #ifndef BOOST_CORE_LIGHTWEIGHT_TEST_TRAIT_HPP diff --git a/boost/core/ref.hpp b/boost/core/ref.hpp new file mode 100644 index 00000000..d29a4d6f --- /dev/null +++ b/boost/core/ref.hpp @@ -0,0 +1,345 @@ +#ifndef BOOST_CORE_REF_HPP +#define BOOST_CORE_REF_HPP + +#include +#include +#include +#include + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +// +// ref.hpp - ref/cref, useful helper functions +// +// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// Copyright (C) 2001, 2002 Peter Dimov +// Copyright (C) 2002 David Abrahams +// +// Copyright (C) 2014 Glen Joseph Fernandes +// (glenjofe@gmail.com) +// +// Copyright (C) 2014 Agustin Berge +// +// 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) +// +// See http://www.boost.org/libs/core/doc/html/core/ref.html for documentation. +// + +/** + @file +*/ + +/** + Boost namespace. +*/ +namespace boost +{ + +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1600 ) + + struct ref_workaround_tag {}; + +#endif + +namespace detail +{ + +template< class Y, class T > struct ref_convertible +{ + typedef char (&yes) [1]; + typedef char (&no) [2]; + + static yes f( T* ); + static no f( ... ); + + enum _vt { value = sizeof( (f)( static_cast(0) ) ) == sizeof(yes) }; +}; + +#if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) +struct ref_empty +{ +}; +#endif + +} // namespace detail + +// reference_wrapper + +/** + @brief Contains a reference to an object of type `T`. + + `reference_wrapper` is primarily used to "feed" references to + function templates (algorithms) that take their parameter by + value. It provides an implicit conversion to `T&`, which + usually allows the function templates to work on references + unmodified. +*/ +template class reference_wrapper +{ +public: + /** + Type `T`. + */ + typedef T type; + + /** + Constructs a `reference_wrapper` object that stores a + reference to `t`. + + @remark Does not throw. + */ + BOOST_FORCEINLINE explicit reference_wrapper(T& t) BOOST_NOEXCEPT : t_(boost::addressof(t)) {} + +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1600 ) + + BOOST_FORCEINLINE explicit reference_wrapper( T & t, ref_workaround_tag ) BOOST_NOEXCEPT : t_( boost::addressof( t ) ) {} + +#endif + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + /** + @remark Construction from a temporary object is disabled. + */ + BOOST_DELETED_FUNCTION(reference_wrapper(T&& t)) +public: +#endif + + template friend class reference_wrapper; + + /** + Constructs a `reference_wrapper` object that stores the + reference stored in the compatible `reference_wrapper` `r`. + + @remark Only enabled when `Y*` is convertible to `T*`. + @remark Does not throw. + */ +#if !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + template::value>::type> + reference_wrapper( reference_wrapper r ) BOOST_NOEXCEPT : t_( r.t_ ) + { + } +#else + template reference_wrapper( reference_wrapper r, + typename enable_if_c::value, + boost::detail::ref_empty>::type = boost::detail::ref_empty() ) BOOST_NOEXCEPT : t_( r.t_ ) + { + } +#endif + + /** + @return The stored reference. + @remark Does not throw. + */ + BOOST_FORCEINLINE operator T& () const BOOST_NOEXCEPT { return *t_; } + + /** + @return The stored reference. + @remark Does not throw. + */ + BOOST_FORCEINLINE T& get() const BOOST_NOEXCEPT { return *t_; } + + /** + @return A pointer to the object referenced by the stored + reference. + @remark Does not throw. + */ + BOOST_FORCEINLINE T* get_pointer() const BOOST_NOEXCEPT { return t_; } + +private: + + T* t_; +}; + +// ref + +/** + @cond +*/ +#if defined( BOOST_BORLANDC ) && BOOST_WORKAROUND( BOOST_BORLANDC, BOOST_TESTED_AT(0x581) ) +# define BOOST_REF_CONST +#else +# define BOOST_REF_CONST const +#endif +/** + @endcond +*/ + +/** + @return `reference_wrapper(t)` + @remark Does not throw. +*/ +template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST ref( T & t ) BOOST_NOEXCEPT +{ +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1600 ) + + return reference_wrapper( t, ref_workaround_tag() ); + +#else + + return reference_wrapper( t ); + +#endif +} + +// cref + +/** + @return `reference_wrapper(t)` + @remark Does not throw. +*/ +template BOOST_FORCEINLINE reference_wrapper BOOST_REF_CONST cref( T const & t ) BOOST_NOEXCEPT +{ + return reference_wrapper(t); +} + +#undef BOOST_REF_CONST + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +/** + @cond +*/ +#if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) +# define BOOST_REF_DELETE +#else +# define BOOST_REF_DELETE = delete +#endif +/** + @endcond +*/ + +/** + @remark Construction from a temporary object is disabled. +*/ +template void ref(T const&&) BOOST_REF_DELETE; + +/** + @remark Construction from a temporary object is disabled. +*/ +template void cref(T const&&) BOOST_REF_DELETE; + +#undef BOOST_REF_DELETE + +#endif + +// is_reference_wrapper + +/** + @brief Determine if a type `T` is an instantiation of + `reference_wrapper`. + + The value static constant will be true if the type `T` is a + specialization of `reference_wrapper`. +*/ +template struct is_reference_wrapper +{ + BOOST_STATIC_CONSTANT( bool, value = false ); +}; + +/** + @cond +*/ +template struct is_reference_wrapper< reference_wrapper > +{ + BOOST_STATIC_CONSTANT( bool, value = true ); +}; + +#if !defined(BOOST_NO_CV_SPECIALIZATIONS) + +template struct is_reference_wrapper< reference_wrapper const > +{ + BOOST_STATIC_CONSTANT( bool, value = true ); +}; + +template struct is_reference_wrapper< reference_wrapper volatile > +{ + BOOST_STATIC_CONSTANT( bool, value = true ); +}; + +template struct is_reference_wrapper< reference_wrapper const volatile > +{ + BOOST_STATIC_CONSTANT( bool, value = true ); +}; + +#endif // !defined(BOOST_NO_CV_SPECIALIZATIONS) + +/** + @endcond +*/ + + +// unwrap_reference + +/** + @brief Find the type in a `reference_wrapper`. + + The `typedef` type is `T::type` if `T` is a + `reference_wrapper`, `T` otherwise. +*/ +template struct unwrap_reference +{ + typedef T type; +}; + +/** + @cond +*/ +template struct unwrap_reference< reference_wrapper > +{ + typedef T type; +}; + +#if !defined(BOOST_NO_CV_SPECIALIZATIONS) + +template struct unwrap_reference< reference_wrapper const > +{ + typedef T type; +}; + +template struct unwrap_reference< reference_wrapper volatile > +{ + typedef T type; +}; + +template struct unwrap_reference< reference_wrapper const volatile > +{ + typedef T type; +}; + +#endif // !defined(BOOST_NO_CV_SPECIALIZATIONS) + +/** + @endcond +*/ + +// unwrap_ref + +/** + @return `unwrap_reference::type&(t)` + @remark Does not throw. +*/ +template BOOST_FORCEINLINE typename unwrap_reference::type& unwrap_ref( T & t ) BOOST_NOEXCEPT +{ + return t; +} + +// get_pointer + +/** + @cond +*/ +template BOOST_FORCEINLINE T* get_pointer( reference_wrapper const & r ) BOOST_NOEXCEPT +{ + return r.get_pointer(); +} +/** + @endcond +*/ + +} // namespace boost + +#endif // #ifndef BOOST_CORE_REF_HPP diff --git a/boost/core/snprintf.hpp b/boost/core/snprintf.hpp new file mode 100644 index 00000000..91e252b4 --- /dev/null +++ b/boost/core/snprintf.hpp @@ -0,0 +1,173 @@ +/* + * Copyright Andrey Semashev 2022. + * 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) + */ +/*! + * \file snprintf.hpp + * \author Andrey Semashev + * \date 06.12.2022 + * + * \brief The header provides more portable definition of snprintf and vsnprintf, + * as well as \c wchar_t counterparts. + */ + +#ifndef BOOST_CORE_SNPRINTF_HPP_INCLUDED_ +#define BOOST_CORE_SNPRINTF_HPP_INCLUDED_ + +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#if defined(__MINGW32__) + +#include +#include +#if !defined(__MINGW64_VERSION_MAJOR) +#include +#endif + +// MinGW32 and MinGW-w64 provide their own snprintf implementations that are compliant with the C standard. +#define BOOST_CORE_DETAIL_MINGW_SNPRINTF + +#elif (defined(BOOST_MSSTL_VERSION) && BOOST_MSSTL_VERSION < 140) + +#include +#include +#include + +// MSVC snprintfs are not conforming but they are good enough for typical use cases. +#define BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF + +#endif + +namespace boost { + +namespace core { + +#if defined(BOOST_CORE_DETAIL_MINGW_SNPRINTF) || defined(BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF) + +#if defined(BOOST_CORE_DETAIL_MINGW_SNPRINTF) + +inline int vsnprintf(char* buf, std::size_t size, const char* format, std::va_list args) +{ + return __mingw_vsnprintf(buf, size, format, args); +} + +inline int vswprintf(wchar_t* buf, std::size_t size, const wchar_t* format, std::va_list args) +{ +#if defined(__MINGW64_VERSION_MAJOR) + int res = __mingw_vsnwprintf(buf, size, format, args); + // __mingw_vsnwprintf returns the number of characters to be printed, but (v)swprintf is expected to return -1 on truncation + if (static_cast< unsigned int >(res) >= size) + res = -1; + return res; +#else + // Legacy MinGW32 does not provide __mingw_vsnwprintf, so use _vsnwprintf from MSVC CRT + if (BOOST_UNLIKELY(size == 0u || size > static_cast< std::size_t >(INT_MAX))) + return -1; + + int res = _vsnwprintf(buf, size, format, args); + // (v)swprintf is expected to return -1 on truncation, so we only need to ensure the output is null-terminated + if (static_cast< unsigned int >(res) >= size) + { + buf[size - 1u] = L'\0'; + res = -1; + } + + return res; +#endif +} + +#elif defined(BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF) + +#if defined(_MSC_VER) +#pragma warning(push) +// '_vsnprintf': This function or variable may be unsafe. Consider using _vsnprintf_s instead. +#pragma warning(disable: 4996) +#endif + +inline int vsnprintf(char* buf, std::size_t size, const char* format, std::va_list args) +{ + if (BOOST_UNLIKELY(size == 0u)) + return 0; + if (BOOST_UNLIKELY(size > static_cast< std::size_t >(INT_MAX))) + return -1; + + buf[size - 1u] = '\0'; + int res = _vsnprintf(buf, size, format, args); + if (static_cast< unsigned int >(res) >= size) + { + // _vsnprintf returns -1 if the output was truncated and in case of other errors. + // Detect truncation by checking whether the output buffer was written over entirely. + if (buf[size - 1u] != '\0') + { + buf[size - 1u] = '\0'; + res = static_cast< int >(size); + } + } + + return res; +} + +inline int vswprintf(wchar_t* buf, std::size_t size, const wchar_t* format, std::va_list args) +{ + if (BOOST_UNLIKELY(size == 0u || size > static_cast< std::size_t >(INT_MAX))) + return -1; + + int res = _vsnwprintf(buf, size, format, args); + // (v)swprintf is expected to return -1 on truncation, so we only need to ensure the output is null-terminated + if (static_cast< unsigned int >(res) >= size) + { + buf[size - 1u] = L'\0'; + res = -1; + } + + return res; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#endif + +inline int snprintf(char* buf, std::size_t size, const char* format, ...) +{ + std::va_list args; + va_start(args, format); + int res = vsnprintf(buf, size, format, args); + va_end(args); + return res; +} + +inline int swprintf(wchar_t* buf, std::size_t size, const wchar_t* format, ...) +{ + std::va_list args; + va_start(args, format); + int res = vswprintf(buf, size, format, args); + va_end(args); + return res; +} + +#else // defined(BOOST_CORE_DETAIL_MINGW_SNPRINTF) || defined(BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF) + +// Standard-conforming compilers already have the correct snprintfs +using ::snprintf; +using ::vsnprintf; + +using ::swprintf; +using ::vswprintf; + +#endif // defined(BOOST_CORE_DETAIL_MINGW_SNPRINTF) || defined(BOOST_CORE_DETAIL_MSVC_LEGACY_SNPRINTF) + +} // namespace core + +} // namespace boost + +#endif // BOOST_CORE_SNPRINTF_HPP_INCLUDED_ diff --git a/boost/core/type_name.hpp b/boost/core/type_name.hpp new file mode 100644 index 00000000..773b5f68 --- /dev/null +++ b/boost/core/type_name.hpp @@ -0,0 +1,1181 @@ +#ifndef BOOST_CORE_TYPE_NAME_HPP_INCLUDED +#define BOOST_CORE_TYPE_NAME_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// std::string boost::core::type_name() +// +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) +# include +#endif + +namespace boost +{ +namespace core +{ +namespace detail +{ + +// tn_identity + +template struct tn_identity +{ + typedef T type; +}; + +// tn_remove_prefix + +inline bool tn_remove_prefix( std::string& str, char const* prefix ) +{ + std::size_t n = std::strlen( prefix ); + + if( str.substr( 0, n ) == prefix ) + { + str = str.substr( n ); + return true; + } + else + { + return false; + } +} + +#if !defined(BOOST_NO_TYPEID) + +// typeid_name + +inline std::string fix_typeid_name( char const* n ) +{ + std::string r = boost::core::demangle( n ); + +#if defined(_MSC_VER) + + tn_remove_prefix( r, "class " ); + tn_remove_prefix( r, "struct " ); + tn_remove_prefix( r, "enum " ); + +#endif + + // libc++ inline namespace + + if( tn_remove_prefix( r, "std::__1::" ) ) + { + r = "std::" + r; + } + + // libstdc++ inline namespace + + if( tn_remove_prefix( r, "std::__cxx11::" ) ) + { + r = "std::" + r; + } + +#if defined(BOOST_MSVC) && BOOST_MSVC == 1600 + + // msvc-10.0 puts TR1 things in std::tr1 + + if( tn_remove_prefix( r, "std::tr1::" ) ) + { + r = "std::" + r; + } + +#endif + + return r; +} + +// class types can be incomplete +template std::string typeid_name_impl( int T::* ) +{ + std::string r = fix_typeid_name( typeid(T[1]).name() ); + return r.substr( 0, r.size() - 4 ); // remove ' [1]' suffix +} + +template std::string typeid_name_impl( ... ) +{ + return fix_typeid_name( typeid(T).name() ); +} + +template std::string typeid_name() +{ + return typeid_name_impl( 0 ); +} + +// template names + +template std::string class_template_name() +{ +#if defined(BOOST_GCC) + + std::string r = typeid_name(); + +#else + + std::string r = typeid_name(); + +#endif + return r.substr( 0, r.find( '<' ) ); +} + +template std::string sequence_template_name() +{ + return detail::class_template_name(); +} + +template std::string set_template_name() +{ + return detail::class_template_name(); +} + +template std::string map_template_name() +{ + return detail::class_template_name(); +} + +template std::string array_template_name() +{ + return detail::class_template_name(); +} + +#else // #if !defined(BOOST_NO_TYPEID) + +template std::string typeid_name() +{ + return "_Tp"; +} + +template std::string class_template_name() +{ + return "_Tm"; +} + +template std::string sequence_template_name() +{ + return "_Sq"; +} + +template std::string set_template_name() +{ + return "_St"; +} + +template std::string map_template_name() +{ + return "_Mp"; +} + +template std::string array_template_name() +{ + return "_Ar"; +} + +#endif + +// tn_to_string + +#if defined(BOOST_MSVC) +# pragma warning( push ) +# pragma warning( disable: 4996 ) +#endif + +// Use snprintf if available as some compilers (clang 14.0) issue deprecation warnings for sprintf +#if ( defined(_MSC_VER) && _MSC_VER < 1900 ) || ( defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) ) +# define BOOST_CORE_DETAIL_SNPRINTF(buffer, format, arg) std::sprintf(buffer, format, arg) +#else +# define BOOST_CORE_DETAIL_SNPRINTF(buffer, format, arg) std::snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), format, arg) +#endif + +inline std::string tn_to_string( std::size_t n ) +{ + char buffer[ 32 ]; + BOOST_CORE_DETAIL_SNPRINTF( buffer, "%lu", static_cast< unsigned long >( n ) ); + + return buffer; +} + +#undef BOOST_CORE_DETAIL_SNPRINTF + +#if defined(BOOST_MSVC) +# pragma warning( pop ) +#endif + +// tn_holder + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return typeid_name() + suffix; + } +}; + +// integrals + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "bool" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "char" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "signed char" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned char" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "short" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned short" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "int" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "long" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned long" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "long long" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned long long" + suffix; + } +}; + +#if defined(BOOST_HAS_INT128) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "__int128" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "unsigned __int128" + suffix; + } +}; + +#endif + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "wchar_t" + suffix; + } +}; + +#if !defined(BOOST_NO_CXX11_CHAR16_T) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "char16_t" + suffix; + } +}; + +#endif + +#if !defined(BOOST_NO_CXX11_CHAR32_T) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "char32_t" + suffix; + } +}; + +#endif + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "char8_t" + suffix; + } +}; + +#endif + +#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::byte" + suffix; + } +}; + +#endif + +// floating point + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "float" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "double" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "long double" + suffix; + } +}; + +// void + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "void" + suffix; + } +}; + +// nullptr_t + +#if !defined(BOOST_NO_CXX11_NULLPTR) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::nullptr_t" + suffix; + } +}; + +#endif + +// cv + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( " const" + suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( " volatile" + suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( " const volatile" + suffix ); + } +}; + +// refs + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( "&" + suffix ); + } +}; + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( "&&" + suffix ); + } +}; + +#endif + +// function types + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +// tn_add_each + +template int tn_add_each_impl( std::string& st ) +{ + if( !st.empty() ) st += ", "; + st += tn_holder::type_name( "" ); + return 0; +} + +template std::string tn_add_each() +{ + std::string st; + + typedef int A[ sizeof...(T) + 1 ]; + (void)A{ 0, tn_add_each_impl( st )... }; + + return st; +} + +template std::string function_type_name( tn_identity, std::string const& trailer, std::string const& suffix ) +{ + std::string r = tn_holder::type_name( "" ); + + if( !suffix.empty() ) + { + r += '('; + + if( suffix[ 0 ] == ' ' ) + { + r += suffix.substr( 1 ); + } + else + { + r += suffix; + } + + r += ')'; + } + + r += '(' + tn_add_each() + ')'; + r += trailer; + + return r; +} + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), "", suffix ); + } +}; + +#if !defined(BOOST_MSVC) || BOOST_MSVC >= 1900 + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile", suffix ); + } +}; + +#endif + +#if !defined(BOOST_NO_CXX11_REF_QUALIFIERS) + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " &", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const &", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile &", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile &", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " &&", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const &&", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile &&", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile &&", suffix ); + } +}; + +#endif + +#if defined( __cpp_noexcept_function_type ) || defined( _NOEXCEPT_TYPES_SUPPORTED ) + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " & noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const & noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile & noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile & noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " && noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const && noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile && noexcept", suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile && noexcept", suffix ); + } +}; + +#endif + +#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +// pointers + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( "*" + suffix ); + } +}; + +// arrays + +template std::pair array_prefix_suffix( tn_identity ) +{ + return std::pair( tn_holder::type_name( "" ), "" ); +} + +template std::pair array_prefix_suffix( tn_identity ) +{ + std::pair r = detail::array_prefix_suffix( tn_identity() ); + + r.second = '[' + tn_to_string( N ) + ']' + r.second; + + return r; +} + +template std::string array_type_name( tn_identity, std::string const& suffix ) +{ + std::pair r = detail::array_prefix_suffix( tn_identity() ); + + if( suffix.empty() ) + { + return r.first + "[]" + r.second; + } + else + { + return r.first + '(' + suffix + ")[]" + r.second; + } +} + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; + +template std::string array_type_name( tn_identity, std::string const& suffix ) +{ + std::pair r = detail::array_prefix_suffix( tn_identity() ); + + if( suffix.empty() ) + { + return r.first + r.second; + } + else + { + return r.first + '(' + suffix + ")" + r.second; + } +} + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::array_type_name( tn_identity(), suffix ); + } +}; + +// pointers to members + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return tn_holder::type_name( ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; + +#if defined(BOOST_MSVC) && BOOST_MSVC < 1900 + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), "", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " volatile", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; + +template struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return detail::function_type_name( tn_identity(), " const volatile", ' ' + tn_holder::type_name( "" ) + "::*" + suffix ); + } +}; + +#endif // #if defined(BOOST_MSVC) && BOOST_MSVC < 1900 + +#endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +// strings + +template class L, class Ch> struct tn_holder< L, std::allocator > > +{ + static std::string type_name( std::string const& suffix ) + { + std::string tn = sequence_template_name< L, std::allocator > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::string" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::wstring" + suffix; + } +}; + +#if !defined(BOOST_NO_CXX11_CHAR16_T) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::u16string" + suffix; + } +}; + +#endif + +#if !defined(BOOST_NO_CXX11_CHAR32_T) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::u32string" + suffix; + } +}; + +#endif + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + +template<> struct tn_holder< std::basic_string > +{ + static std::string type_name( std::string const& suffix ) + { + return "std::u8string" + suffix; + } +}; + +#endif + +// string views (et al) + +template class L, class Ch> struct tn_holder< L > > +{ + static std::string type_name( std::string const& suffix ) + { + std::string tn = sequence_template_name< L > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; + +// needed for libstdc++ +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::ostream" + suffix; + } +}; + +#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::string_view" + suffix; + } +}; + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::wstring_view" + suffix; + } +}; + +#if !defined(BOOST_NO_CXX11_CHAR16_T) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::u16string_view" + suffix; + } +}; + +#endif + +#if !defined(BOOST_NO_CXX11_CHAR32_T) + +template<> struct tn_holder +{ + static std::string type_name( std::string const& suffix ) + { + return "std::u32string_view" + suffix; + } +}; + +#endif + +#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L + +template<> struct tn_holder< std::basic_string_view > +{ + static std::string type_name( std::string const& suffix ) + { + return "std::u8string_view" + suffix; + } +}; + +#endif + +#endif + +// class templates + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +template class L, class... T> struct tn_holder< L > +{ + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::class_template_name< L >(); + std::string st = tn_add_each(); + + return tn + '<' + st + '>' + suffix; + } +}; + +#else + +template class L, class T1> struct tn_holder< L > +{ + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::class_template_name< L >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; + +template class L, class T1, class T2> struct tn_holder< L > +{ + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::class_template_name< L >(); + return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_holder::type_name( "" ) + '>' + suffix; + } +}; + +#endif + +// sequence containers + +template class L, class T> struct tn_holder< L > > +{ + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::sequence_template_name< L > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; + +// set + +template class L, class T> struct tn_holder< L, std::allocator > > +{ + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::set_template_name< L, std::allocator > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; + +// map + +template class L, class T, class U> struct tn_holder< L, std::allocator > > > +{ + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::map_template_name< L, std::allocator > > >(); + return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_holder::type_name( "" ) + '>' + suffix; + } +}; + +#if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) + +// unordered_set + +template class L, class T> struct tn_holder< L, std::equal_to, std::allocator > > +{ + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::set_template_name< L, std::equal_to, std::allocator > >(); + return tn + '<' + tn_holder::type_name( "" ) + '>' + suffix; + } +}; + +// unordered_map + +template class L, class T, class U> struct tn_holder< L, std::equal_to, std::allocator > > > +{ + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::map_template_name< L, std::equal_to, std::allocator > > >(); + return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_holder::type_name( "" ) + '>' + suffix; + } +}; + +#endif + +// array + +template class L, class T, std::size_t N> struct tn_holder< L > +{ + static std::string type_name( std::string const& suffix ) + { + std::string tn = detail::array_template_name< L >(); + return tn + '<' + tn_holder::type_name( "" ) + ", " + tn_to_string( N ) + '>' + suffix; + } +}; + +} // namespace detail + +template std::string type_name() +{ + return core::detail::tn_holder::type_name( "" ); +} + +} // namespace core +} // namespace boost + +#endif // #ifndef BOOST_CORE_TYPE_NAME_HPP_INCLUDED diff --git a/boost/cregex.hpp b/boost/cregex.hpp new file mode 100644 index 00000000..78012dd6 --- /dev/null +++ b/boost/cregex.hpp @@ -0,0 +1,43 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org/libs/regex for most recent version. + * FILE cregex.cpp + * VERSION see + * DESCRIPTION: Declares POSIX API functions + * + boost::RegEx high level wrapper. + */ + +#ifndef BOOST_RE_CREGEX_HPP +#define BOOST_RE_CREGEX_HPP + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif + +#ifdef BOOST_REGEX_CXX03 +#include +#else +#include +#endif + +#endif /* include guard */ + + + + + + + + + + diff --git a/boost/describe/bases.hpp b/boost/describe/bases.hpp new file mode 100644 index 00000000..b01313e0 --- /dev/null +++ b/boost/describe/bases.hpp @@ -0,0 +1,50 @@ +#ifndef BOOST_DESCRIBE_BASES_HPP_INCLUDED +#define BOOST_DESCRIBE_BASES_HPP_INCLUDED + +// Copyright 2020, 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include + +#if defined(BOOST_DESCRIBE_CXX11) + +#include +#include + +namespace boost +{ +namespace describe +{ +namespace detail +{ + +template using _describe_bases = decltype( boost_base_descriptor_fn( static_cast(0) ) ); + +template struct base_filter +{ + template using fn = mp11::mp_bool< ( M & mod_any_access & T::modifiers ) != 0 >; +}; + +template struct has_describe_bases: std::false_type +{ +}; + +template struct has_describe_bases>>: std::true_type +{ +}; + +} // namespace detail + +template using describe_bases = mp11::mp_copy_if_q, detail::base_filter>; + +template using has_describe_bases = detail::has_describe_bases; + +} // namespace describe +} // namespace boost + +#endif // !defined(BOOST_DESCRIBE_CXX11) + +#endif // #ifndef BOOST_DESCRIBE_BASES_HPP_INCLUDED diff --git a/boost/describe/detail/config.hpp b/boost/describe/detail/config.hpp new file mode 100644 index 00000000..c24a070e --- /dev/null +++ b/boost/describe/detail/config.hpp @@ -0,0 +1,40 @@ +#ifndef BOOST_DESCRIBE_DETAIL_CONFIG_HPP_INCLUDED +#define BOOST_DESCRIBE_DETAIL_CONFIG_HPP_INCLUDED + +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#if __cplusplus >= 201402L + +# define BOOST_DESCRIBE_CXX14 +# define BOOST_DESCRIBE_CXX11 + +#elif defined(_MSC_VER) && _MSC_VER >= 1900 + +# define BOOST_DESCRIBE_CXX14 +# define BOOST_DESCRIBE_CXX11 + +#elif __cplusplus >= 201103L + +# define BOOST_DESCRIBE_CXX11 + +# if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 7 +# undef BOOST_DESCRIBE_CXX11 +# endif + +#endif + +#if defined(BOOST_DESCRIBE_CXX11) +# define BOOST_DESCRIBE_CONSTEXPR_OR_CONST constexpr +#else +# define BOOST_DESCRIBE_CONSTEXPR_OR_CONST const +#endif + +#if defined(__clang__) +# define BOOST_DESCRIBE_MAYBE_UNUSED __attribute__((unused)) +#else +# define BOOST_DESCRIBE_MAYBE_UNUSED +#endif + +#endif // #ifndef BOOST_DESCRIBE_DETAIL_CONFIG_HPP_INCLUDED diff --git a/boost/describe/detail/cx_streq.hpp b/boost/describe/detail/cx_streq.hpp new file mode 100644 index 00000000..15e87dc2 --- /dev/null +++ b/boost/describe/detail/cx_streq.hpp @@ -0,0 +1,30 @@ +#ifndef BOOST_DESCRIBE_DETAIL_CX_STREQ_HPP_INCLUDED +#define BOOST_DESCRIBE_DETAIL_CX_STREQ_HPP_INCLUDED + +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#if defined(BOOST_DESCRIBE_CXX11) + +namespace boost +{ +namespace describe +{ +namespace detail +{ + +constexpr bool cx_streq( char const * s1, char const * s2 ) +{ + return s1[0] == s2[0] && ( s1[0] == 0 || cx_streq( s1 + 1, s2 + 1 ) ); +} + +} // namespace detail +} // namespace describe +} // namespace boost + +#endif // defined(BOOST_DESCRIBE_CXX11) + +#endif // #ifndef BOOST_DESCRIBE_DETAIL_CX_STREQ_HPP_INCLUDED diff --git a/boost/describe/detail/void_t.hpp b/boost/describe/detail/void_t.hpp new file mode 100644 index 00000000..f304250d --- /dev/null +++ b/boost/describe/detail/void_t.hpp @@ -0,0 +1,32 @@ +#ifndef BOOST_DESCRIBE_DETAIL_VOID_T_HPP_INCLUDED +#define BOOST_DESCRIBE_DETAIL_VOID_T_HPP_INCLUDED + +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#if defined(BOOST_DESCRIBE_CXX11) + +namespace boost +{ +namespace describe +{ +namespace detail +{ + +template struct make_void +{ + using type = void; +}; + +template using void_t = typename make_void::type; + +} // namespace detail +} // namespace describe +} // namespace boost + +#endif // defined(BOOST_DESCRIBE_CXX11) + +#endif // #ifndef BOOST_DESCRIBE_DETAIL_VOID_T_HPP_INCLUDED diff --git a/boost/describe/members.hpp b/boost/describe/members.hpp new file mode 100644 index 00000000..828c4955 --- /dev/null +++ b/boost/describe/members.hpp @@ -0,0 +1,161 @@ +#ifndef BOOST_DESCRIBE_DATA_MEMBERS_HPP_INCLUDED +#define BOOST_DESCRIBE_DATA_MEMBERS_HPP_INCLUDED + +// Copyright 2020 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include + +#if defined(BOOST_DESCRIBE_CXX11) + +#include +#include +#include +#include +#include +#include + +namespace boost +{ +namespace describe +{ +namespace detail +{ + +// _describe_members + +template using _describe_public_members = decltype( boost_public_member_descriptor_fn( static_cast(0) ) ); +template using _describe_protected_members = decltype( boost_protected_member_descriptor_fn( static_cast(0) ) ); +template using _describe_private_members = decltype( boost_private_member_descriptor_fn( static_cast(0) ) ); + +template using _describe_members = mp11::mp_append<_describe_public_members, _describe_protected_members, _describe_private_members>; + +// describe_inherited_members + +// T: type +// V: list of virtual bases visited so far +template struct describe_inherited_members_impl; +template using describe_inherited_members = typename describe_inherited_members_impl::type; + +// L: list of base class descriptors +// T: derived type +// V: list of virtual bases visited so far +template struct describe_inherited_members2_impl; +template using describe_inherited_members2 = typename describe_inherited_members2_impl::type; + +template struct describe_inherited_members_impl +{ + using R1 = describe_inherited_members2, T, V>; + using R2 = _describe_members; + + using type = mp11::mp_append; +}; + +template class L, class T, class V> struct describe_inherited_members2_impl, T, V> +{ + using type = L<>; +}; + +template using name_matches = mp11::mp_bool< cx_streq( D1::name, D2::name ) >; + +template using name_is_hidden = mp11::mp_any_of_q>; + +constexpr unsigned cx_max( unsigned m1, unsigned m2 ) +{ + return m1 > m2? m1: m2; +} + +template struct update_modifiers +{ + template struct fn + { + using L = _describe_members; + static constexpr unsigned hidden = name_is_hidden::value? mod_hidden: 0; + + static constexpr unsigned mods = D::modifiers; + static constexpr unsigned access = cx_max( mods & mod_any_access, Bm & mod_any_access ); + + static constexpr decltype(D::pointer) pointer = D::pointer; + static constexpr decltype(D::name) name = D::name; + static constexpr unsigned modifiers = ( mods & ~mod_any_access ) | access | mod_inherited | hidden; + }; +}; + +#ifndef __cpp_inline_variables +template template constexpr decltype(D::pointer) update_modifiers::fn::pointer; +template template constexpr decltype(D::name) update_modifiers::fn::name; +template template constexpr unsigned update_modifiers::fn::modifiers; +#endif + +template struct gather_virtual_bases_impl; +template using gather_virtual_bases = typename gather_virtual_bases_impl::type; + +template struct gather_virtual_bases_impl +{ + using B = typename D::type; + static constexpr unsigned M = D::modifiers; + + using R1 = mp11::mp_transform>; + using R2 = mp11::mp_apply; + + using type = mp11::mp_if_c<(M & mod_virtual) != 0, mp11::mp_push_front, R2>; +}; + +template class L, class D1, class... D, class T, class V> struct describe_inherited_members2_impl, T, V> +{ + using B = typename D1::type; + static constexpr unsigned M = D1::modifiers; + + using R1 = mp11::mp_if_c<(M & mod_virtual) && mp11::mp_contains::value, L<>, describe_inherited_members>; + + using R2 = mp11::mp_transform_q, R1>; + + using V2 = mp11::mp_append>; + using R3 = describe_inherited_members2, T, V2>; + + using type = mp11::mp_append; +}; + +// describe_members + +template using describe_members = mp11::mp_eval_if_c<(M & mod_inherited) == 0, _describe_members, describe_inherited_members, T, mp11::mp_list<>>; + +// member_filter + +template struct member_filter +{ + template using fn = mp11::mp_bool< + (M & mod_any_access & T::modifiers) != 0 && + ( (M & mod_any_member) != 0 || (M & mod_static) == (T::modifiers & mod_static) ) && + ( (M & mod_any_member) != 0 || (M & mod_function) == (T::modifiers & mod_function) ) && + (M & mod_hidden) >= (T::modifiers & mod_hidden) + >; +}; + +// has_describe_members + +template struct has_describe_members: std::false_type +{ +}; + +template struct has_describe_members>>: std::true_type +{ +}; + +} // namespace detail + +template using describe_members = mp11::mp_copy_if_q, detail::member_filter>; + +template using has_describe_members = detail::has_describe_members; + +} // namespace describe +} // namespace boost + +#endif // !defined(BOOST_DESCRIBE_CXX11) + +#endif // #ifndef BOOST_DESCRIBE_DATA_MEMBERS_HPP_INCLUDED diff --git a/boost/describe/modifiers.hpp b/boost/describe/modifiers.hpp new file mode 100644 index 00000000..06650ea1 --- /dev/null +++ b/boost/describe/modifiers.hpp @@ -0,0 +1,33 @@ +#ifndef BOOST_DESCRIBE_MODIFIERS_HPP_INCLUDED +#define BOOST_DESCRIBE_MODIFIERS_HPP_INCLUDED + +// Copyright 2020 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +namespace boost +{ +namespace describe +{ + +enum modifiers +{ + mod_public = 1, + mod_protected = 2, + mod_private = 4, + mod_virtual = 8, + mod_static = 16, + mod_function = 32, + mod_any_member = 64, + mod_inherited = 128, + mod_hidden = 256 +}; + +BOOST_DESCRIBE_CONSTEXPR_OR_CONST modifiers mod_any_access = static_cast( mod_public | mod_protected | mod_private ); + +} // namespace describe +} // namespace boost + +#endif // #ifndef BOOST_DESCRIBE_MODIFIERS_HPP_INCLUDED diff --git a/boost/integer.hpp b/boost/integer.hpp new file mode 100644 index 00000000..ad7945ac --- /dev/null +++ b/boost/integer.hpp @@ -0,0 +1,262 @@ +// boost integer.hpp header file -------------------------------------------// + +// Copyright Beman Dawes and Daryle Walker 1999. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) + +// See https://www.boost.org/libs/integer for documentation. + +// Revision History +// 22 Sep 01 Added value-based integer templates. (Daryle Walker) +// 01 Apr 01 Modified to use new header. (John Maddock) +// 30 Jul 00 Add typename syntax fix (Jens Maurer) +// 28 Aug 99 Initial version + +#ifndef BOOST_INTEGER_HPP +#define BOOST_INTEGER_HPP + +#include // self include + +#include // for boost::::boost::integer_traits +#include // for ::std::numeric_limits +#include // for boost::int64_t and BOOST_NO_INTEGRAL_INT64_T +#include + +// +// We simply cannot include this header on gcc without getting copious warnings of the kind: +// +// boost/integer.hpp:77:30: warning: use of C99 long long integer constant +// +// And yet there is no other reasonable implementation, so we declare this a system header +// to suppress these warnings. +// +#if defined(__GNUC__) && (__GNUC__ >= 4) +#pragma GCC system_header +#endif + +namespace boost +{ + + // Helper templates ------------------------------------------------------// + + // fast integers from least integers + // int_fast_t<> works correctly for unsigned too, in spite of the name. + template< typename LeastInt > + struct int_fast_t + { + typedef LeastInt fast; + typedef fast type; + }; // imps may specialize + + namespace detail{ + + // convert category to type + template< int Category > struct int_least_helper {}; // default is empty + template< int Category > struct uint_least_helper {}; // default is empty + + // specializatons: 1=long, 2=int, 3=short, 4=signed char, + // 6=unsigned long, 7=unsigned int, 8=unsigned short, 9=unsigned char + // no specializations for 0 and 5: requests for a type > long are in error +#ifdef BOOST_HAS_LONG_LONG + template<> struct int_least_helper<1> { typedef boost::long_long_type least; }; +#elif defined(BOOST_HAS_MS_INT64) + template<> struct int_least_helper<1> { typedef __int64 least; }; +#endif + template<> struct int_least_helper<2> { typedef long least; }; + template<> struct int_least_helper<3> { typedef int least; }; + template<> struct int_least_helper<4> { typedef short least; }; + template<> struct int_least_helper<5> { typedef signed char least; }; +#ifdef BOOST_HAS_LONG_LONG + template<> struct uint_least_helper<1> { typedef boost::ulong_long_type least; }; +#elif defined(BOOST_HAS_MS_INT64) + template<> struct uint_least_helper<1> { typedef unsigned __int64 least; }; +#endif + template<> struct uint_least_helper<2> { typedef unsigned long least; }; + template<> struct uint_least_helper<3> { typedef unsigned int least; }; + template<> struct uint_least_helper<4> { typedef unsigned short least; }; + template<> struct uint_least_helper<5> { typedef unsigned char least; }; + + template + struct exact_signed_base_helper{}; + template + struct exact_unsigned_base_helper{}; + + template <> struct exact_signed_base_helper { typedef signed char exact; }; + template <> struct exact_unsigned_base_helper { typedef unsigned char exact; }; +#if USHRT_MAX != UCHAR_MAX + template <> struct exact_signed_base_helper { typedef short exact; }; + template <> struct exact_unsigned_base_helper { typedef unsigned short exact; }; +#endif +#if UINT_MAX != USHRT_MAX + template <> struct exact_signed_base_helper { typedef int exact; }; + template <> struct exact_unsigned_base_helper { typedef unsigned int exact; }; +#endif +#if ULONG_MAX != UINT_MAX && ( !defined __TI_COMPILER_VERSION__ || \ + ( __TI_COMPILER_VERSION__ >= 7000000 && !defined __TI_40BIT_LONG__ ) ) + template <> struct exact_signed_base_helper { typedef long exact; }; + template <> struct exact_unsigned_base_helper { typedef unsigned long exact; }; +#endif +#if defined(BOOST_HAS_LONG_LONG) &&\ + ((defined(ULLONG_MAX) && (ULLONG_MAX != ULONG_MAX)) ||\ + (defined(ULONG_LONG_MAX) && (ULONG_LONG_MAX != ULONG_MAX)) ||\ + (defined(ULONGLONG_MAX) && (ULONGLONG_MAX != ULONG_MAX)) ||\ + (defined(_ULLONG_MAX) && (_ULLONG_MAX != ULONG_MAX))) + template <> struct exact_signed_base_helper { typedef boost::long_long_type exact; }; + template <> struct exact_unsigned_base_helper { typedef boost::ulong_long_type exact; }; +#endif + + + } // namespace detail + + // integer templates specifying number of bits ---------------------------// + + // signed + template< int Bits > // bits (including sign) required + struct int_t : public boost::detail::exact_signed_base_helper + { + BOOST_STATIC_ASSERT_MSG(Bits <= (int)(sizeof(boost::intmax_t) * CHAR_BIT), + "No suitable signed integer type with the requested number of bits is available."); + typedef typename boost::detail::int_least_helper + < +#ifdef BOOST_HAS_LONG_LONG + (Bits <= (int)(sizeof(boost::long_long_type) * CHAR_BIT)) + +#else + 1 + +#endif + (Bits-1 <= ::std::numeric_limits::digits) + + (Bits-1 <= ::std::numeric_limits::digits) + + (Bits-1 <= ::std::numeric_limits::digits) + + (Bits-1 <= ::std::numeric_limits::digits) + >::least least; + typedef typename int_fast_t::type fast; + }; + + // unsigned + template< int Bits > // bits required + struct uint_t : public boost::detail::exact_unsigned_base_helper + { + BOOST_STATIC_ASSERT_MSG(Bits <= (int)(sizeof(boost::uintmax_t) * CHAR_BIT), + "No suitable unsigned integer type with the requested number of bits is available."); +#if (defined(BOOST_BORLANDC) || defined(__CODEGEAR__)) && defined(BOOST_NO_INTEGRAL_INT64_T) + // It's really not clear why this workaround should be needed... shrug I guess! JM + BOOST_STATIC_CONSTANT(int, s = + 6 + + (Bits <= ::std::numeric_limits::digits) + + (Bits <= ::std::numeric_limits::digits) + + (Bits <= ::std::numeric_limits::digits) + + (Bits <= ::std::numeric_limits::digits)); + typedef typename detail::int_least_helper< ::boost::uint_t::s>::least least; +#else + typedef typename boost::detail::uint_least_helper + < +#ifdef BOOST_HAS_LONG_LONG + (Bits <= (int)(sizeof(boost::long_long_type) * CHAR_BIT)) + +#else + 1 + +#endif + (Bits <= ::std::numeric_limits::digits) + + (Bits <= ::std::numeric_limits::digits) + + (Bits <= ::std::numeric_limits::digits) + + (Bits <= ::std::numeric_limits::digits) + >::least least; +#endif + typedef typename int_fast_t::type fast; + // int_fast_t<> works correctly for unsigned too, in spite of the name. + }; + + // integer templates specifying extreme value ----------------------------// + + // signed +#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_LONG_LONG) + template< boost::long_long_type MaxValue > // maximum value to require support +#else + template< long MaxValue > // maximum value to require support +#endif + struct int_max_value_t + { + typedef typename boost::detail::int_least_helper + < +#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_LONG_LONG) + (MaxValue <= ::boost::integer_traits::const_max) + +#else + 1 + +#endif + (MaxValue <= ::boost::integer_traits::const_max) + + (MaxValue <= ::boost::integer_traits::const_max) + + (MaxValue <= ::boost::integer_traits::const_max) + + (MaxValue <= ::boost::integer_traits::const_max) + >::least least; + typedef typename int_fast_t::type fast; + }; + +#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_LONG_LONG) + template< boost::long_long_type MinValue > // minimum value to require support +#else + template< long MinValue > // minimum value to require support +#endif + struct int_min_value_t + { + typedef typename boost::detail::int_least_helper + < +#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_LONG_LONG) + (MinValue >= ::boost::integer_traits::const_min) + +#else + 1 + +#endif + (MinValue >= ::boost::integer_traits::const_min) + + (MinValue >= ::boost::integer_traits::const_min) + + (MinValue >= ::boost::integer_traits::const_min) + + (MinValue >= ::boost::integer_traits::const_min) + >::least least; + typedef typename int_fast_t::type fast; + }; + + // unsigned +#if !defined(BOOST_NO_INTEGRAL_INT64_T) && defined(BOOST_HAS_LONG_LONG) + template< boost::ulong_long_type MaxValue > // minimum value to require support +#else + template< unsigned long MaxValue > // minimum value to require support +#endif + struct uint_value_t + { +#if (defined(BOOST_BORLANDC) || defined(__CODEGEAR__)) + // It's really not clear why this workaround should be needed... shrug I guess! JM +#if defined(BOOST_NO_INTEGRAL_INT64_T) + BOOST_STATIC_CONSTANT(unsigned, which = + 1 + + (MaxValue <= ::boost::integer_traits::const_max) + + (MaxValue <= ::boost::integer_traits::const_max) + + (MaxValue <= ::boost::integer_traits::const_max) + + (MaxValue <= ::boost::integer_traits::const_max)); + typedef typename detail::int_least_helper< ::boost::uint_value_t::which>::least least; +#else // BOOST_NO_INTEGRAL_INT64_T + BOOST_STATIC_CONSTANT(unsigned, which = + 1 + + (MaxValue <= ::boost::integer_traits::const_max) + + (MaxValue <= ::boost::integer_traits::const_max) + + (MaxValue <= ::boost::integer_traits::const_max) + + (MaxValue <= ::boost::integer_traits::const_max) + + (MaxValue <= ::boost::integer_traits::const_max)); + typedef typename detail::uint_least_helper< ::boost::uint_value_t::which>::least least; +#endif // BOOST_NO_INTEGRAL_INT64_T +#else + typedef typename boost::detail::uint_least_helper + < +#if !defined(BOOST_NO_INTEGRAL_INT64_T) && defined(BOOST_HAS_LONG_LONG) + (MaxValue <= ::boost::integer_traits::const_max) + +#else + 1 + +#endif + (MaxValue <= ::boost::integer_traits::const_max) + + (MaxValue <= ::boost::integer_traits::const_max) + + (MaxValue <= ::boost::integer_traits::const_max) + + (MaxValue <= ::boost::integer_traits::const_max) + >::least least; +#endif + typedef typename int_fast_t::type fast; + }; + + +} // namespace boost + +#endif // BOOST_INTEGER_HPP diff --git a/boost/integer_traits.hpp b/boost/integer_traits.hpp new file mode 100644 index 00000000..c2d4897a --- /dev/null +++ b/boost/integer_traits.hpp @@ -0,0 +1,256 @@ +/* boost integer_traits.hpp header file + * + * Copyright Jens Maurer 2000 + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * https://www.boost.org/LICENSE_1_0.txt) + * + * $Id$ + * + * Idea by Beman Dawes, Ed Brey, Steve Cleary, and Nathan Myers + */ + +// See https://www.boost.org/libs/integer for documentation. + + +#ifndef BOOST_INTEGER_TRAITS_HPP +#define BOOST_INTEGER_TRAITS_HPP + +#include +#include + +// These are an implementation detail and not part of the interface +#include +// we need wchar.h for WCHAR_MAX/MIN but not all platforms provide it, +// and some may have but not ... +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) && (!defined(BOOST_NO_CWCHAR) || defined(sun) || defined(__sun) || defined(__QNX__)) +#include +#endif + +// +// We simply cannot include this header on gcc without getting copious warnings of the kind: +// +// ../../../boost/integer_traits.hpp:164:66: warning: use of C99 long long integer constant +// +// And yet there is no other reasonable implementation, so we declare this a system header +// to suppress these warnings. +// +#if defined(__GNUC__) && (__GNUC__ >= 4) +#pragma GCC system_header +#endif + +namespace boost { +template +class integer_traits : public std::numeric_limits +{ +public: + BOOST_STATIC_CONSTANT(bool, is_integral = false); +}; + +namespace detail { +template +class integer_traits_base +{ +public: + BOOST_STATIC_CONSTANT(bool, is_integral = true); + BOOST_STATIC_CONSTANT(T, const_min = min_val); + BOOST_STATIC_CONSTANT(T, const_max = max_val); +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool integer_traits_base::is_integral; + +template +const T integer_traits_base::const_min; + +template +const T integer_traits_base::const_max; +#endif + +} // namespace detail + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template<> +class integer_traits + : public std::numeric_limits, + // Don't trust WCHAR_MIN and WCHAR_MAX with Mac OS X's native + // library: they are wrong! +#if defined(WCHAR_MIN) && defined(WCHAR_MAX) && !defined(__APPLE__) + public detail::integer_traits_base +#elif defined(BOOST_BORLANDC) || defined(__CYGWIN__) || defined(__MINGW32__) || (defined(__BEOS__) && defined(__GNUC__)) + // No WCHAR_MIN and WCHAR_MAX, whar_t is short and unsigned: + public detail::integer_traits_base +#elif (defined(__sgi) && (!defined(__SGI_STL_PORT) || __SGI_STL_PORT < 0x400))\ + || (defined __APPLE__)\ + || (defined(__OpenBSD__) && defined(__GNUC__))\ + || (defined(__NetBSD__) && defined(__GNUC__))\ + || (defined(__FreeBSD__) && defined(__GNUC__))\ + || (defined(__DragonFly__) && defined(__GNUC__))\ + || (defined(__hpux) && defined(__GNUC__) && (__GNUC__ == 3) && !defined(__SGI_STL_PORT)) + // No WCHAR_MIN and WCHAR_MAX, wchar_t has the same range as int. + // - SGI MIPSpro with native library + // - gcc 3.x on HP-UX + // - Mac OS X with native library + // - gcc on FreeBSD, OpenBSD and NetBSD + public detail::integer_traits_base +#else +#error No WCHAR_MIN and WCHAR_MAX present, please adjust integer_traits<> for your compiler. +#endif +{ }; +#endif // BOOST_NO_INTRINSIC_WCHAR_T + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +template<> +class integer_traits + : public std::numeric_limits, + public detail::integer_traits_base +{ }; + +#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) +#if defined(ULLONG_MAX) && defined(BOOST_HAS_LONG_LONG) + +template<> +class integer_traits< ::boost::long_long_type> + : public std::numeric_limits< ::boost::long_long_type>, + public detail::integer_traits_base< ::boost::long_long_type, LLONG_MIN, LLONG_MAX> +{ }; + +template<> +class integer_traits< ::boost::ulong_long_type> + : public std::numeric_limits< ::boost::ulong_long_type>, + public detail::integer_traits_base< ::boost::ulong_long_type, 0, ULLONG_MAX> +{ }; + +#elif defined(ULONG_LONG_MAX) && defined(BOOST_HAS_LONG_LONG) + +template<> +class integer_traits< ::boost::long_long_type> : public std::numeric_limits< ::boost::long_long_type>, public detail::integer_traits_base< ::boost::long_long_type, LONG_LONG_MIN, LONG_LONG_MAX>{ }; +template<> +class integer_traits< ::boost::ulong_long_type> + : public std::numeric_limits< ::boost::ulong_long_type>, + public detail::integer_traits_base< ::boost::ulong_long_type, 0, ULONG_LONG_MAX> +{ }; + +#elif defined(ULONGLONG_MAX) && defined(BOOST_HAS_LONG_LONG) + +template<> +class integer_traits< ::boost::long_long_type> + : public std::numeric_limits< ::boost::long_long_type>, + public detail::integer_traits_base< ::boost::long_long_type, LONGLONG_MIN, LONGLONG_MAX> +{ }; + +template<> +class integer_traits< ::boost::ulong_long_type> + : public std::numeric_limits< ::boost::ulong_long_type>, + public detail::integer_traits_base< ::boost::ulong_long_type, 0, ULONGLONG_MAX> +{ }; + +#elif defined(_LLONG_MAX) && defined(_C2) && defined(BOOST_HAS_LONG_LONG) + +template<> +class integer_traits< ::boost::long_long_type> + : public std::numeric_limits< ::boost::long_long_type>, + public detail::integer_traits_base< ::boost::long_long_type, -_LLONG_MAX - _C2, _LLONG_MAX> +{ }; + +template<> +class integer_traits< ::boost::ulong_long_type> + : public std::numeric_limits< ::boost::ulong_long_type>, + public detail::integer_traits_base< ::boost::ulong_long_type, 0, _ULLONG_MAX> +{ }; + +#elif defined(BOOST_HAS_LONG_LONG) +// +// we have long long but no constants, this happens for example with gcc in -ansi mode, +// we'll just have to work out the values for ourselves (assumes 2's compliment representation): +// +template<> +class integer_traits< ::boost::long_long_type> + : public std::numeric_limits< ::boost::long_long_type>, + public detail::integer_traits_base< ::boost::long_long_type, (1LL << (sizeof(::boost::long_long_type) * CHAR_BIT - 1)), ~(1LL << (sizeof(::boost::long_long_type) * CHAR_BIT - 1))> +{ }; + +template<> +class integer_traits< ::boost::ulong_long_type> + : public std::numeric_limits< ::boost::ulong_long_type>, + public detail::integer_traits_base< ::boost::ulong_long_type, 0, ~0uLL> +{ }; + +#elif defined(BOOST_HAS_MS_INT64) + +template<> +class integer_traits< __int64> + : public std::numeric_limits< __int64>, + public detail::integer_traits_base< __int64, _I64_MIN, _I64_MAX> +{ }; + +template<> +class integer_traits< unsigned __int64> + : public std::numeric_limits< unsigned __int64>, + public detail::integer_traits_base< unsigned __int64, 0, _UI64_MAX> +{ }; + +#endif +#endif + +} // namespace boost + +#endif /* BOOST_INTEGER_TRAITS_HPP */ + + + diff --git a/boost/io/detail/buffer_fill.hpp b/boost/io/detail/buffer_fill.hpp new file mode 100644 index 00000000..b25a8844 --- /dev/null +++ b/boost/io/detail/buffer_fill.hpp @@ -0,0 +1,39 @@ +/* +Copyright 2019-2020 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_IO_DETAIL_BUFFER_FILL_HPP +#define BOOST_IO_DETAIL_BUFFER_FILL_HPP + +#include +#include + +namespace boost { +namespace io { +namespace detail { + +template +inline bool +buffer_fill(std::basic_streambuf& buf, charT ch, + std::size_t size) +{ + charT fill[] = { ch, ch, ch, ch, ch, ch, ch, ch }; + enum { + chunk = sizeof fill / sizeof(charT) + }; + for (; size > chunk; size -= chunk) { + if (static_cast(buf.sputn(fill, chunk)) != chunk) { + return false; + } + } + return static_cast(buf.sputn(fill, size)) == size; +} + +} /* detail */ +} /* io */ +} /* boost */ + +#endif diff --git a/boost/io/detail/ostream_guard.hpp b/boost/io/detail/ostream_guard.hpp new file mode 100644 index 00000000..6999d813 --- /dev/null +++ b/boost/io/detail/ostream_guard.hpp @@ -0,0 +1,45 @@ +/* +Copyright 2019-2020 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_IO_DETAIL_OSTREAM_GUARD_HPP +#define BOOST_IO_DETAIL_OSTREAM_GUARD_HPP + +#include +#include + +namespace boost { +namespace io { +namespace detail { + +template +class ostream_guard { +public: + explicit ostream_guard(std::basic_ostream& os) BOOST_NOEXCEPT + : os_(&os) { } + + ~ostream_guard() BOOST_NOEXCEPT_IF(false) { + if (os_) { + os_->setstate(std::basic_ostream::badbit); + } + } + + void release() BOOST_NOEXCEPT { + os_ = 0; + } + +private: + ostream_guard(const ostream_guard&); + ostream_guard& operator=(const ostream_guard&); + + std::basic_ostream* os_; +}; + +} /* detail */ +} /* io */ +} /* boost */ + +#endif diff --git a/boost/io/ostream_put.hpp b/boost/io/ostream_put.hpp new file mode 100644 index 00000000..97627f8e --- /dev/null +++ b/boost/io/ostream_put.hpp @@ -0,0 +1,50 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_IO_OSTREAM_PUT_HPP +#define BOOST_IO_OSTREAM_PUT_HPP + +#include +#include + +namespace boost { +namespace io { + +template +inline std::basic_ostream& +ostream_put(std::basic_ostream& os, const charT* data, + std::size_t size) +{ + typedef std::basic_ostream stream; + detail::ostream_guard guard(os); + typename stream::sentry entry(os); + if (entry) { + std::basic_streambuf& buf = *os.rdbuf(); + std::size_t width = static_cast(os.width()); + if (width <= size) { + if (static_cast(buf.sputn(data, size)) != size) { + return os; + } + } else if ((os.flags() & stream::adjustfield) == stream::left) { + if (static_cast(buf.sputn(data, size)) != size || + !detail::buffer_fill(buf, os.fill(), width - size)) { + return os; + } + } else if (!detail::buffer_fill(buf, os.fill(), width - size) || + static_cast(buf.sputn(data, size)) != size) { + return os; + } + os.width(0); + } + guard.release(); + return os; +} + +} /* io */ +} /* boost */ + +#endif diff --git a/boost/iterator/counting_iterator.hpp b/boost/iterator/counting_iterator.hpp new file mode 100644 index 00000000..65c11e94 --- /dev/null +++ b/boost/iterator/counting_iterator.hpp @@ -0,0 +1,254 @@ +// Copyright David Abrahams 2003. +// 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) +#ifndef COUNTING_ITERATOR_DWA200348_HPP +# define COUNTING_ITERATOR_DWA200348_HPP + +# include +# include +# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +# include +# elif !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) +# include +# else +# include +# endif +# include +# include +# include +# include +# include +# include + +namespace boost { +namespace iterators { + +template < + class Incrementable + , class CategoryOrTraversal + , class Difference +> +class counting_iterator; + +namespace detail +{ + // Try to detect numeric types at compile time in ways compatible + // with the limitations of the compiler and library. + template + struct is_numeric_impl + { + // For a while, this wasn't true, but we rely on it below. This is a regression assert. + BOOST_STATIC_ASSERT(::boost::is_integral::value); + +# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + + BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_specialized); + +# else + +# if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) + BOOST_STATIC_CONSTANT( + bool, value = ( + boost::is_convertible::value + && boost::is_convertible::value + )); +# else + BOOST_STATIC_CONSTANT(bool, value = ::boost::is_arithmetic::value); +# endif + +# endif + }; + + template + struct is_numeric + : boost::integral_constant::value> + {}; + +# if defined(BOOST_HAS_LONG_LONG) + template <> + struct is_numeric + : boost::true_type {}; + + template <> + struct is_numeric + : boost::true_type {}; +# endif + +# if defined(BOOST_HAS_INT128) + template <> + struct is_numeric + : boost::true_type {}; + + template <> + struct is_numeric + : boost::true_type {}; +# endif + + // Some compilers fail to have a numeric_limits specialization + template <> + struct is_numeric + : true_type {}; + + template + struct numeric_difference + { + typedef typename boost::detail::numeric_traits::difference_type type; + }; + +# if defined(BOOST_HAS_INT128) + // std::numeric_limits, which is used by numeric_traits, is not specialized for __int128 in some standard libraries + template <> + struct numeric_difference + { + typedef boost::int128_type type; + }; + + template <> + struct numeric_difference + { + typedef boost::int128_type type; + }; +# endif + + template + struct counting_iterator_base + { + typedef typename detail::ia_dflt_help< + CategoryOrTraversal + , typename boost::conditional< + is_numeric::value + , boost::type_identity + , iterator_traversal + >::type + >::type traversal; + + typedef typename detail::ia_dflt_help< + Difference + , typename boost::conditional< + is_numeric::value + , numeric_difference + , iterator_difference + >::type + >::type difference; + + typedef iterator_adaptor< + counting_iterator // self + , Incrementable // Base + , Incrementable // Value +# ifndef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY + const // MSVC won't strip this. Instead we enable Thomas' + // criterion (see boost/iterator/detail/facade_iterator_category.hpp) +# endif + , traversal + , Incrementable const& // reference + , difference + > type; + }; + + // Template class distance_policy_select -- choose a policy for computing the + // distance between counting_iterators at compile-time based on whether or not + // the iterator wraps an integer or an iterator, using "poor man's partial + // specialization". + + template struct distance_policy_select; + + // A policy for wrapped iterators + template + struct iterator_distance + { + static Difference distance(Incrementable1 x, Incrementable2 y) + { + return y - x; + } + }; + + // A policy for wrapped numbers + template + struct number_distance + { + static Difference distance(Incrementable1 x, Incrementable2 y) + { + return boost::detail::numeric_distance(x, y); + } + }; +} + +template < + class Incrementable + , class CategoryOrTraversal = use_default + , class Difference = use_default +> +class counting_iterator + : public detail::counting_iterator_base< + Incrementable, CategoryOrTraversal, Difference + >::type +{ + typedef typename detail::counting_iterator_base< + Incrementable, CategoryOrTraversal, Difference + >::type super_t; + + friend class iterator_core_access; + + public: + typedef typename super_t::difference_type difference_type; + + BOOST_DEFAULTED_FUNCTION(counting_iterator(), {}) + + BOOST_DEFAULTED_FUNCTION(counting_iterator(counting_iterator const& rhs), : super_t(rhs.base()) {}) + + counting_iterator(Incrementable x) + : super_t(x) + { + } + +# if 0 + template + counting_iterator( + counting_iterator const& t + , typename enable_if_convertible::type* = 0 + ) + : super_t(t.base()) + {} +# endif + + BOOST_DEFAULTED_FUNCTION(counting_iterator& operator=(counting_iterator const& rhs), { *static_cast< super_t* >(this) = static_cast< super_t const& >(rhs); return *this; }) + + private: + + typename super_t::reference dereference() const + { + return this->base_reference(); + } + + template + difference_type + distance_to(counting_iterator const& y) const + { + typedef typename boost::conditional< + detail::is_numeric::value + , detail::number_distance + , detail::iterator_distance + >::type d; + + return d::distance(this->base(), y.base()); + } +}; + +// Manufacture a counting iterator for an arbitrary incrementable type +template +inline counting_iterator +make_counting_iterator(Incrementable x) +{ + typedef counting_iterator result_t; + return result_t(x); +} + +} // namespace iterators + +using iterators::counting_iterator; +using iterators::make_counting_iterator; + +} // namespace boost + +#endif // COUNTING_ITERATOR_DWA200348_HPP diff --git a/boost/iterator/detail/any_conversion_eater.hpp b/boost/iterator/detail/any_conversion_eater.hpp new file mode 100644 index 00000000..429421fd --- /dev/null +++ b/boost/iterator/detail/any_conversion_eater.hpp @@ -0,0 +1,21 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to 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) +#ifndef ANY_CONVERSION_EATER_DWA20031117_HPP +# define ANY_CONVERSION_EATER_DWA20031117_HPP + +namespace boost { +namespace iterators { +namespace detail { + +// This type can be used in traits to "eat" up the one user-defined +// implicit conversion allowed. +struct any_conversion_eater +{ + template + any_conversion_eater(T const&); +}; + +}}} // namespace boost::iterators::detail + +#endif // ANY_CONVERSION_EATER_DWA20031117_HPP diff --git a/boost/iterator/detail/minimum_category.hpp b/boost/iterator/detail/minimum_category.hpp new file mode 100644 index 00000000..748c0d3e --- /dev/null +++ b/boost/iterator/detail/minimum_category.hpp @@ -0,0 +1,19 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to 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) +#ifndef MINIMUM_CATEGORY_DWA20031119_HPP +# define MINIMUM_CATEGORY_DWA20031119_HPP + +# include + +namespace boost { + +// This import below (as well as the whole header) is for backward compatibility +// with boost/token_iterator.hpp. It should be removed as soon as that header is fixed. +namespace detail { +using iterators::minimum_category; +} // namespace detail + +} // namespace boost + +#endif // MINIMUM_CATEGORY_DWA20031119_HPP diff --git a/boost/iterator/filter_iterator.hpp b/boost/iterator/filter_iterator.hpp new file mode 100644 index 00000000..18c6186a --- /dev/null +++ b/boost/iterator/filter_iterator.hpp @@ -0,0 +1,146 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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) +#ifndef BOOST_FILTER_ITERATOR_23022003THW_HPP +#define BOOST_FILTER_ITERATOR_23022003THW_HPP + +#include +#include + +#include +#include +#include +#include + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_ITERATOR_DETAIL_MOVE(_type, _value) static_cast< _type&& >(_value) +#else +#define BOOST_ITERATOR_DETAIL_MOVE(_type, _value) _value +#endif + +namespace boost { +namespace iterators { + + template + class filter_iterator; + + namespace detail + { + template + struct filter_iterator_base + { + typedef iterator_adaptor< + filter_iterator + , Iterator + , use_default + , typename mpl::if_< + is_convertible< + typename iterator_traversal::type + , random_access_traversal_tag + > + , bidirectional_traversal_tag + , use_default + >::type + > type; + }; + } + + template + class filter_iterator + : public detail::filter_iterator_base::type + { + typedef typename detail::filter_iterator_base< + Predicate, Iterator + >::type super_t; + + friend class iterator_core_access; + + public: + filter_iterator() { } + + filter_iterator(Predicate f, Iterator x, Iterator end_ = Iterator()) + : super_t(BOOST_ITERATOR_DETAIL_MOVE(Iterator, x)), m_predicate(BOOST_ITERATOR_DETAIL_MOVE(Predicate, f)), m_end(BOOST_ITERATOR_DETAIL_MOVE(Iterator, end_)) + { + satisfy_predicate(); + } + + filter_iterator(Iterator x, Iterator end_ = Iterator()) + : super_t(BOOST_ITERATOR_DETAIL_MOVE(Iterator, x)), m_predicate(), m_end(BOOST_ITERATOR_DETAIL_MOVE(Iterator, end_)) + { + // Pro8 is a little too aggressive about instantiating the + // body of this function. +#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + // Don't allow use of this constructor if Predicate is a + // function pointer type, since it will be 0. + BOOST_STATIC_ASSERT(is_class::value); +#endif + satisfy_predicate(); + } + + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 + ) + : super_t(t.base()), m_predicate(t.predicate()), m_end(t.end()) {} + + Predicate predicate() const { return m_predicate; } + + Iterator end() const { return m_end; } + + private: + void increment() + { + ++(this->base_reference()); + satisfy_predicate(); + } + + void decrement() + { + while(!this->m_predicate(*--(this->base_reference()))){}; + } + + void satisfy_predicate() + { + while (this->base() != this->m_end && !this->m_predicate(*this->base())) + ++(this->base_reference()); + } + + // Probably should be the initial base class so it can be + // optimized away via EBO if it is an empty class. + Predicate m_predicate; + Iterator m_end; + }; + + template + inline filter_iterator + make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()) + { + return filter_iterator(BOOST_ITERATOR_DETAIL_MOVE(Predicate, f), BOOST_ITERATOR_DETAIL_MOVE(Iterator, x), BOOST_ITERATOR_DETAIL_MOVE(Iterator, end)); + } + + template + inline filter_iterator + make_filter_iterator( + typename iterators::enable_if< + is_class + , Iterator + >::type x + , Iterator end = Iterator()) + { + return filter_iterator(BOOST_ITERATOR_DETAIL_MOVE(Iterator, x), BOOST_ITERATOR_DETAIL_MOVE(Iterator, end)); + } + +} // namespace iterators + +using iterators::filter_iterator; +using iterators::make_filter_iterator; + +} // namespace boost + +#undef BOOST_ITERATOR_DETAIL_MOVE + +#endif // BOOST_FILTER_ITERATOR_23022003THW_HPP diff --git a/boost/iterator/function_input_iterator.hpp b/boost/iterator/function_input_iterator.hpp new file mode 100644 index 00000000..610c1338 --- /dev/null +++ b/boost/iterator/function_input_iterator.hpp @@ -0,0 +1,180 @@ +// Copyright 2009 (C) Dean Michael Berris +// Copyright 2012 (C) Google, Inc. +// Copyright 2012 (C) Jeffrey Lee Hellrung, Jr. +// 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) +// + +#ifndef BOOST_FUNCTION_INPUT_ITERATOR +#define BOOST_FUNCTION_INPUT_ITERATOR + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_RESULT_OF_USE_TR1 +#include +#endif + +namespace boost { + +namespace iterators { + + template + class function_input_iterator; + + namespace impl { + + // Computes the return type of an lvalue-call with an empty argument, + // i.e. decltype(declval()()). F should be a nullary lvalue-callable + // or function. + template + struct result_of_nullary_lvalue_call + { + typedef typename result_of< +#ifdef BOOST_RESULT_OF_USE_TR1 + typename boost::conditional::value, F&, F>::type() +#else + F&() +#endif + >::type type; + }; + + template + class function_object_input_iterator : + public iterator_facade< + iterators::function_input_iterator, + typename result_of_nullary_lvalue_call::type, + single_pass_traversal_tag, + typename result_of_nullary_lvalue_call::type const & + > + { + public: + function_object_input_iterator() {} + function_object_input_iterator(Function & f_, Input state_ = Input()) + : f(boost::addressof(f_)), state(state_) {} + + void increment() { + if (value) + value = none; + else + (*f)(); + ++state; + } + + typename result_of_nullary_lvalue_call::type const & + dereference() const { + if (!value) + value = (*f)(); + return value.get(); + } + + bool equal(function_object_input_iterator const & other) const { + return f == other.f && state == other.state; + } + + private: + Function * f; + Input state; + mutable optional::type> value; + }; + + template + class function_pointer_input_iterator : + public iterator_facade< + iterators::function_input_iterator, + typename function_types::result_type::type, + single_pass_traversal_tag, + typename function_types::result_type::type const & + > + { + public: + function_pointer_input_iterator() {} + function_pointer_input_iterator(Function &f_, Input state_ = Input()) + : f(f_), state(state_) {} + + void increment() { + if (value) + value = none; + else + (*f)(); + ++state; + } + + typename function_types::result_type::type const & + dereference() const { + if (!value) + value = (*f)(); + return value.get(); + } + + bool equal(function_pointer_input_iterator const & other) const { + return f == other.f && state == other.state; + } + + private: + Function f; + Input state; + mutable optional::type> value; + }; + + } // namespace impl + + template + class function_input_iterator : + public boost::conditional< + function_types::is_function_pointer::value, + impl::function_pointer_input_iterator, + impl::function_object_input_iterator + >::type + { + typedef typename boost::conditional< + function_types::is_function_pointer::value, + impl::function_pointer_input_iterator, + impl::function_object_input_iterator + >::type base_type; + public: + function_input_iterator(Function & f, Input i) + : base_type(f, i) {} + }; + + template + inline function_input_iterator + make_function_input_iterator(Function & f, Input state) { + typedef function_input_iterator result_t; + return result_t(f, state); + } + + template + inline function_input_iterator + make_function_input_iterator(Function * f, Input state) { + typedef function_input_iterator result_t; + return result_t(f, state); + } + + struct infinite + { + infinite & operator++() { return *this; } + infinite & operator++(int) { return *this; } + bool operator==(infinite &) const { return false; }; + bool operator==(infinite const &) const { return false; }; + }; + +} // namespace iterators + +using iterators::function_input_iterator; +using iterators::make_function_input_iterator; +using iterators::infinite; + +} // namespace boost + +#endif + diff --git a/boost/iterator/function_output_iterator.hpp b/boost/iterator/function_output_iterator.hpp new file mode 100644 index 00000000..b59cbc91 --- /dev/null +++ b/boost/iterator/function_output_iterator.hpp @@ -0,0 +1,95 @@ +// (C) Copyright Jeremy Siek 2001. +// 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) + +// Revision History: + +// 27 Feb 2001 Jeremy Siek +// Initial checkin. + +#ifndef BOOST_ITERATOR_FUNCTION_OUTPUT_ITERATOR_HPP +#define BOOST_ITERATOR_FUNCTION_OUTPUT_ITERATOR_HPP + +#include +#include +#include +#include +#include +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#include +#endif + +namespace boost { +namespace iterators { + + template + class function_output_iterator { + private: + typedef function_output_iterator self; + + class output_proxy { + public: + explicit output_proxy(UnaryFunction& f) BOOST_NOEXCEPT : m_f(f) { } + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + template + typename boost::disable_if_c< + boost::is_same< typename boost::remove_cv< T >::type, output_proxy >::value, + output_proxy& + >::type operator=(const T& value) { + m_f(value); + return *this; + } +#else + template + typename boost::disable_if_c< + boost::is_same< typename boost::remove_cv< typename boost::remove_reference< T >::type >::type, output_proxy >::value, + output_proxy& + >::type operator=(T&& value) { + m_f(static_cast< T&& >(value)); + return *this; + } +#endif + + BOOST_DEFAULTED_FUNCTION(output_proxy(output_proxy const& that), BOOST_NOEXCEPT : m_f(that.m_f) {}) + BOOST_DELETED_FUNCTION(output_proxy& operator=(output_proxy const&)) + + private: + UnaryFunction& m_f; + }; + + public: + typedef std::output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + explicit function_output_iterator() {} + + explicit function_output_iterator(const UnaryFunction& f) + : m_f(f) {} + + output_proxy operator*() { return output_proxy(m_f); } + self& operator++() { return *this; } + self& operator++(int) { return *this; } + + private: + UnaryFunction m_f; + }; + + template + inline function_output_iterator + make_function_output_iterator(const UnaryFunction& f = UnaryFunction()) { + return function_output_iterator(f); + } + +} // namespace iterators + +using iterators::function_output_iterator; +using iterators::make_function_output_iterator; + +} // namespace boost + +#endif // BOOST_ITERATOR_FUNCTION_OUTPUT_ITERATOR_HPP diff --git a/boost/iterator/indirect_iterator.hpp b/boost/iterator/indirect_iterator.hpp new file mode 100644 index 00000000..e15ac87e --- /dev/null +++ b/boost/iterator/indirect_iterator.hpp @@ -0,0 +1,145 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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) +#ifndef BOOST_INDIRECT_ITERATOR_23022003THW_HPP +#define BOOST_INDIRECT_ITERATOR_23022003THW_HPP + +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef BOOST_MPL_CFG_NO_HAS_XXX +# include +# include +# include +# include +#endif + +#include // must be last #include + +namespace boost { +namespace iterators { + + template + class indirect_iterator; + + namespace detail + { + template + struct indirect_base + { + typedef typename std::iterator_traits::value_type dereferenceable; + + typedef iterator_adaptor< + indirect_iterator + , Iter + , typename ia_dflt_help< + Value, pointee + >::type + , Category + , typename ia_dflt_help< + Reference + , mpl::eval_if< + is_same + , indirect_reference + , add_reference + > + >::type + , Difference + > type; + }; + + template <> + struct indirect_base {}; + } // namespace detail + + + template < + class Iterator + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class indirect_iterator + : public detail::indirect_base< + Iterator, Value, Category, Reference, Difference + >::type + { + typedef typename detail::indirect_base< + Iterator, Value, Category, Reference, Difference + >::type super_t; + + friend class iterator_core_access; + + public: + indirect_iterator() {} + + indirect_iterator(Iterator iter) + : super_t(iter) {} + + template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 + ) + : super_t(y.base()) + {} + + private: + typename super_t::reference dereference() const + { +# if BOOST_WORKAROUND(BOOST_BORLANDC, < 0x5A0 ) + return const_cast(**this->base()); +# else + return **this->base(); +# endif + } + }; + + template + inline + indirect_iterator make_indirect_iterator(Iter x) + { + return indirect_iterator(x); + } + + template + inline + indirect_iterator make_indirect_iterator(Iter x, Traits* = 0) + { + return indirect_iterator(x); + } + +} // namespace iterators + +using iterators::indirect_iterator; +using iterators::make_indirect_iterator; + +} // namespace boost + +#include + +#endif // BOOST_INDIRECT_ITERATOR_23022003THW_HPP diff --git a/boost/iterator/is_lvalue_iterator.hpp b/boost/iterator/is_lvalue_iterator.hpp new file mode 100644 index 00000000..46f0483e --- /dev/null +++ b/boost/iterator/is_lvalue_iterator.hpp @@ -0,0 +1,164 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to 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) +#ifndef IS_LVALUE_ITERATOR_DWA2003112_HPP +# define IS_LVALUE_ITERATOR_DWA2003112_HPP + +#include + +#include +#include +#include +#include + +#include + +// should be the last #includes +#include +#include + +#ifndef BOOST_NO_IS_CONVERTIBLE + +namespace boost { + +namespace iterators { + +namespace detail +{ +#ifndef BOOST_NO_LVALUE_RETURN_DETECTION + // Calling lvalue_preserver( , 0 ) returns a reference + // to the expression's result if is an lvalue, or + // not_an_lvalue() otherwise. + struct not_an_lvalue {}; + + template + T& lvalue_preserver(T&, int); + + template + not_an_lvalue lvalue_preserver(U const&, ...); + +# define BOOST_LVALUE_PRESERVER(expr) detail::lvalue_preserver(expr,0) + +#else + +# define BOOST_LVALUE_PRESERVER(expr) expr + +#endif + + // Guts of is_lvalue_iterator. Value is the iterator's value_type + // and the result is computed in the nested rebind template. + template + struct is_lvalue_iterator_impl + { + // Eat implicit conversions so we don't report true for things + // convertible to Value const& + struct conversion_eater + { + conversion_eater(typename add_lvalue_reference::type); + }; + + static char tester(conversion_eater, int); + static char (& tester(any_conversion_eater, ...) )[2]; + + template + struct rebind + { + static It& x; + + BOOST_STATIC_CONSTANT( + bool + , value = ( + sizeof( + is_lvalue_iterator_impl::tester( + BOOST_LVALUE_PRESERVER(*x), 0 + ) + ) == 1 + ) + ); + }; + }; + +#undef BOOST_LVALUE_PRESERVER + + // + // void specializations to handle std input and output iterators + // + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; +#endif + + // + // This level of dispatching is required for Borland. We might save + // an instantiation by removing it for others. + // + template + struct is_readable_lvalue_iterator_impl + : is_lvalue_iterator_impl< + BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type const + >::template rebind + {}; + + template + struct is_non_const_lvalue_iterator_impl + : is_lvalue_iterator_impl< + BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type + >::template rebind + {}; +} // namespace detail + +template< typename T > struct is_lvalue_iterator +: public ::boost::integral_constant::value> +{ +public: + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_lvalue_iterator,(T)) +}; + +template< typename T > struct is_non_const_lvalue_iterator +: public ::boost::integral_constant::value> +{ +public: + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_non_const_lvalue_iterator,(T)) +}; + +} // namespace iterators + +using iterators::is_lvalue_iterator; +using iterators::is_non_const_lvalue_iterator; + +} // namespace boost + +#endif + +#include + +#endif // IS_LVALUE_ITERATOR_DWA2003112_HPP diff --git a/boost/iterator/is_readable_iterator.hpp b/boost/iterator/is_readable_iterator.hpp new file mode 100644 index 00000000..26827c4c --- /dev/null +++ b/boost/iterator/is_readable_iterator.hpp @@ -0,0 +1,119 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to 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) +#ifndef IS_READABLE_ITERATOR_DWA2003112_HPP +# define IS_READABLE_ITERATOR_DWA2003112_HPP + +#include +#include +#include + +#include + +#include + +// should be the last #include +#include +#include + +#ifndef BOOST_NO_IS_CONVERTIBLE + +namespace boost { + +namespace iterators { + +namespace detail +{ + // Guts of is_readable_iterator. Value is the iterator's value_type + // and the result is computed in the nested rebind template. + template + struct is_readable_iterator_impl + { + static char tester(typename add_lvalue_reference::type, int); + static char (& tester(any_conversion_eater, ...) )[2]; + + template + struct rebind + { + static It& x; + + BOOST_STATIC_CONSTANT( + bool + , value = ( + sizeof( + is_readable_iterator_impl::tester(*x, 1) + ) == 1 + ) + ); + }; + }; + +#undef BOOST_READABLE_PRESERVER + + // + // void specializations to handle std input and output iterators + // + template <> + struct is_readable_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS + template <> + struct is_readable_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_readable_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_readable_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; +#endif + + // + // This level of dispatching is required for Borland. We might save + // an instantiation by removing it for others. + // + template + struct is_readable_iterator_impl2 + : is_readable_iterator_impl< + BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type const + >::template rebind + {}; +} // namespace detail + +template< typename T > struct is_readable_iterator +: public ::boost::integral_constant::value> +{ +public: + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_readable_iterator,(T)) +}; + +} // namespace iterators + +using iterators::is_readable_iterator; + +} // namespace boost + +#endif + +#include + +#endif // IS_READABLE_ITERATOR_DWA2003112_HPP diff --git a/boost/iterator/iterator_archetypes.hpp b/boost/iterator/iterator_archetypes.hpp new file mode 100644 index 00000000..1d259152 --- /dev/null +++ b/boost/iterator/iterator_archetypes.hpp @@ -0,0 +1,509 @@ +// (C) Copyright Jeremy Siek 2002. +// 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) + +#ifndef BOOST_ITERATOR_ARCHETYPES_HPP +#define BOOST_ITERATOR_ARCHETYPES_HPP + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace iterators { + +template +struct access_archetype; + +template +struct traversal_archetype; + +namespace archetypes +{ + enum { + readable_iterator_bit = 1 + , writable_iterator_bit = 2 + , swappable_iterator_bit = 4 + , lvalue_iterator_bit = 8 + }; + + // Not quite tags, since dispatching wouldn't work. + typedef mpl::int_::type readable_iterator_t; + typedef mpl::int_::type writable_iterator_t; + + typedef mpl::int_< + (readable_iterator_bit|writable_iterator_bit) + >::type readable_writable_iterator_t; + + typedef mpl::int_< + (readable_iterator_bit|lvalue_iterator_bit) + >::type readable_lvalue_iterator_t; + + typedef mpl::int_< + (lvalue_iterator_bit|writable_iterator_bit) + >::type writable_lvalue_iterator_t; + + typedef mpl::int_::type swappable_iterator_t; + typedef mpl::int_::type lvalue_iterator_t; + + template + struct has_access + : mpl::equal_to< + mpl::bitand_ + , Base + > + {}; +} + +namespace detail +{ + template + struct assign_proxy + { + assign_proxy& operator=(T) { return *this; } + }; + + template + struct read_proxy + { + operator T() { return static_object::get(); } + }; + + template + struct read_write_proxy + : read_proxy // Use to inherit from assign_proxy, but that doesn't work. -JGS + { + read_write_proxy& operator=(T) { return *this; } + }; + + template + struct arrow_proxy + { + T const* operator->() const { return 0; } + }; + + struct no_operator_brackets {}; + + template + struct readable_operator_brackets + { + read_proxy operator[](std::ptrdiff_t n) const { return read_proxy(); } + }; + + template + struct writable_operator_brackets + { + read_write_proxy operator[](std::ptrdiff_t n) const { return read_write_proxy(); } + }; + + template + struct operator_brackets + : mpl::eval_if< + is_convertible + , mpl::eval_if< + archetypes::has_access< + AccessCategory + , archetypes::writable_iterator_t + > + , mpl::identity > + , mpl::if_< + archetypes::has_access< + AccessCategory + , archetypes::readable_iterator_t + > + , readable_operator_brackets + , no_operator_brackets + > + > + , mpl::identity + >::type + {}; + + template + struct traversal_archetype_impl + { + template struct archetype; + }; + + // Constructor argument for those iterators that + // are not default constructible + struct ctor_arg {}; + + template + struct traversal_archetype_ + : traversal_archetype_impl::template archetype + { + typedef typename + traversal_archetype_impl::template archetype + base; + + traversal_archetype_() {} + + traversal_archetype_(ctor_arg arg) + : base(arg) + {} + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + { + explicit archetype(ctor_arg) {} + + struct bogus { }; // This use to be void, but that causes trouble for iterator_facade. Need more research. -JGS + typedef bogus difference_type; + + Derived& operator++() { return (Derived&)static_object::get(); } + Derived operator++(int) const { return (Derived&)static_object::get(); } + }; + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public equality_comparable< traversal_archetype_ >, + public traversal_archetype_ + { + explicit archetype(ctor_arg arg) + : traversal_archetype_(arg) + {} + + typedef std::ptrdiff_t difference_type; + }; + }; + + template + bool operator==(traversal_archetype_ const&, + traversal_archetype_ const&) { return true; } + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + archetype() + : traversal_archetype_(ctor_arg()) + {} + }; + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + Derived& operator--() { return static_object::get(); } + Derived operator--(int) const { return static_object::get(); } + }; + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + Derived& operator+=(std::ptrdiff_t) { return static_object::get(); } + Derived& operator-=(std::ptrdiff_t) { return static_object::get(); } + }; + }; + + template + Derived& operator+(traversal_archetype_ const&, + std::ptrdiff_t) { return static_object::get(); } + + template + Derived& operator+(std::ptrdiff_t, + traversal_archetype_ const&) + { return static_object::get(); } + + template + Derived& operator-(traversal_archetype_ const&, + std::ptrdiff_t) + { return static_object::get(); } + + template + std::ptrdiff_t operator-(traversal_archetype_ const&, + traversal_archetype_ const&) + { return 0; } + + template + bool operator<(traversal_archetype_ const&, + traversal_archetype_ const&) + { return true; } + + template + bool operator>(traversal_archetype_ const&, + traversal_archetype_ const&) + { return true; } + + template + bool operator<=(traversal_archetype_ const&, + traversal_archetype_ const&) + { return true; } + + template + bool operator>=(traversal_archetype_ const&, + traversal_archetype_ const&) + { return true; } + + struct bogus_type; + + template + struct convertible_type + : mpl::if_< is_const, + typename remove_const::type, + bogus_type > + {}; + +} // namespace detail + + +template struct undefined; + +template +struct iterator_access_archetype_impl +{ + template struct archetype; +}; + +template +struct iterator_access_archetype + : iterator_access_archetype_impl< + AccessCategory + >::template archetype +{ +}; + +template <> +struct iterator_access_archetype_impl< + archetypes::readable_iterator_t +> +{ + template + struct archetype + { + typedef typename remove_cv::type value_type; + typedef Value reference; + typedef Value* pointer; + + value_type operator*() const { return static_object::get(); } + + detail::arrow_proxy operator->() const { return detail::arrow_proxy(); } + }; +}; + +template <> +struct iterator_access_archetype_impl< + archetypes::writable_iterator_t +> +{ + template + struct archetype + { + BOOST_STATIC_ASSERT(!is_const::value); + typedef void value_type; + typedef void reference; + typedef void pointer; + + detail::assign_proxy operator*() const { return detail::assign_proxy(); } + }; +}; + +template <> +struct iterator_access_archetype_impl< + archetypes::readable_writable_iterator_t +> +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, archetypes::readable_iterator_t + > + { + typedef detail::read_write_proxy reference; + + detail::read_write_proxy operator*() const { return detail::read_write_proxy(); } + }; +}; + +template <> +struct iterator_access_archetype_impl +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, archetypes::readable_iterator_t + > + { + typedef Value& reference; + + Value& operator*() const { return static_object::get(); } + Value* operator->() const { return 0; } + }; +}; + +template <> +struct iterator_access_archetype_impl +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, archetypes::readable_lvalue_iterator_t + > + { + BOOST_STATIC_ASSERT((!is_const::value)); + }; +}; + + +template +struct iterator_archetype; + +template +struct traversal_archetype_base + : detail::operator_brackets< + typename remove_cv::type + , AccessCategory + , TraversalCategory + > + , detail::traversal_archetype_< + iterator_archetype + , Value + , TraversalCategory + > +{ +}; + +namespace detail +{ + template + struct iterator_archetype_base + : iterator_access_archetype + , traversal_archetype_base + { + typedef iterator_access_archetype access; + + typedef typename detail::facade_iterator_category< + TraversalCategory + , typename mpl::eval_if< + archetypes::has_access< + AccessCategory, archetypes::writable_iterator_t + > + , remove_const + , add_const + >::type + , typename access::reference + >::type iterator_category; + + // Needed for some broken libraries (see below) + struct workaround_iterator_base + { + typedef typename iterator_archetype_base::iterator_category iterator_category; + typedef Value value_type; + typedef typename traversal_archetype_base< + Value, AccessCategory, TraversalCategory + >::difference_type difference_type; + typedef typename access::pointer pointer; + typedef typename access::reference reference; + }; + }; +} + +template +struct iterator_archetype + : public detail::iterator_archetype_base + + // These broken libraries require derivation from std::iterator + // (or related magic) in order to handle iter_swap and other + // iterator operations +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ + || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) + , public detail::iterator_archetype_base< + Value, AccessCategory, TraversalCategory + >::workaround_iterator_base +# endif +{ + // Derivation from std::iterator above caused references to nested + // types to be ambiguous, so now we have to redeclare them all + // here. +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ + || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) + + typedef detail::iterator_archetype_base< + Value,AccessCategory,TraversalCategory + > base; + + typedef typename base::value_type value_type; + typedef typename base::reference reference; + typedef typename base::pointer pointer; + typedef typename base::difference_type difference_type; + typedef typename base::iterator_category iterator_category; +# endif + + iterator_archetype() { } + iterator_archetype(iterator_archetype const& x) + : detail::iterator_archetype_base< + Value + , AccessCategory + , TraversalCategory + >(x) + {} + + iterator_archetype& operator=(iterator_archetype const&) + { return *this; } + +# if 0 + // Optional conversion from mutable + iterator_archetype( + iterator_archetype< + typename detail::convertible_type::type + , AccessCategory + , TraversalCategory> const& + ); +# endif +}; + +} // namespace iterators + +// Backward compatibility names +namespace iterator_archetypes = iterators::archetypes; +using iterators::access_archetype; +using iterators::traversal_archetype; +using iterators::iterator_archetype; +using iterators::undefined; +using iterators::iterator_access_archetype_impl; +using iterators::traversal_archetype_base; + +} // namespace boost + +#endif // BOOST_ITERATOR_ARCHETYPES_HPP diff --git a/boost/iterator/minimum_category.hpp b/boost/iterator/minimum_category.hpp new file mode 100644 index 00000000..15679bc7 --- /dev/null +++ b/boost/iterator/minimum_category.hpp @@ -0,0 +1,95 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to 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) +#ifndef BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ +# define BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ + +# include +# include +# include + +# include +# include + +namespace boost { +namespace iterators { +namespace detail { + +template +struct minimum_category_impl; + +template +struct error_not_related_by_convertibility; + +template <> +struct minimum_category_impl +{ + template struct apply + { + typedef T2 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + { + typedef T1 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + { + BOOST_STATIC_ASSERT((is_same::value)); + typedef T1 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + : error_not_related_by_convertibility + { + }; +}; + +} // namespace detail + +// +// Returns the minimum category type or fails to compile +// if T1 and T2 are unrelated. +// +template +struct minimum_category +{ + typedef boost::iterators::detail::minimum_category_impl< + ::boost::is_convertible::value + , ::boost::is_convertible::value + > outer; + + typedef typename outer::template apply inner; + typedef typename inner::type type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2)) +}; + +template <> +struct minimum_category +{ + template + struct apply : minimum_category + {}; + + BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(2,minimum_category,(mpl::_1,mpl::_2)) +}; + +} // namespace iterators + +} // namespace boost + +#endif // BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ diff --git a/boost/iterator/new_iterator_tests.hpp b/boost/iterator/new_iterator_tests.hpp new file mode 100644 index 00000000..2091e597 --- /dev/null +++ b/boost/iterator/new_iterator_tests.hpp @@ -0,0 +1,265 @@ +#ifndef BOOST_NEW_ITERATOR_TESTS_HPP +# define BOOST_NEW_ITERATOR_TESTS_HPP + +// +// Copyright (c) David Abrahams 2001. +// Copyright (c) Jeremy Siek 2001-2003. +// Copyright (c) Thomas Witt 2002. +// +// Use, modification and distribution is subject to 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) +// + +// This is meant to be the beginnings of a comprehensive, generic +// test suite for STL concepts such as iterators and containers. +// +// Revision History: +// 28 Oct 2002 Started update for new iterator categories +// (Jeremy Siek) +// 28 Apr 2002 Fixed input iterator requirements. +// For a == b a++ == b++ is no longer required. +// See 24.1.1/3 for details. +// (Thomas Witt) +// 08 Feb 2001 Fixed bidirectional iterator test so that +// --i is no longer a precondition. +// (Jeremy Siek) +// 04 Feb 2001 Added lvalue test, corrected preconditions +// (David Abrahams) + +# include +# include +# include // for detail::dummy_constructor +# include +# include +# include +# include +# include +# include + +# include +# include +# include + +namespace boost { + + +// Do separate tests for *i++ so we can treat, e.g., smart pointers, +// as readable and/or writable iterators. +template +void readable_iterator_traversal_test(Iterator i1, T v, mpl::true_) +{ + T v2(*i1++); + BOOST_TEST(v == v2); +} + +template +void readable_iterator_traversal_test(const Iterator i1, T v, mpl::false_) +{} + +template +void writable_iterator_traversal_test(Iterator i1, T v, mpl::true_) +{ + ++i1; // we just wrote into that position + *i1++ = v; + Iterator x(i1++); + (void)x; +} + +template +void writable_iterator_traversal_test(const Iterator i1, T v, mpl::false_) +{} + + +// Preconditions: *i == v +template +void readable_iterator_test(const Iterator i1, T v) +{ + Iterator i2(i1); // Copy Constructible + typedef typename std::iterator_traits::reference ref_t; + ref_t r1 = *i1; + ref_t r2 = *i2; + T v1 = r1; + T v2 = r2; + BOOST_TEST(v1 == v); + BOOST_TEST(v2 == v); + +# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + readable_iterator_traversal_test(i1, v, detail::is_postfix_incrementable()); + + // I think we don't really need this as it checks the same things as + // the above code. + BOOST_STATIC_ASSERT(is_readable_iterator::value); +# endif +} + +template +void writable_iterator_test(Iterator i, T v, T v2) +{ + Iterator i2(i); // Copy Constructible + *i2 = v; + +# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + writable_iterator_traversal_test( + i, v2, mpl::and_< + detail::is_incrementable + , detail::is_postfix_incrementable + >()); +# endif +} + +template +void swappable_iterator_test(Iterator i, Iterator j) +{ + Iterator i2(i), j2(j); + typename std::iterator_traits::value_type bi = *i, bj = *j; + iter_swap(i2, j2); + typename std::iterator_traits::value_type ai = *i, aj = *j; + BOOST_TEST(bi == aj && bj == ai); +} + +template +void constant_lvalue_iterator_test(Iterator i, T v1) +{ + Iterator i2(i); + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::reference reference; + BOOST_STATIC_ASSERT((is_same::value)); + const T& v2 = *i2; + BOOST_TEST(v1 == v2); +# ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!is_non_const_lvalue_iterator::value); +# endif +} + +template +void non_const_lvalue_iterator_test(Iterator i, T v1, T v2) +{ + Iterator i2(i); + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::reference reference; + BOOST_STATIC_ASSERT((is_same::value)); + T& v3 = *i2; + BOOST_TEST(v1 == v3); + + // A non-const lvalue iterator is not neccessarily writable, but we + // are assuming the value_type is assignable here + *i = v2; + + T& v4 = *i2; + BOOST_TEST(v2 == v4); +# ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(is_non_const_lvalue_iterator::value); +# endif +} + +template +void forward_readable_iterator_test(Iterator i, Iterator j, T val1, T val2) +{ + Iterator i2; + Iterator i3(i); + i2 = i; + BOOST_TEST(i2 == i3); + BOOST_TEST(i != j); + BOOST_TEST(i2 != j); + readable_iterator_test(i, val1); + readable_iterator_test(i2, val1); + readable_iterator_test(i3, val1); + + BOOST_TEST(i == i2++); + BOOST_TEST(i != ++i3); + + readable_iterator_test(i2, val2); + readable_iterator_test(i3, val2); + + readable_iterator_test(i, val1); +} + +template +void forward_swappable_iterator_test(Iterator i, Iterator j, T val1, T val2) +{ + forward_readable_iterator_test(i, j, val1, val2); + Iterator i2 = i; + ++i2; + swappable_iterator_test(i, i2); +} + +// bidirectional +// Preconditions: *i == v1, *++i == v2 +template +void bidirectional_readable_iterator_test(Iterator i, T v1, T v2) +{ + Iterator j(i); + ++j; + forward_readable_iterator_test(i, j, v1, v2); + ++i; + + Iterator i1 = i, i2 = i; + + BOOST_TEST(i == i1--); + BOOST_TEST(i != --i2); + + readable_iterator_test(i, v2); + readable_iterator_test(i1, v1); + readable_iterator_test(i2, v1); + + --i; + BOOST_TEST(i == i1); + BOOST_TEST(i == i2); + ++i1; + ++i2; + + readable_iterator_test(i, v1); + readable_iterator_test(i1, v2); + readable_iterator_test(i2, v2); +} + +// random access +// Preconditions: [i,i+N) is a valid range +template +void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals) +{ + bidirectional_readable_iterator_test(i, vals[0], vals[1]); + const Iterator j = i; + int c; + + for (c = 0; c < N-1; ++c) + { + BOOST_TEST(i == j + c); + BOOST_TEST(*i == vals[c]); + typename std::iterator_traits::value_type x = j[c]; + BOOST_TEST(*i == x); + BOOST_TEST(*i == *(j + c)); + BOOST_TEST(*i == *(c + j)); + ++i; + BOOST_TEST(i > j); + BOOST_TEST(i >= j); + BOOST_TEST(j <= i); + BOOST_TEST(j < i); + } + + Iterator k = j + N - 1; + for (c = 0; c < N-1; ++c) + { + BOOST_TEST(i == k - c); + BOOST_TEST(*i == vals[N - 1 - c]); + typename std::iterator_traits::value_type x = j[N - 1 - c]; + BOOST_TEST(*i == x); + Iterator q = k - c; + BOOST_TEST(*i == *q); + BOOST_TEST(i > j); + BOOST_TEST(i >= j); + BOOST_TEST(j <= i); + BOOST_TEST(j < i); + --i; + } +} + +} // namespace boost + +# include + +#endif // BOOST_NEW_ITERATOR_TESTS_HPP diff --git a/boost/iterator/permutation_iterator.hpp b/boost/iterator/permutation_iterator.hpp new file mode 100644 index 00000000..3876f3d9 --- /dev/null +++ b/boost/iterator/permutation_iterator.hpp @@ -0,0 +1,76 @@ +// (C) Copyright Toon Knapen 2001. +// (C) Copyright David Abrahams 2003. +// (C) Copyright Roland Richter 2003. +// 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) + +#ifndef BOOST_PERMUTATION_ITERATOR_HPP +#define BOOST_PERMUTATION_ITERATOR_HPP + +#include + +#include + + +namespace boost { +namespace iterators { + +template< class ElementIterator + , class IndexIterator> +class permutation_iterator + : public iterator_adaptor< + permutation_iterator + , IndexIterator, typename std::iterator_traits::value_type + , use_default, typename std::iterator_traits::reference> +{ + typedef iterator_adaptor< + permutation_iterator + , IndexIterator, typename std::iterator_traits::value_type + , use_default, typename std::iterator_traits::reference> super_t; + + friend class iterator_core_access; + +public: + permutation_iterator() : m_elt_iter() {} + + explicit permutation_iterator(ElementIterator x, IndexIterator y) + : super_t(y), m_elt_iter(x) {} + + template + permutation_iterator( + permutation_iterator const& r + , typename enable_if_convertible::type* = 0 + , typename enable_if_convertible::type* = 0 + ) + : super_t(r.base()), m_elt_iter(r.m_elt_iter) + {} + +private: + typename super_t::reference dereference() const + { return *(m_elt_iter + *this->base()); } + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + template friend class permutation_iterator; +#else + public: +#endif + ElementIterator m_elt_iter; +}; + + +template +inline permutation_iterator +make_permutation_iterator( ElementIterator e, IndexIterator i ) +{ + return permutation_iterator( e, i ); +} + +} // namespace iterators + +using iterators::permutation_iterator; +using iterators::make_permutation_iterator; + +} // namespace boost + +#endif diff --git a/boost/iterator/transform_iterator.hpp b/boost/iterator/transform_iterator.hpp new file mode 100644 index 00000000..5b2b810e --- /dev/null +++ b/boost/iterator/transform_iterator.hpp @@ -0,0 +1,179 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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) +#ifndef BOOST_TRANSFORM_ITERATOR_23022003THW_HPP +#define BOOST_TRANSFORM_ITERATOR_23022003THW_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) +#include +#endif + +#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) +#include +#endif + +#include + + +namespace boost { +namespace iterators { + + template + class transform_iterator; + + namespace detail + { + // Compute the iterator_adaptor instantiation to be used for transform_iterator + template + struct transform_iterator_base + { + private: + // By default, dereferencing the iterator yields the same as + // the function. + typedef typename ia_dflt_help< + Reference +#ifdef BOOST_RESULT_OF_USE_TR1 + , result_of::reference)> +#else + , result_of::reference)> +#endif + >::type reference; + + // To get the default for Value: remove any reference on the + // result type, but retain any constness to signal + // non-writability. Note that if we adopt Thomas' suggestion + // to key non-writability *only* on the Reference argument, + // we'd need to strip constness here as well. + typedef typename ia_dflt_help< + Value + , remove_reference + >::type cv_value_type; + + public: + typedef iterator_adaptor< + transform_iterator + , Iterator + , cv_value_type + , use_default // Leave the traversal category alone + , reference + > type; + }; + } + + template + class transform_iterator + : public boost::iterators::detail::transform_iterator_base::type + { + typedef typename + boost::iterators::detail::transform_iterator_base::type + super_t; + + friend class iterator_core_access; + + public: + transform_iterator() { } + + transform_iterator(Iterator const& x, UnaryFunc f) + : super_t(x), m_f(f) { } + + explicit transform_iterator(Iterator const& x) + : super_t(x) + { + // Pro8 is a little too aggressive about instantiating the + // body of this function. +#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + // don't provide this constructor if UnaryFunc is a + // function pointer type, since it will be 0. Too dangerous. + BOOST_STATIC_ASSERT(is_class::value); +#endif + } + + template < + class OtherUnaryFunction + , class OtherIterator + , class OtherReference + , class OtherValue> + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 +#if !BOOST_WORKAROUND(BOOST_MSVC, == 1310) + , typename enable_if_convertible::type* = 0 +#endif + ) + : super_t(t.base()), m_f(t.functor()) + {} + + UnaryFunc functor() const + { return m_f; } + + private: + typename super_t::reference dereference() const + { return m_f(*this->base()); } + + // Probably should be the initial base class so it can be + // optimized away via EBO if it is an empty class. + UnaryFunc m_f; + }; + + template + inline transform_iterator + make_transform_iterator(Iterator it, UnaryFunc fun) + { + return transform_iterator(it, fun); + } + + // Version which allows explicit specification of the UnaryFunc + // type. + // + // This generator is not provided if UnaryFunc is a function + // pointer type, because it's too dangerous: the default-constructed + // function pointer in the iterator be 0, leading to a runtime + // crash. + template + inline typename iterators::enable_if< + is_class // We should probably find a cheaper test than is_class<> + , transform_iterator + >::type + make_transform_iterator(Iterator it) + { + return transform_iterator(it, UnaryFunc()); + } + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + template + inline transform_iterator< Return (*)(Argument), Iterator, Return> + make_transform_iterator(Iterator it, Return (*fun)(Argument)) + { + return transform_iterator(it, fun); + } +#endif + +} // namespace iterators + +using iterators::transform_iterator; +using iterators::make_transform_iterator; + +} // namespace boost + +#include + +#endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP diff --git a/boost/iterator/zip_iterator.hpp b/boost/iterator/zip_iterator.hpp new file mode 100644 index 00000000..f5780aeb --- /dev/null +++ b/boost/iterator/zip_iterator.hpp @@ -0,0 +1,367 @@ +// Copyright David Abrahams and Thomas Becker 2000-2006. +// Copyright Kohei Takahashi 2012-2014. +// +// 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) + +#ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_ +# define BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_ + +#include +#include +#include +#include // for enable_if_convertible +#include + +#include + +#include // for std::pair +#include // for backward compatibility + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace iterators { + + // Zip iterator forward declaration for zip_iterator_base + template + class zip_iterator; + + namespace detail + { + + // Functors to be used with tuple algorithms + // + template + class advance_iterator + { + public: + advance_iterator(DiffType step) : m_step(step) {} + + template + void operator()(Iterator& it) const + { it += m_step; } + + private: + DiffType m_step; + }; + // + struct increment_iterator + { + template + void operator()(Iterator& it) const + { ++it; } + }; + // + struct decrement_iterator + { + template + void operator()(Iterator& it) const + { --it; } + }; + // + struct dereference_iterator + { + template + struct result; + + template + struct result + { + typedef typename + remove_cv::type>::type + iterator; + + typedef typename iterator_reference::type type; + }; + + template + typename result::type + operator()(Iterator const& it) const + { return *it; } + }; + + // Metafunction to obtain the type of the tuple whose element types + // are the reference types of an iterator tuple. + // + template + struct tuple_of_references + : mpl::transform< + IteratorTuple, + iterator_reference + > + { + }; + + // Specialization for std::pair + template + struct tuple_of_references > + { + typedef std::pair< + typename iterator_reference::type + , typename iterator_reference::type + > type; + }; + + // Metafunction to obtain the minimal traversal tag in a tuple + // of iterators. + // + template + struct minimum_traversal_category_in_iterator_tuple + { + typedef typename mpl::transform< + IteratorTuple + , pure_traversal_tag > + >::type tuple_of_traversal_tags; + + typedef typename mpl::fold< + tuple_of_traversal_tags + , random_access_traversal_tag + , minimum_category<> + >::type type; + }; + + template + struct minimum_traversal_category_in_iterator_tuple > + { + typedef typename pure_traversal_tag< + typename iterator_traversal::type + >::type iterator1_traversal; + typedef typename pure_traversal_tag< + typename iterator_traversal::type + >::type iterator2_traversal; + + typedef typename minimum_category< + iterator1_traversal + , typename minimum_category< + iterator2_traversal + , random_access_traversal_tag + >::type + >::type type; + }; + + /////////////////////////////////////////////////////////////////// + // + // Class zip_iterator_base + // + // Builds and exposes the iterator facade type from which the zip + // iterator will be derived. + // + template + struct zip_iterator_base + { + private: + // Reference type is the type of the tuple obtained from the + // iterators' reference types. + typedef typename + detail::tuple_of_references::type reference; + + // Value type is the same as reference type. + typedef reference value_type; + + // Difference type is the first iterator's difference type + typedef typename iterator_difference< + typename mpl::at_c::type + >::type difference_type; + + // Traversal catetgory is the minimum traversal category in the + // iterator tuple. + typedef typename + detail::minimum_traversal_category_in_iterator_tuple< + IteratorTuple + >::type traversal_category; + public: + + // The iterator facade type from which the zip iterator will + // be derived. + typedef iterator_facade< + zip_iterator, + value_type, + traversal_category, + reference, + difference_type + > type; + }; + + template <> + struct zip_iterator_base + { + typedef int type; + }; + + template + struct converter + { + template + static reference call(Seq seq) + { + typedef typename fusion::traits::tag_of::type tag; + return fusion::convert(seq); + } + }; + + template + struct converter > + { + typedef std::pair reference; + template + static reference call(Seq seq) + { + return reference( + fusion::at_c<0>(seq) + , fusion::at_c<1>(seq)); + } + }; + } + + ///////////////////////////////////////////////////////////////////// + // + // zip_iterator class definition + // + template + class zip_iterator : + public detail::zip_iterator_base::type + { + + // Typedef super_t as our base class. + typedef typename + detail::zip_iterator_base::type super_t; + + // iterator_core_access is the iterator's best friend. + friend class iterator_core_access; + + public: + + // Construction + // ============ + + // Default constructor + zip_iterator() { } + + // Constructor from iterator tuple + zip_iterator(IteratorTuple iterator_tuple) + : m_iterator_tuple(iterator_tuple) + { } + + // Copy constructor + template + zip_iterator( + const zip_iterator& other, + typename enable_if_convertible< + OtherIteratorTuple, + IteratorTuple + >::type* = 0 + ) : m_iterator_tuple(other.get_iterator_tuple()) + {} + + // Get method for the iterator tuple. + const IteratorTuple& get_iterator_tuple() const + { return m_iterator_tuple; } + + private: + + // Implementation of Iterator Operations + // ===================================== + + // Dereferencing returns a tuple built from the dereferenced + // iterators in the iterator tuple. + typename super_t::reference dereference() const + { + typedef typename super_t::reference reference; + typedef detail::converter gen; + return gen::call(fusion::transform( + get_iterator_tuple(), + detail::dereference_iterator())); + } + + // Two zip iterators are equal if all iterators in the iterator + // tuple are equal. NOTE: It should be possible to implement this + // as + // + // return get_iterator_tuple() == other.get_iterator_tuple(); + // + // but equality of tuples currently (7/2003) does not compile + // under several compilers. No point in bringing in a bunch + // of #ifdefs here. + // + template + bool equal(const zip_iterator& other) const + { + return fusion::equal_to( + get_iterator_tuple(), + other.get_iterator_tuple()); + } + + // Advancing a zip iterator means to advance all iterators in the + // iterator tuple. + void advance(typename super_t::difference_type n) + { + fusion::for_each( + m_iterator_tuple, + detail::advance_iterator(n)); + } + // Incrementing a zip iterator means to increment all iterators in + // the iterator tuple. + void increment() + { + fusion::for_each( + m_iterator_tuple, + detail::increment_iterator()); + } + + // Decrementing a zip iterator means to decrement all iterators in + // the iterator tuple. + void decrement() + { + fusion::for_each( + m_iterator_tuple, + detail::decrement_iterator()); + } + + // Distance is calculated using the first iterator in the tuple. + template + typename super_t::difference_type distance_to( + const zip_iterator& other + ) const + { + return fusion::at_c<0>(other.get_iterator_tuple()) - + fusion::at_c<0>(this->get_iterator_tuple()); + } + + // Data Members + // ============ + + // The iterator tuple. + IteratorTuple m_iterator_tuple; + + }; + + // Make function for zip iterator + // + template + inline zip_iterator + make_zip_iterator(IteratorTuple t) + { return zip_iterator(t); } + +} // namespace iterators + +using iterators::zip_iterator; +using iterators::make_zip_iterator; + +} // namespace boost + +#endif diff --git a/boost/mp11/algorithm.hpp b/boost/mp11/algorithm.hpp new file mode 100644 index 00000000..be377f5a --- /dev/null +++ b/boost/mp11/algorithm.hpp @@ -0,0 +1,1327 @@ +#ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED +#define BOOST_MP11_ALGORITHM_HPP_INCLUDED + +// Copyright 2015-2019 Peter Dimov +// +// 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_transform +namespace detail +{ + +template class F, class... L> struct mp_transform_impl +{ +}; + +template class F, template class L, class... T> struct mp_transform_impl> +{ +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) + + template struct f { using type = F; }; + + using type = L::type...>; + +#else + + using type = L...>; + +#endif +}; + +template class F, template class L1, class... T1, template class L2, class... T2> struct mp_transform_impl, L2> +{ +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) + + template struct f { using type = F; }; + + using type = L1::type...>; + +#else + + using type = L1...>; + +#endif +}; + +template class F, template class L1, class... T1, template class L2, class... T2, template class L3, class... T3> struct mp_transform_impl, L2, L3> +{ +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) + + template struct f { using type = F; }; + + using type = L1::type...>; + +#else + + using type = L1...>; + +#endif +}; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, == 1900 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 40800 ) + +template using mp_same_size_1 = mp_same...>; +template struct mp_same_size_2: mp_defer {}; + +#endif + +struct list_size_mismatch +{ +}; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) + +template class F, class... L> struct mp_transform_cuda_workaround +{ + using type = mp_if...>, detail::mp_transform_impl, detail::list_size_mismatch>; +}; + +#endif + +} // namespace detail + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, == 1900 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 40800 ) + +template class F, class... L> using mp_transform = typename mp_if::type, detail::mp_transform_impl, detail::list_size_mismatch>::type; + +#else + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) + +template class F, class... L> using mp_transform = typename detail::mp_transform_cuda_workaround< F, L...>::type::type; + +#else + +template class F, class... L> using mp_transform = typename mp_if...>, detail::mp_transform_impl, detail::list_size_mismatch>::type; + +#endif + +#endif + +template using mp_transform_q = mp_transform; + +namespace detail +{ + +template class F, template class L1, class... T1, template class L2, class... T2, template class L3, class... T3, template class L4, class... T4, class... L> struct mp_transform_impl, L2, L3, L4, L...> +{ + using A1 = L1...>; + + template using _f = mp_transform; + + using A2 = mp_fold, A1, _f>; + + template using _g = mp_apply; + + using type = mp_transform<_g, A2>; +}; + +} // namespace detail + +// mp_transform_if +namespace detail +{ + +template class P, template class F, class... L> struct mp_transform_if_impl +{ + // the stupid quote-unquote dance avoids "pack expansion used as argument for non-pack parameter of alias template" + + using Qp = mp_quote

; + using Qf = mp_quote; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) + + template struct _f_ { using type = mp_eval_if_q>, mp_first>, Qf, U...>; }; + template using _f = typename _f_::type; + +#else + + template using _f = mp_eval_if_q>, mp_first>, Qf, U...>; + +#endif + + using type = mp_transform<_f, L...>; +}; + +} // namespace detail + +template class P, template class F, class... L> using mp_transform_if = typename detail::mp_transform_if_impl::type; +template using mp_transform_if_q = typename detail::mp_transform_if_impl::type; + +// mp_filter +namespace detail +{ + +template class P, class L1, class... L> struct mp_filter_impl +{ + using Qp = mp_quote

; + + template using _f = mp_if< mp_invoke_q, mp_list, mp_list<> >; + + using _t1 = mp_transform<_f, L1, L...>; + using _t2 = mp_apply; + + using type = mp_assign; +}; + +} // namespace detail + +template class P, class... L> using mp_filter = typename detail::mp_filter_impl::type; +template using mp_filter_q = typename detail::mp_filter_impl::type; + +// mp_fill +namespace detail +{ + +template struct mp_fill_impl +{ +// An error "no type named 'type'" here means that the L argument of mp_fill is not a list +}; + +template class L, class... T, class V> struct mp_fill_impl, V> +{ +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1900 ) + + template struct _f { using type = V; }; + using type = L::type...>; + +#else + + template using _f = V; + using type = L<_f...>; + +#endif +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto... A, class V> struct mp_fill_impl, V> +{ + using type = L<((void)A, V::value)...>; +}; + +#endif + +} // namespace detail + +template using mp_fill = typename detail::mp_fill_impl::type; + +// mp_contains +template using mp_contains = mp_to_bool>; + +// mp_repeat(_c) +namespace detail +{ + +template struct mp_repeat_c_impl +{ + using _l1 = typename mp_repeat_c_impl::type; + using _l2 = typename mp_repeat_c_impl::type; + + using type = mp_append<_l1, _l1, _l2>; +}; + +template struct mp_repeat_c_impl +{ + using type = mp_clear; +}; + +template struct mp_repeat_c_impl +{ + using type = L; +}; + +} // namespace detail + +template using mp_repeat_c = typename detail::mp_repeat_c_impl::type; +template using mp_repeat = typename detail::mp_repeat_c_impl::type; + +// mp_product +namespace detail +{ + +template class F, class P, class... L> struct mp_product_impl_2 +{ +}; + +template class F, class P> struct mp_product_impl_2 +{ + using type = mp_list>; +}; + +template class F, class P, template class L1, class... T1, class... L> struct mp_product_impl_2, L...> +{ + using type = mp_append, L...>::type...>; +}; + +template class F, class... L> struct mp_product_impl +{ +}; + +template class F> struct mp_product_impl +{ + using type = mp_list< F<> >; +}; + +template class F, class L1, class... L> struct mp_product_impl +{ + using type = mp_assign, L1, L...>::type>; +}; + +} // namespace detail + +template class F, class... L> using mp_product = typename detail::mp_product_impl::type; +template using mp_product_q = typename detail::mp_product_impl::type; + +// mp_drop(_c) +namespace detail +{ + +template struct mp_drop_impl; + +template class L, class... T, template class L2, class... U> struct mp_drop_impl, L2, mp_true> +{ + template static mp_identity> f( U*..., mp_identity*... ); + + using R = decltype( f( static_cast*>(0) ... ) ); + + using type = typename R::type; +}; + +} // namespace detail + +template using mp_drop_c = mp_assign, mp_repeat_c, N>, mp_bool::value>>::type>; + +template using mp_drop = mp_drop_c; + +// mp_from_sequence +namespace detail +{ + +template struct mp_from_sequence_impl; + +template class S, class U, U... J, class F> struct mp_from_sequence_impl, F> +{ + using type = mp_list_c; +}; + +} // namespace detail + +template> using mp_from_sequence = typename detail::mp_from_sequence_impl::type; + +// mp_iota(_c) +template using mp_iota_c = mp_from_sequence, mp_size_t>; +template> using mp_iota = mp_from_sequence::type, N::value>, F>; + +// mp_at(_c) +namespace detail +{ + +template struct mp_at_c_impl; + +#if defined(BOOST_MP11_HAS_TYPE_PACK_ELEMENT) + +template class L, class... T, std::size_t I> struct mp_at_c_impl, I> +{ + using type = __type_pack_element; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto... A, std::size_t I> struct mp_at_c_impl, I> +{ + using type = __type_pack_element...>; +}; + +#endif + +#else + +template struct mp_at_c_impl +{ + using _map = mp_transform >, mp_rename>; + using type = mp_second > >; +}; + +#endif + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) + +template struct mp_at_c_cuda_workaround +{ + using type = mp_if_c<(I < mp_size::value), detail::mp_at_c_impl, void>; +}; + +#endif + +} // namespace detail + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) + +template using mp_at_c = typename detail::mp_at_c_cuda_workaround< L, I >::type::type; + +#else + +template using mp_at_c = typename mp_if_c<(I < mp_size::value), detail::mp_at_c_impl, void>::type; + +#endif + +template using mp_at = mp_at_c; + +// mp_take(_c) +namespace detail +{ + +template struct mp_take_c_impl +{ +}; + +template class L, class... T> +struct mp_take_c_impl<0, L> +{ + using type = L<>; +}; + +template class L, class T1, class... T> +struct mp_take_c_impl<1, L> +{ + using type = L; +}; + +template class L, class T1, class T2, class... T> +struct mp_take_c_impl<2, L> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class... T> +struct mp_take_c_impl<3, L> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class... T> +struct mp_take_c_impl<4, L> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class... T> +struct mp_take_c_impl<5, L> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class... T> +struct mp_take_c_impl<6, L> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class... T> +struct mp_take_c_impl<7, L> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class... T> +struct mp_take_c_impl<8, L> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class... T> +struct mp_take_c_impl<9, L> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T, std::size_t N> +struct mp_take_c_impl, typename std::enable_if= 10>::type> +{ + using type = mp_append, typename mp_take_c_impl>::type>; +}; + +} // namespace detail + +template using mp_take_c = mp_assign>::type>; +template using mp_take = mp_take_c; + +// mp_back +template using mp_back = mp_at_c::value - 1>; + +// mp_pop_back +template using mp_pop_back = mp_take_c::value - 1>; + +// mp_replace +namespace detail +{ + +template struct mp_replace_impl; + +template class L, class... T, class V, class W> struct mp_replace_impl, V, W> +{ +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) + template struct _f { using type = mp_if, W, A>; }; + using type = L::type...>; +#else + template using _f = mp_if, W, A>; + using type = L<_f...>; +#endif +}; + +} // namespace detail + +template using mp_replace = typename detail::mp_replace_impl::type; + +// mp_replace_if +namespace detail +{ + +template class P, class W> struct mp_replace_if_impl; + +template class L, class... T, template class P, class W> struct mp_replace_if_impl, P, W> +{ +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) + template struct _f { using type = mp_if, W, U>; }; + using type = L::type...>; +#else + template using _f = mp_if, W, U>; + using type = L<_f...>; +#endif +}; + +} // namespace detail + +template class P, class W> using mp_replace_if = typename detail::mp_replace_if_impl::type; +template using mp_replace_if_q = mp_replace_if; + +// mp_copy_if +// in detail/mp_copy_if.hpp + +// mp_remove +namespace detail +{ + +template struct mp_remove_impl; + +template class L, class... T, class V> struct mp_remove_impl, V> +{ +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) + template struct _f { using type = mp_if, mp_list<>, mp_list>; }; + using type = mp_append, typename _f::type...>; +#else + template using _f = mp_if, mp_list<>, mp_list>; + using type = mp_append, _f...>; +#endif +}; + +} // namespace detail + +template using mp_remove = typename detail::mp_remove_impl::type; + +// mp_remove_if +// in detail/mp_remove_if.hpp + +// mp_flatten> +namespace detail +{ + +template struct mp_flatten_impl +{ + template using fn = mp_if, T, mp_list>; +}; + +} // namespace detail + +template> using mp_flatten = mp_apply, L>, mp_clear>>; + +// mp_partition +namespace detail +{ + +template class P> struct mp_partition_impl; + +template class L, class... T, template class P> struct mp_partition_impl, P> +{ + using type = L, P>, mp_remove_if, P>>; +}; + +} // namespace detail + +template class P> using mp_partition = typename detail::mp_partition_impl::type; +template using mp_partition_q = mp_partition; + +// mp_sort +namespace detail +{ + +template class P> struct mp_sort_impl; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) + +template class L, class... T, template class P> struct mp_sort_impl, P> +{ + static_assert( sizeof...(T) == 0, "T... must be empty" ); + using type = L<>; +}; + +#else + +template class L, template class P> struct mp_sort_impl, P> +{ + using type = L<>; +}; + +#endif + +template class L, class T1, template class P> struct mp_sort_impl, P> +{ + using type = L; +}; + +template class L, class T1, class... T, template class P> struct mp_sort_impl, P> +{ + template using F = P; + + using part = mp_partition, F>; + + using S1 = typename mp_sort_impl, P>::type; + using S2 = typename mp_sort_impl, P>::type; + + using type = mp_append, S2>; +}; + +} // namespace detail + +template class P> using mp_sort = typename detail::mp_sort_impl::type; +template using mp_sort_q = mp_sort; + +// mp_nth_element(_c) +namespace detail +{ + +template class P> struct mp_nth_element_impl; + +template class L, class T1, std::size_t I, template class P> struct mp_nth_element_impl, I, P> +{ + static_assert( I == 0, "mp_nth_element index out of range" ); + using type = T1; +}; + +template class L, class T1, class... T, std::size_t I, template class P> struct mp_nth_element_impl, I, P> +{ + static_assert( I < 1 + sizeof...(T), "mp_nth_element index out of range" ); + + template using F = P; + + using part = mp_partition, F>; + + using L1 = mp_first; + static std::size_t const N1 = mp_size::value; + + using L2 = mp_second; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) + + struct detail + { + struct mp_nth_element_impl_cuda_workaround + { + using type = mp_cond< + + mp_bool<(I < N1)>, mp_nth_element_impl, + mp_bool<(I == N1)>, mp_identity, + mp_true, mp_nth_element_impl + + >; + }; + }; + + using type = typename detail::mp_nth_element_impl_cuda_workaround::type::type; + +#else + + using type = typename mp_cond< + + mp_bool<(I < N1)>, mp_nth_element_impl, + mp_bool<(I == N1)>, mp_identity, + mp_true, mp_nth_element_impl + + >::type; + +#endif +}; + +} // namespace detail + +template class P> using mp_nth_element_c = typename detail::mp_nth_element_impl::type; +template class P> using mp_nth_element = typename detail::mp_nth_element_impl::type; +template using mp_nth_element_q = mp_nth_element; + +// mp_find +namespace detail +{ + +template struct mp_find_impl; + +#if BOOST_MP11_CLANG && defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) + +struct mp_index_holder +{ + std::size_t i_; + bool f_; +}; + +constexpr inline mp_index_holder operator+( mp_index_holder const & v, bool f ) +{ + if( v.f_ ) + { + return v; + } + else if( f ) + { + return { v.i_, true }; + } + else + { + return { v.i_ + 1, false }; + } +} + +template class L, class... T, class V> struct mp_find_impl, V> +{ + static constexpr mp_index_holder _v{ 0, false }; + using type = mp_size_t< (_v + ... + std::is_same::value).i_ >; +}; + +#elif !defined( BOOST_MP11_NO_CONSTEXPR ) + +template class L, class V> struct mp_find_impl, V> +{ + using type = mp_size_t<0>; +}; + +#if defined( BOOST_MP11_HAS_CXX14_CONSTEXPR ) + +constexpr std::size_t cx_find_index( bool const * first, bool const * last ) +{ + std::size_t m = 0; + + while( first != last && !*first ) + { + ++m; + ++first; + } + + return m; +} + +#else + +constexpr std::size_t cx_find_index( bool const * first, bool const * last ) +{ + return first == last || *first? 0: 1 + cx_find_index( first + 1, last ); +} + +#endif + +template class L, class... T, class V> struct mp_find_impl, V> +{ + static constexpr bool _v[] = { std::is_same::value... }; + using type = mp_size_t< cx_find_index( _v, _v + sizeof...(T) ) >; +}; + +#else + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) + +template class L, class... T, class V> struct mp_find_impl, V> +{ + static_assert( sizeof...(T) == 0, "T... must be empty" ); + using type = mp_size_t<0>; +}; + +#else + +template class L, class V> struct mp_find_impl, V> +{ + using type = mp_size_t<0>; +}; + +#endif + +template class L, class... T, class V> struct mp_find_impl, V> +{ + using type = mp_size_t<0>; +}; + +template class L, class T1, class... T, class V> struct mp_find_impl, V> +{ + using _r = typename mp_find_impl, V>::type; + using type = mp_size_t<1 + _r::value>; +}; + +#endif + +} // namespace detail + +template using mp_find = typename detail::mp_find_impl::type; + +// mp_find_if +namespace detail +{ + +template class P> struct mp_find_if_impl; + +#if BOOST_MP11_CLANG && defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) + +template class L, class... T, template class P> struct mp_find_if_impl, P> +{ + static constexpr mp_index_holder _v{ 0, false }; + using type = mp_size_t< (_v + ... + P::value).i_ >; +}; + +#elif !defined( BOOST_MP11_NO_CONSTEXPR ) + +template class L, template class P> struct mp_find_if_impl, P> +{ + using type = mp_size_t<0>; +}; + +template class L, class... T, template class P> struct mp_find_if_impl, P> +{ + static constexpr bool _v[] = { P::value... }; + using type = mp_size_t< cx_find_index( _v, _v + sizeof...(T) ) >; +}; + +#else + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) + +template class L, class... T, template class P> struct mp_find_if_impl, P> +{ + static_assert( sizeof...(T) == 0, "T... must be empty" ); + using type = mp_size_t<0>; +}; + +#else + +template class L, template class P> struct mp_find_if_impl, P> +{ + using type = mp_size_t<0>; +}; + +#endif + +template class P> struct mp_find_if_impl_2 +{ + using _r = typename mp_find_if_impl::type; + using type = mp_size_t<1 + _r::value>; +}; + +template class L, class T1, class... T, template class P> struct mp_find_if_impl, P> +{ + using type = typename mp_if, mp_identity>, mp_find_if_impl_2, P>>::type; +}; + +#endif + +} // namespace detail + +template class P> using mp_find_if = typename detail::mp_find_if_impl::type; +template using mp_find_if_q = mp_find_if; + +// mp_reverse +namespace detail +{ + +template struct mp_reverse_impl; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) + +template class L, class... T> struct mp_reverse_impl> +{ + static_assert( sizeof...(T) == 0, "T... must be empty" ); + using type = L<>; +}; + +#else + +template class L> struct mp_reverse_impl> +{ + using type = L<>; +}; + +#endif + +template class L, class T1> struct mp_reverse_impl> +{ + using type = L; +}; + +template class L, class T1, class T2> struct mp_reverse_impl> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3> struct mp_reverse_impl> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4> struct mp_reverse_impl> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class T5> struct mp_reverse_impl> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6> struct mp_reverse_impl> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7> struct mp_reverse_impl> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8> struct mp_reverse_impl> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9> struct mp_reverse_impl> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T> struct mp_reverse_impl> +{ + using type = mp_push_back>::type, T10, T9, T8, T7, T6, T5, T4, T3, T2, T1>; +}; + +} // namespace detail + +template using mp_reverse = typename detail::mp_reverse_impl::type; + +// mp_fold +// in detail/mp_fold.hpp + +// mp_reverse_fold +namespace detail +{ + +template class F> struct mp_reverse_fold_impl; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) + +template class L, class... T, class V, template class F> struct mp_reverse_fold_impl, V, F> +{ + static_assert( sizeof...(T) == 0, "T... must be empty" ); + using type = V; +}; + +#else + +template class L, class V, template class F> struct mp_reverse_fold_impl, V, F> +{ + using type = V; +}; + +#endif + +template class L, class T1, class... T, class V, template class F> struct mp_reverse_fold_impl, V, F> +{ + using rest = typename mp_reverse_fold_impl, V, F>::type; + using type = F; +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T, class V, template class F> struct mp_reverse_fold_impl, V, F> +{ + using rest = typename mp_reverse_fold_impl, V, F>::type; + using type = F > > > > > > > > >; +}; + +} // namespace detail + +template class F> using mp_reverse_fold = typename detail::mp_reverse_fold_impl::type; +template using mp_reverse_fold_q = mp_reverse_fold; + +// mp_unique +namespace detail +{ + +template struct mp_unique_impl; + +template class L, class... T> struct mp_unique_impl> +{ + using type = mp_set_push_back, T...>; +}; + +} // namespace detail + +template using mp_unique = typename detail::mp_unique_impl::type; + +// mp_unique_if +namespace detail +{ + +template class P> struct mp_unique_if_push_back +{ + template struct impl + { + }; + + template class L, class... Ts, class T> + struct impl, T> + { + using type = mp_if...>, L, L>; + }; + + template using fn = typename impl::type; +}; + +} // namespace detail + +template class P> +using mp_unique_if = mp_fold_q, detail::mp_unique_if_push_back

>; + +template using mp_unique_if_q = mp_unique_if; + +// mp_all_of +template class P> using mp_all_of = mp_bool< mp_count_if::value == mp_size::value >; +template using mp_all_of_q = mp_all_of; + +// mp_none_of +template class P> using mp_none_of = mp_bool< mp_count_if::value == 0 >; +template using mp_none_of_q = mp_none_of; + +// mp_any_of +template class P> using mp_any_of = mp_bool< mp_count_if::value != 0 >; +template using mp_any_of_q = mp_any_of; + +// mp_replace_at_c +namespace detail +{ + +template struct mp_replace_at_impl +{ + static_assert( I::value >= 0, "mp_replace_at: I must not be negative" ); + + template using _p = std::is_same>; + template using _f = W; + + using type = mp_transform_if<_p, _f, L, mp_iota > >; +}; + +} // namespace detail + +template using mp_replace_at = typename detail::mp_replace_at_impl::type; +template using mp_replace_at_c = typename detail::mp_replace_at_impl, W>::type; + +//mp_for_each(f) +namespace detail +{ + +template BOOST_MP11_CONSTEXPR F mp_for_each_impl( mp_list, F && f ) +{ + using A = int[sizeof...(T)]; + return (void)A{ ((void)f(T()), 0)... }, std::forward(f); +} + +template BOOST_MP11_CONSTEXPR F mp_for_each_impl( mp_list<>, F && f ) +{ + return std::forward(f); +} + +} // namespace detail + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, >= 1900 ) + +// msvc has a limit of 1024 + +template BOOST_MP11_CONSTEXPR mp_if_c::value <= 1024, F> mp_for_each( F && f ) +{ + return detail::mp_for_each_impl( mp_rename(), std::forward(f) ); +} + +template BOOST_MP11_CONSTEXPR mp_if_c::value >= 1025, F> mp_for_each( F && f ) +{ + using L2 = mp_rename; + + using L3 = mp_take_c; + using L4 = mp_drop_c; + + return mp_for_each( mp_for_each( std::forward(f) ) ); +} + +#else + +template BOOST_MP11_CONSTEXPR F mp_for_each( F && f ) +{ + return detail::mp_for_each_impl( mp_rename(), std::forward(f) ); +} + +#endif + +// mp_insert +template using mp_insert = mp_append, mp_push_front, T...>>; + +// mp_insert_c +template using mp_insert_c = mp_append, mp_push_front, T...>>; + +// mp_erase +template using mp_erase = mp_append, mp_drop>; + +// mp_erase_c +template using mp_erase_c = mp_append, mp_drop_c>; + +// mp_starts_with +// contributed by Glen Joseph Fernandes (glenjofe@gmail.com) +namespace detail { + +template +struct mp_starts_with_impl { }; + +template class L1, class... T1, template class L2, + class... T2> +struct mp_starts_with_impl, L2 > { + template + static mp_false check(L); + + template + static mp_true check(mp_list); + + using type = decltype(check(mp_list())); +}; + +} // namespace detail + +template +using mp_starts_with = typename detail::mp_starts_with_impl::type; + +// mp_rotate_left(_c) +namespace detail +{ + +// limit divisor to 1 to avoid division by 0 and give a rotation of 0 for lists containing 0 or 1 elements +template using canonical_left_rotation = mp_size_t; + +// perform right rotation as a left rotation by inverting the number of elements to rotate +template using canonical_right_rotation = mp_size_t; + +// avoid errors when rotating fixed-sized lists by using mp_list for the transformation +template> using mp_rotate_impl = mp_assign, mp_take >>; + +} // namespace detail + +template using mp_rotate_left_c = detail::mp_rotate_impl::value, N>>; +template using mp_rotate_left = mp_rotate_left_c; + +// mp_rotate_right(_c) +template using mp_rotate_right_c = mp_rotate_left::value, N>>; +template using mp_rotate_right = mp_rotate_right_c; + +// mp_min_element +// mp_max_element +// in detail/mp_min_element.hpp + +// mp_power_set +namespace detail +{ + +template struct mp_power_set_impl; + +} // namespace detail + +template using mp_power_set = typename detail::mp_power_set_impl::type; + +namespace detail +{ + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) + +template class L, class... T> struct mp_power_set_impl< L > +{ + static_assert( sizeof...(T) == 0, "T... must be empty" ); + using type = L< L<> >; +}; + +#else + +template class L> struct mp_power_set_impl< L<> > +{ + using type = L< L<> >; +}; + +#endif + +template class L, class T1, class... T> struct mp_power_set_impl< L > +{ + using S1 = mp_power_set< L >; + + template using _f = mp_push_front; + + using S2 = mp_transform<_f, S1>; + + using type = mp_append< S1, S2 >; +}; + +} // namespace detail + +// mp_partial_sum +namespace detail +{ + +template class F> struct mp_partial_sum_impl_f +{ +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1900 ) + + template using fn = mp_list, T>, mp_push_back, F, T>> >; + +#else + + template, T>> using fn = mp_list, N>>; + +#endif +}; + +} // namespace detail + +template class F> using mp_partial_sum = mp_second>, detail::mp_partial_sum_impl_f> >; +template using mp_partial_sum_q = mp_partial_sum; + +// mp_iterate +namespace detail +{ + +template class F, template class R, class N> struct mp_iterate_impl; + +} // namespace detail + +template class F, template class R> using mp_iterate = typename detail::mp_iterate_impl>::type; + +namespace detail +{ + +template class F, template class R> struct mp_iterate_impl +{ + template using _f = mp_list>; + using type = mp_eval_or, _f, V>; +}; + +template class F, template class R> struct mp_iterate_impl +{ + using type = mp_push_front, F, R>, F>; +}; + +} // namespace detail + +template using mp_iterate_q = mp_iterate; + +// mp_pairwise_fold +namespace detail +{ + +template using mp_pairwise_fold_impl = mp_transform_q, mp_pop_front>; + +} // namespace detail + +template using mp_pairwise_fold_q = mp_eval_if, mp_clear, detail::mp_pairwise_fold_impl, L, Q>; +template class F> using mp_pairwise_fold = mp_pairwise_fold_q>; + +// mp_intersperse +namespace detail +{ + +template struct mp_intersperse_impl +{ +}; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) + +template class L, class... T, class S> struct mp_intersperse_impl, S> +{ + static_assert( sizeof...(T) == 0, "T... must be empty" ); + using type = L<>; +}; + +#else + +template class L, class S> struct mp_intersperse_impl, S> +{ + using type = L<>; +}; + +#endif + +template class L, class T1, class... T, class S> struct mp_intersperse_impl, S> +{ + using type = mp_append, L...>; +}; + +} // namespace detail + +template using mp_intersperse = typename detail::mp_intersperse_impl::type; + +// mp_split +namespace detail +{ + +template struct mp_split_impl; + +} // namespace detail + +template using mp_split = typename detail::mp_split_impl>::type; + +namespace detail +{ + +template using mp_split_impl_ = mp_push_front, S>, mp_take>; + +template struct mp_split_impl +{ + using type = mp_eval_if_c::value == J::value, mp_push_back, L>, mp_split_impl_, L, S, J>; +}; + +} // namespace detail + +// mp_join + +template using mp_join = mp_apply>>; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED diff --git a/boost/mp11/bind.hpp b/boost/mp11/bind.hpp new file mode 100644 index 00000000..bbdecd22 --- /dev/null +++ b/boost/mp11/bind.hpp @@ -0,0 +1,111 @@ +#ifndef BOOST_MP11_BIND_HPP_INCLUDED +#define BOOST_MP11_BIND_HPP_INCLUDED + +// Copyright 2017, 2018 Peter Dimov. +// +// 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 + +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_bind_front +template class F, class... T> struct mp_bind_front +{ + // the indirection through mp_defer works around the language inability + // to expand U... into a fixed parameter list of an alias template + + template using fn = typename mp_defer::type; +}; + +template using mp_bind_front_q = mp_bind_front; + +// mp_bind_back +template class F, class... T> struct mp_bind_back +{ + template using fn = typename mp_defer::type; +}; + +template using mp_bind_back_q = mp_bind_back; + +// mp_arg +template struct mp_arg +{ + template using fn = mp_at_c, I>; +}; + +using _1 = mp_arg<0>; +using _2 = mp_arg<1>; +using _3 = mp_arg<2>; +using _4 = mp_arg<3>; +using _5 = mp_arg<4>; +using _6 = mp_arg<5>; +using _7 = mp_arg<6>; +using _8 = mp_arg<7>; +using _9 = mp_arg<8>; + +// mp_bind +template class F, class... T> struct mp_bind; + +namespace detail +{ + +template struct eval_bound_arg +{ + using type = V; +}; + +template struct eval_bound_arg, T...> +{ + using type = typename mp_arg::template fn; +}; + +template class F, class... U, class... T> struct eval_bound_arg, T...> +{ + using type = typename mp_bind::template fn; +}; + +template class F, class... U, class... T> struct eval_bound_arg, T...> +{ + using type = typename mp_bind_front::template fn; +}; + +template class F, class... U, class... T> struct eval_bound_arg, T...> +{ + using type = typename mp_bind_back::template fn; +}; + +} // namespace detail + +template class F, class... T> struct mp_bind +{ +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, == 1915 ) +private: + + template struct _f { using type = F::type...>; }; + +public: + + template using fn = typename _f::type; + +#else + + template using fn = F::type...>; + +#endif +}; + +template using mp_bind_q = mp_bind; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_BIND_HPP_INCLUDED diff --git a/boost/mp11/detail/config.hpp b/boost/mp11/detail/config.hpp new file mode 100644 index 00000000..44686c73 --- /dev/null +++ b/boost/mp11/detail/config.hpp @@ -0,0 +1,149 @@ +#ifndef BOOST_MP11_DETAIL_CONFIG_HPP_INCLUDED +#define BOOST_MP11_DETAIL_CONFIG_HPP_INCLUDED + +// Copyright 2016, 2018, 2019 Peter Dimov. +// +// 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 + +// BOOST_MP11_WORKAROUND + +#if defined( BOOST_STRICT_CONFIG ) || defined( BOOST_MP11_NO_WORKAROUNDS ) + +# define BOOST_MP11_WORKAROUND( symbol, test ) 0 + +#else + +# define BOOST_MP11_WORKAROUND( symbol, test ) ((symbol) != 0 && ((symbol) test)) + +#endif + +// + +#define BOOST_MP11_CUDA 0 +#define BOOST_MP11_CLANG 0 +#define BOOST_MP11_INTEL 0 +#define BOOST_MP11_GCC 0 +#define BOOST_MP11_MSVC 0 + +#define BOOST_MP11_CONSTEXPR constexpr + +#if defined( __CUDACC__ ) + +// nvcc + +# undef BOOST_MP11_CUDA +# define BOOST_MP11_CUDA (__CUDACC_VER_MAJOR__ * 1000000 + __CUDACC_VER_MINOR__ * 10000 + __CUDACC_VER_BUILD__) + +// CUDA (8.0) has no constexpr support in msvc mode: +# if defined(_MSC_VER) && (BOOST_MP11_CUDA < 9000000) + +# define BOOST_MP11_NO_CONSTEXPR + +# undef BOOST_MP11_CONSTEXPR +# define BOOST_MP11_CONSTEXPR + +# endif + +#endif + +#if defined(__clang__) + +// Clang + +# undef BOOST_MP11_CLANG +# define BOOST_MP11_CLANG (__clang_major__ * 100 + __clang_minor__) + +# if defined(__has_cpp_attribute) +# if __has_cpp_attribute(fallthrough) && __cplusplus >= 201406L // Clang 3.9+ in c++1z mode +# define BOOST_MP11_HAS_FOLD_EXPRESSIONS +# endif +# endif + +#if BOOST_MP11_CLANG < 400 && __cplusplus >= 201402L \ + && defined( __GLIBCXX__ ) && !__has_include() + +// Clang pre-4 in C++14 mode, libstdc++ pre-4.9, ::gets is not defined, +// but Clang tries to import it into std + + extern "C" char *gets (char *__s); +#endif + +#elif defined(__INTEL_COMPILER) + +// Intel C++ + +# undef BOOST_MP11_INTEL +# define BOOST_MP11_INTEL __INTEL_COMPILER + +#elif defined(__GNUC__) + +// g++ + +# undef BOOST_MP11_GCC +# define BOOST_MP11_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) + +#elif defined(_MSC_VER) + +// MS Visual C++ + +# undef BOOST_MP11_MSVC +# define BOOST_MP11_MSVC _MSC_VER + +# if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) +# define BOOST_MP11_NO_CONSTEXPR +# endif + +#if _MSC_FULL_VER < 190024210 // 2015u3 +# undef BOOST_MP11_CONSTEXPR +# define BOOST_MP11_CONSTEXPR +#endif + +#endif + +// BOOST_MP11_HAS_CXX14_CONSTEXPR + +#if !defined(BOOST_MP11_NO_CONSTEXPR) && defined(__cpp_constexpr) && __cpp_constexpr >= 201304 +# define BOOST_MP11_HAS_CXX14_CONSTEXPR +#endif + +// BOOST_MP11_HAS_FOLD_EXPRESSIONS + +#if !defined(BOOST_MP11_HAS_FOLD_EXPRESSIONS) && defined(__cpp_fold_expressions) && __cpp_fold_expressions >= 201603 +# define BOOST_MP11_HAS_FOLD_EXPRESSIONS +#endif + +// BOOST_MP11_HAS_TYPE_PACK_ELEMENT + +#if defined(__has_builtin) +# if __has_builtin(__type_pack_element) +# define BOOST_MP11_HAS_TYPE_PACK_ELEMENT +# endif +#endif + +// BOOST_MP11_HAS_TEMPLATE_AUTO + +#if defined(__cpp_nontype_template_parameter_auto) && __cpp_nontype_template_parameter_auto >= 201606L +# define BOOST_MP11_HAS_TEMPLATE_AUTO +#endif + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) +// mp_value<0> is bool, mp_value<-1L> is int, etc +# undef BOOST_MP11_HAS_TEMPLATE_AUTO +#endif + +// BOOST_MP11_DEPRECATED(msg) + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_CLANG, < 304 ) +# define BOOST_MP11_DEPRECATED(msg) +#elif defined(__GNUC__) || defined(__clang__) +# define BOOST_MP11_DEPRECATED(msg) __attribute__((deprecated(msg))) +#elif defined(_MSC_VER) && _MSC_VER >= 1900 +# define BOOST_MP11_DEPRECATED(msg) [[deprecated(msg)]] +#else +# define BOOST_MP11_DEPRECATED(msg) +#endif + +#endif // #ifndef BOOST_MP11_DETAIL_CONFIG_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_append.hpp b/boost/mp11/detail/mp_append.hpp new file mode 100644 index 00000000..858ee24e --- /dev/null +++ b/boost/mp11/detail/mp_append.hpp @@ -0,0 +1,321 @@ +#ifndef BOOST_MP11_DETAIL_MP_APPEND_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_APPEND_HPP_INCLUDED + +// Copyright 2015-2017 Peter Dimov. +// +// 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 + +#include +#include +#include +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_append + +namespace detail +{ + +// append_type_lists + +template struct mp_append_impl; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) + +template struct mp_append_impl +{ +}; + +template<> struct mp_append_impl<> +{ + using type = mp_list<>; +}; + +template class L, class... T> struct mp_append_impl> +{ + using type = L; +}; + +template class L1, class... T1, template class L2, class... T2> struct mp_append_impl, L2> +{ + using type = L1; +}; + +template class L1, class... T1, template class L2, class... T2, template class L3, class... T3> struct mp_append_impl, L2, L3> +{ + using type = L1; +}; + +template class L1, class... T1, template class L2, class... T2, template class L3, class... T3, template class L4, class... T4> struct mp_append_impl, L2, L3, L4> +{ + using type = L1; +}; + +template class L1, class... T1, template class L2, class... T2, template class L3, class... T3, template class L4, class... T4, template class L5, class... T5, class... Lr> struct mp_append_impl, L2, L3, L4, L5, Lr...> +{ + using type = typename mp_append_impl, Lr...>::type; +}; + +#else + +template, class L2 = mp_list<>, class L3 = mp_list<>, class L4 = mp_list<>, class L5 = mp_list<>, class L6 = mp_list<>, class L7 = mp_list<>, class L8 = mp_list<>, class L9 = mp_list<>, class L10 = mp_list<>, class L11 = mp_list<>> struct append_11_impl +{ +}; + +template< + template class L1, class... T1, + template class L2, class... T2, + template class L3, class... T3, + template class L4, class... T4, + template class L5, class... T5, + template class L6, class... T6, + template class L7, class... T7, + template class L8, class... T8, + template class L9, class... T9, + template class L10, class... T10, + template class L11, class... T11> + +struct append_11_impl, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11> +{ + using type = L1; +}; + +template< + + class L00 = mp_list<>, class L01 = mp_list<>, class L02 = mp_list<>, class L03 = mp_list<>, class L04 = mp_list<>, class L05 = mp_list<>, class L06 = mp_list<>, class L07 = mp_list<>, class L08 = mp_list<>, class L09 = mp_list<>, class L0A = mp_list<>, + class L10 = mp_list<>, class L11 = mp_list<>, class L12 = mp_list<>, class L13 = mp_list<>, class L14 = mp_list<>, class L15 = mp_list<>, class L16 = mp_list<>, class L17 = mp_list<>, class L18 = mp_list<>, class L19 = mp_list<>, + class L20 = mp_list<>, class L21 = mp_list<>, class L22 = mp_list<>, class L23 = mp_list<>, class L24 = mp_list<>, class L25 = mp_list<>, class L26 = mp_list<>, class L27 = mp_list<>, class L28 = mp_list<>, class L29 = mp_list<>, + class L30 = mp_list<>, class L31 = mp_list<>, class L32 = mp_list<>, class L33 = mp_list<>, class L34 = mp_list<>, class L35 = mp_list<>, class L36 = mp_list<>, class L37 = mp_list<>, class L38 = mp_list<>, class L39 = mp_list<>, + class L40 = mp_list<>, class L41 = mp_list<>, class L42 = mp_list<>, class L43 = mp_list<>, class L44 = mp_list<>, class L45 = mp_list<>, class L46 = mp_list<>, class L47 = mp_list<>, class L48 = mp_list<>, class L49 = mp_list<>, + class L50 = mp_list<>, class L51 = mp_list<>, class L52 = mp_list<>, class L53 = mp_list<>, class L54 = mp_list<>, class L55 = mp_list<>, class L56 = mp_list<>, class L57 = mp_list<>, class L58 = mp_list<>, class L59 = mp_list<>, + class L60 = mp_list<>, class L61 = mp_list<>, class L62 = mp_list<>, class L63 = mp_list<>, class L64 = mp_list<>, class L65 = mp_list<>, class L66 = mp_list<>, class L67 = mp_list<>, class L68 = mp_list<>, class L69 = mp_list<>, + class L70 = mp_list<>, class L71 = mp_list<>, class L72 = mp_list<>, class L73 = mp_list<>, class L74 = mp_list<>, class L75 = mp_list<>, class L76 = mp_list<>, class L77 = mp_list<>, class L78 = mp_list<>, class L79 = mp_list<>, + class L80 = mp_list<>, class L81 = mp_list<>, class L82 = mp_list<>, class L83 = mp_list<>, class L84 = mp_list<>, class L85 = mp_list<>, class L86 = mp_list<>, class L87 = mp_list<>, class L88 = mp_list<>, class L89 = mp_list<>, + class L90 = mp_list<>, class L91 = mp_list<>, class L92 = mp_list<>, class L93 = mp_list<>, class L94 = mp_list<>, class L95 = mp_list<>, class L96 = mp_list<>, class L97 = mp_list<>, class L98 = mp_list<>, class L99 = mp_list<>, + class LA0 = mp_list<>, class LA1 = mp_list<>, class LA2 = mp_list<>, class LA3 = mp_list<>, class LA4 = mp_list<>, class LA5 = mp_list<>, class LA6 = mp_list<>, class LA7 = mp_list<>, class LA8 = mp_list<>, class LA9 = mp_list<> + +> struct append_111_impl +{ + using type = typename append_11_impl< + + typename append_11_impl::type, + typename append_11_impl, L10, L11, L12, L13, L14, L15, L16, L17, L18, L19>::type, + typename append_11_impl, L20, L21, L22, L23, L24, L25, L26, L27, L28, L29>::type, + typename append_11_impl, L30, L31, L32, L33, L34, L35, L36, L37, L38, L39>::type, + typename append_11_impl, L40, L41, L42, L43, L44, L45, L46, L47, L48, L49>::type, + typename append_11_impl, L50, L51, L52, L53, L54, L55, L56, L57, L58, L59>::type, + typename append_11_impl, L60, L61, L62, L63, L64, L65, L66, L67, L68, L69>::type, + typename append_11_impl, L70, L71, L72, L73, L74, L75, L76, L77, L78, L79>::type, + typename append_11_impl, L80, L81, L82, L83, L84, L85, L86, L87, L88, L89>::type, + typename append_11_impl, L90, L91, L92, L93, L94, L95, L96, L97, L98, L99>::type, + typename append_11_impl, LA0, LA1, LA2, LA3, LA4, LA5, LA6, LA7, LA8, LA9>::type + + >::type; +}; + +template< + + class L00, class L01, class L02, class L03, class L04, class L05, class L06, class L07, class L08, class L09, class L0A, + class L10, class L11, class L12, class L13, class L14, class L15, class L16, class L17, class L18, class L19, + class L20, class L21, class L22, class L23, class L24, class L25, class L26, class L27, class L28, class L29, + class L30, class L31, class L32, class L33, class L34, class L35, class L36, class L37, class L38, class L39, + class L40, class L41, class L42, class L43, class L44, class L45, class L46, class L47, class L48, class L49, + class L50, class L51, class L52, class L53, class L54, class L55, class L56, class L57, class L58, class L59, + class L60, class L61, class L62, class L63, class L64, class L65, class L66, class L67, class L68, class L69, + class L70, class L71, class L72, class L73, class L74, class L75, class L76, class L77, class L78, class L79, + class L80, class L81, class L82, class L83, class L84, class L85, class L86, class L87, class L88, class L89, + class L90, class L91, class L92, class L93, class L94, class L95, class L96, class L97, class L98, class L99, + class LA0, class LA1, class LA2, class LA3, class LA4, class LA5, class LA6, class LA7, class LA8, class LA9, + class... Lr + +> struct append_inf_impl +{ + using prefix = typename append_111_impl< + + L00, L01, L02, L03, L04, L05, L06, L07, L08, L09, L0A, + L10, L11, L12, L13, L14, L15, L16, L17, L18, L19, + L20, L21, L22, L23, L24, L25, L26, L27, L28, L29, + L30, L31, L32, L33, L34, L35, L36, L37, L38, L39, + L40, L41, L42, L43, L44, L45, L46, L47, L48, L49, + L50, L51, L52, L53, L54, L55, L56, L57, L58, L59, + L60, L61, L62, L63, L64, L65, L66, L67, L68, L69, + L70, L71, L72, L73, L74, L75, L76, L77, L78, L79, + L80, L81, L82, L83, L84, L85, L86, L87, L88, L89, + L90, L91, L92, L93, L94, L95, L96, L97, L98, L99, + LA0, LA1, LA2, LA3, LA4, LA5, LA6, LA7, LA8, LA9 + + >::type; + + using type = typename mp_append_impl::type; +}; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) + +template +struct mp_append_impl_cuda_workaround +{ + using type = mp_if_c<(sizeof...(L) > 111), mp_quote, mp_if_c<(sizeof...(L) > 11), mp_quote, mp_quote > >; +}; + +template struct mp_append_impl: mp_append_impl_cuda_workaround::type::template fn +{ +}; + +#else + +template struct mp_append_impl: + mp_cond< + mp_bool<(sizeof...(L) > 111)>, mp_quote, + mp_bool<(sizeof...(L) > 11)>, mp_quote, + mp_true, mp_quote + >::template fn +{ +}; + +#endif // #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) + +#endif // #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) + +struct append_type_lists +{ + template using fn = typename mp_append_impl::type; +}; + +// append_value_lists + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template struct append_value_impl; + +template, class L2 = mp_list_v<>, class L3 = mp_list_v<>, class L4 = mp_list_v<>, class L5 = mp_list_v<>, class L6 = mp_list_v<>, class L7 = mp_list_v<>, class L8 = mp_list_v<>, class L9 = mp_list_v<>, class L10 = mp_list_v<>, class L11 = mp_list_v<>> struct append_value_11_impl +{ +}; + +template< + template class L1, auto... T1, + template class L2, auto... T2, + template class L3, auto... T3, + template class L4, auto... T4, + template class L5, auto... T5, + template class L6, auto... T6, + template class L7, auto... T7, + template class L8, auto... T8, + template class L9, auto... T9, + template class L10, auto... T10, + template class L11, auto... T11> + +struct append_value_11_impl, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11> +{ + using type = L1; +}; + +template< + + class L00 = mp_list_v<>, class L01 = mp_list_v<>, class L02 = mp_list_v<>, class L03 = mp_list_v<>, class L04 = mp_list_v<>, class L05 = mp_list_v<>, class L06 = mp_list_v<>, class L07 = mp_list_v<>, class L08 = mp_list_v<>, class L09 = mp_list_v<>, class L0A = mp_list_v<>, + class L10 = mp_list_v<>, class L11 = mp_list_v<>, class L12 = mp_list_v<>, class L13 = mp_list_v<>, class L14 = mp_list_v<>, class L15 = mp_list_v<>, class L16 = mp_list_v<>, class L17 = mp_list_v<>, class L18 = mp_list_v<>, class L19 = mp_list_v<>, + class L20 = mp_list_v<>, class L21 = mp_list_v<>, class L22 = mp_list_v<>, class L23 = mp_list_v<>, class L24 = mp_list_v<>, class L25 = mp_list_v<>, class L26 = mp_list_v<>, class L27 = mp_list_v<>, class L28 = mp_list_v<>, class L29 = mp_list_v<>, + class L30 = mp_list_v<>, class L31 = mp_list_v<>, class L32 = mp_list_v<>, class L33 = mp_list_v<>, class L34 = mp_list_v<>, class L35 = mp_list_v<>, class L36 = mp_list_v<>, class L37 = mp_list_v<>, class L38 = mp_list_v<>, class L39 = mp_list_v<>, + class L40 = mp_list_v<>, class L41 = mp_list_v<>, class L42 = mp_list_v<>, class L43 = mp_list_v<>, class L44 = mp_list_v<>, class L45 = mp_list_v<>, class L46 = mp_list_v<>, class L47 = mp_list_v<>, class L48 = mp_list_v<>, class L49 = mp_list_v<>, + class L50 = mp_list_v<>, class L51 = mp_list_v<>, class L52 = mp_list_v<>, class L53 = mp_list_v<>, class L54 = mp_list_v<>, class L55 = mp_list_v<>, class L56 = mp_list_v<>, class L57 = mp_list_v<>, class L58 = mp_list_v<>, class L59 = mp_list_v<>, + class L60 = mp_list_v<>, class L61 = mp_list_v<>, class L62 = mp_list_v<>, class L63 = mp_list_v<>, class L64 = mp_list_v<>, class L65 = mp_list_v<>, class L66 = mp_list_v<>, class L67 = mp_list_v<>, class L68 = mp_list_v<>, class L69 = mp_list_v<>, + class L70 = mp_list_v<>, class L71 = mp_list_v<>, class L72 = mp_list_v<>, class L73 = mp_list_v<>, class L74 = mp_list_v<>, class L75 = mp_list_v<>, class L76 = mp_list_v<>, class L77 = mp_list_v<>, class L78 = mp_list_v<>, class L79 = mp_list_v<>, + class L80 = mp_list_v<>, class L81 = mp_list_v<>, class L82 = mp_list_v<>, class L83 = mp_list_v<>, class L84 = mp_list_v<>, class L85 = mp_list_v<>, class L86 = mp_list_v<>, class L87 = mp_list_v<>, class L88 = mp_list_v<>, class L89 = mp_list_v<>, + class L90 = mp_list_v<>, class L91 = mp_list_v<>, class L92 = mp_list_v<>, class L93 = mp_list_v<>, class L94 = mp_list_v<>, class L95 = mp_list_v<>, class L96 = mp_list_v<>, class L97 = mp_list_v<>, class L98 = mp_list_v<>, class L99 = mp_list_v<>, + class LA0 = mp_list_v<>, class LA1 = mp_list_v<>, class LA2 = mp_list_v<>, class LA3 = mp_list_v<>, class LA4 = mp_list_v<>, class LA5 = mp_list_v<>, class LA6 = mp_list_v<>, class LA7 = mp_list_v<>, class LA8 = mp_list_v<>, class LA9 = mp_list_v<> + +> struct append_value_111_impl +{ + using type = typename append_value_11_impl< + + typename append_value_11_impl::type, + typename append_value_11_impl, L10, L11, L12, L13, L14, L15, L16, L17, L18, L19>::type, + typename append_value_11_impl, L20, L21, L22, L23, L24, L25, L26, L27, L28, L29>::type, + typename append_value_11_impl, L30, L31, L32, L33, L34, L35, L36, L37, L38, L39>::type, + typename append_value_11_impl, L40, L41, L42, L43, L44, L45, L46, L47, L48, L49>::type, + typename append_value_11_impl, L50, L51, L52, L53, L54, L55, L56, L57, L58, L59>::type, + typename append_value_11_impl, L60, L61, L62, L63, L64, L65, L66, L67, L68, L69>::type, + typename append_value_11_impl, L70, L71, L72, L73, L74, L75, L76, L77, L78, L79>::type, + typename append_value_11_impl, L80, L81, L82, L83, L84, L85, L86, L87, L88, L89>::type, + typename append_value_11_impl, L90, L91, L92, L93, L94, L95, L96, L97, L98, L99>::type, + typename append_value_11_impl, LA0, LA1, LA2, LA3, LA4, LA5, LA6, LA7, LA8, LA9>::type + + >::type; +}; + +template< + + class L00, class L01, class L02, class L03, class L04, class L05, class L06, class L07, class L08, class L09, class L0A, + class L10, class L11, class L12, class L13, class L14, class L15, class L16, class L17, class L18, class L19, + class L20, class L21, class L22, class L23, class L24, class L25, class L26, class L27, class L28, class L29, + class L30, class L31, class L32, class L33, class L34, class L35, class L36, class L37, class L38, class L39, + class L40, class L41, class L42, class L43, class L44, class L45, class L46, class L47, class L48, class L49, + class L50, class L51, class L52, class L53, class L54, class L55, class L56, class L57, class L58, class L59, + class L60, class L61, class L62, class L63, class L64, class L65, class L66, class L67, class L68, class L69, + class L70, class L71, class L72, class L73, class L74, class L75, class L76, class L77, class L78, class L79, + class L80, class L81, class L82, class L83, class L84, class L85, class L86, class L87, class L88, class L89, + class L90, class L91, class L92, class L93, class L94, class L95, class L96, class L97, class L98, class L99, + class LA0, class LA1, class LA2, class LA3, class LA4, class LA5, class LA6, class LA7, class LA8, class LA9, + class... Lr + +> struct append_value_inf_impl +{ + using prefix = typename append_value_111_impl< + + L00, L01, L02, L03, L04, L05, L06, L07, L08, L09, L0A, + L10, L11, L12, L13, L14, L15, L16, L17, L18, L19, + L20, L21, L22, L23, L24, L25, L26, L27, L28, L29, + L30, L31, L32, L33, L34, L35, L36, L37, L38, L39, + L40, L41, L42, L43, L44, L45, L46, L47, L48, L49, + L50, L51, L52, L53, L54, L55, L56, L57, L58, L59, + L60, L61, L62, L63, L64, L65, L66, L67, L68, L69, + L70, L71, L72, L73, L74, L75, L76, L77, L78, L79, + L80, L81, L82, L83, L84, L85, L86, L87, L88, L89, + L90, L91, L92, L93, L94, L95, L96, L97, L98, L99, + LA0, LA1, LA2, LA3, LA4, LA5, LA6, LA7, LA8, LA9 + + >::type; + + using type = typename append_value_impl::type; +}; + +template struct append_value_impl: + mp_cond< + mp_bool<(sizeof...(L) > 111)>, mp_quote, + mp_bool<(sizeof...(L) > 11)>, mp_quote, + mp_true, mp_quote + >::template fn +{ +}; + +struct append_value_lists +{ + template using fn = typename append_value_impl::type; +}; + +#endif // #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +} // namespace detail + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template using mp_append = typename mp_if_c<(sizeof...(L) > 0 && sizeof...(L) == mp_count_if, mp_is_value_list>::value), detail::append_value_lists, detail::append_type_lists>::template fn; + +#else + +template using mp_append = detail::append_type_lists::fn; + +#endif + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_APPEND_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_copy_if.hpp b/boost/mp11/detail/mp_copy_if.hpp new file mode 100644 index 00000000..4edcde09 --- /dev/null +++ b/boost/mp11/detail/mp_copy_if.hpp @@ -0,0 +1,48 @@ +#ifndef BOOST_MP11_DETAIL_MP_COPY_IF_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_COPY_IF_HPP_INCLUDED + +// Copyright 2015-2019 Peter Dimov. +// +// 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 + +#include +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_copy_if +namespace detail +{ + +template class P> struct mp_copy_if_impl +{ +}; + +template class L, class... T, template class P> struct mp_copy_if_impl, P> +{ +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) + template struct _f { using type = mp_if, mp_list, mp_list<>>; }; + using type = mp_append, typename _f::type...>; +#else + template using _f = mp_if, mp_list, mp_list<>>; + using type = mp_append, _f...>; +#endif +}; + +} // namespace detail + +template class P> using mp_copy_if = typename detail::mp_copy_if_impl::type; +template using mp_copy_if_q = mp_copy_if; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_COPY_IF_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_count.hpp b/boost/mp11/detail/mp_count.hpp new file mode 100644 index 00000000..37b39ed5 --- /dev/null +++ b/boost/mp11/detail/mp_count.hpp @@ -0,0 +1,147 @@ +#ifndef BOOST_MP11_DETAIL_MP_COUNT_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_COUNT_HPP_INCLUDED + +// Copyright 2015, 2016 Peter Dimov. +// +// 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 + +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_count +namespace detail +{ + +#if !defined( BOOST_MP11_NO_CONSTEXPR ) + +constexpr std::size_t cx_plus() +{ + return 0; +} + +template constexpr std::size_t cx_plus(T1 t1, T... t) +{ + return static_cast(t1) + cx_plus(t...); +} + +template +constexpr std::size_t cx_plus(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T... t) +{ + return static_cast(t1 + t2 + t3 + t4 + t5 + t6 + t7 + t8 + t9 + t10) + cx_plus(t...); +} + +#endif + +template struct mp_count_impl; + +#if defined( BOOST_MP11_HAS_CXX14_CONSTEXPR ) + +template constexpr std::size_t cx_count() +{ + constexpr bool a[] = { false, std::is_same::value... }; + + std::size_t r = 0; + + for( std::size_t i = 1; i < sizeof...(T) + 1; ++i ) + { + r += a[ i ]; + } + + return r; +} + +template class L, class... T, class V> struct mp_count_impl, V> +{ + using type = mp_size_t()>; +}; + +#elif !defined( BOOST_MP11_NO_CONSTEXPR ) + +template class L, class... T, class V> struct mp_count_impl, V> +{ + using type = mp_size_t::value...)>; +}; + +#else + +template class L, class... T, class V> struct mp_count_impl, V> +{ + using type = mp_size_t...>::value>; +}; + +#endif + +} // namespace detail + +template using mp_count = typename detail::mp_count_impl::type; + +// mp_count_if +namespace detail +{ + +template class P> struct mp_count_if_impl; + +#if defined( BOOST_MP11_HAS_CXX14_CONSTEXPR ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1930 ) + +template class P, class... T> constexpr std::size_t cx_count_if() +{ + constexpr bool a[] = { false, static_cast( P::value )... }; + + std::size_t r = 0; + + for( std::size_t i = 1; i < sizeof...(T) + 1; ++i ) + { + r += a[ i ]; + } + + return r; +} + +template class L, class... T, template class P> struct mp_count_if_impl, P> +{ + using type = mp_size_t()>; +}; + +#elif !defined( BOOST_MP11_NO_CONSTEXPR ) + +template class L, class... T, template class P> struct mp_count_if_impl, P> +{ + using type = mp_size_t>::value...)>; +}; + +#else + +template class L, class... T, template class P> struct mp_count_if_impl, P> +{ +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) + + template struct _f { using type = mp_to_bool>; }; + using type = mp_size_t::type...>::value>; + +#else + + using type = mp_size_t>...>::value>; + +#endif +}; + +#endif + +} // namespace detail + +template class P> using mp_count_if = typename detail::mp_count_if_impl::type; +template using mp_count_if_q = mp_count_if; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_COUNT_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_defer.hpp b/boost/mp11/detail/mp_defer.hpp new file mode 100644 index 00000000..9aaca99e --- /dev/null +++ b/boost/mp11/detail/mp_defer.hpp @@ -0,0 +1,119 @@ +#ifndef BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED + +// Copyright 2015-2020, 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_if, mp_if_c +namespace detail +{ + +template struct mp_if_c_impl +{ +}; + +template struct mp_if_c_impl +{ + using type = T; +}; + +template struct mp_if_c_impl +{ + using type = E; +}; + +} // namespace detail + +template using mp_if_c = typename detail::mp_if_c_impl::type; +template using mp_if = typename detail::mp_if_c_impl(C::value), T, E...>::type; + +// mp_valid + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_INTEL, != 0 ) // tested at 1800 + +// contributed by Roland Schulz in https://github.com/boostorg/mp11/issues/17 + +namespace detail +{ + +template using void_t = void; + +template class F, class... T> +struct mp_valid_impl: mp_false {}; + +template class F, class... T> +struct mp_valid_impl>, F, T...>: mp_true {}; + +} // namespace detail + +template class F, class... T> using mp_valid = typename detail::mp_valid_impl; + +#else + +// implementation by Bruno Dutra (by the name is_evaluable) +namespace detail +{ + +template class F, class... T> struct mp_valid_impl +{ + template class G, class = G> static mp_true check(int); + template class> static mp_false check(...); + + using type = decltype(check(0)); +}; + +} // namespace detail + +template class F, class... T> using mp_valid = typename detail::mp_valid_impl::type; + +#endif + +template using mp_valid_q = mp_valid; + +// mp_defer +namespace detail +{ + +template class F, class... T> struct mp_defer_impl +{ + using type = F; +}; + +struct mp_no_type +{ +}; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) + +template class F, class... T> struct mp_defer_cuda_workaround +{ + using type = mp_if, detail::mp_defer_impl, detail::mp_no_type>; +}; + +#endif + +} // namespace detail + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) + +template class F, class... T> using mp_defer = typename detail::mp_defer_cuda_workaround< F, T...>::type; + +#else + +template class F, class... T> using mp_defer = mp_if, detail::mp_defer_impl, detail::mp_no_type>; + +#endif + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_fold.hpp b/boost/mp11/detail/mp_fold.hpp new file mode 100644 index 00000000..266d9c18 --- /dev/null +++ b/boost/mp11/detail/mp_fold.hpp @@ -0,0 +1,164 @@ +#ifndef BOOST_MP11_DETAIL_MP_FOLD_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_FOLD_HPP_INCLUDED + +// Copyright 2015-2017 Peter Dimov. +// +// 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 + +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_fold +namespace detail +{ + +template class F> struct mp_fold_impl +{ +// An error "no type named 'type'" here means that the first argument to mp_fold is not a list +}; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) + +template class L, class... T, class V, template class F> struct mp_fold_impl, V, F> +{ + static_assert( sizeof...(T) == 0, "T... must be empty" ); + using type = V; +}; + +#else + +template class L, class V, template class F> struct mp_fold_impl, V, F> +{ + using type = V; +}; + +#endif + +// + +template class F> struct mp_fold_Q1 +{ + template + using fn = F; +}; + +template class F> struct mp_fold_Q2 +{ + template + using fn = F, T2>; +}; + +template class F> struct mp_fold_Q3 +{ + template + using fn = F, T2>, T3>; +}; + +template class F> struct mp_fold_Q4 +{ + template + using fn = F, T2>, T3>, T4>; +}; + +template class F> struct mp_fold_Q5 +{ + template + using fn = F, T2>, T3>, T4>, T5>; +}; + +template class F> struct mp_fold_Q6 +{ + template + using fn = F, T2>, T3>, T4>, T5>, T6>; +}; + +template class F> struct mp_fold_Q7 +{ + template + using fn = F, T2>, T3>, T4>, T5>, T6>, T7>; +}; + +template class F> struct mp_fold_Q8 +{ + template + using fn = F, T2>, T3>, T4>, T5>, T6>, T7>, T8>; +}; + +template class F> struct mp_fold_Q9 +{ + template + using fn = F, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>; +}; + +// + +template class L, class T1, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1> +{ +}; + +template class L, class T1, class T2, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2> +{ +}; + +template class L, class T1, class T2, class T3, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5, T6> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5, T6, T7> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5, T6, T7, T8> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5, T6, T7, T8, T9> +{ +}; + +// + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T, class V, template class F> +struct mp_fold_impl, V, F> +{ + using type = typename mp_fold_impl, F, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>, T10>, F>::type; +}; + +} // namespace detail + +template class F> using mp_fold = typename detail::mp_fold_impl::type; +template using mp_fold_q = mp_fold; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_FOLD_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_front.hpp b/boost/mp11/detail/mp_front.hpp new file mode 100644 index 00000000..53a73ac3 --- /dev/null +++ b/boost/mp11/detail/mp_front.hpp @@ -0,0 +1,50 @@ +#ifndef BOOST_MP11_DETAIL_MP_FRONT_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_FRONT_HPP_INCLUDED + +// Copyright 2015-2023 Peter Dimov. +// +// 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 + +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_front +namespace detail +{ + +template struct mp_front_impl +{ +// An error "no type named 'type'" here means that the argument to mp_front +// is either not a list, or is an empty list +}; + +template class L, class T1, class... T> struct mp_front_impl> +{ + using type = T1; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto... A> struct mp_front_impl> +{ + using type = mp_value; +}; + +#endif + +} // namespace detail + +template using mp_front = typename detail::mp_front_impl::type; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_FRONT_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_is_list.hpp b/boost/mp11/detail/mp_is_list.hpp new file mode 100644 index 00000000..25b378bd --- /dev/null +++ b/boost/mp11/detail/mp_is_list.hpp @@ -0,0 +1,39 @@ +#ifndef BOOST_MP11_DETAIL_MP_IS_LIST_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_IS_LIST_HPP_INCLUDED + +// Copyright 2015-2019 Peter Dimov. +// +// 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 + +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_is_list +namespace detail +{ + +template struct mp_is_list_impl +{ + using type = mp_false; +}; + +template class L, class... T> struct mp_is_list_impl> +{ + using type = mp_true; +}; + +} // namespace detail + +template using mp_is_list = typename detail::mp_is_list_impl::type; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_IS_LIST_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_is_value_list.hpp b/boost/mp11/detail/mp_is_value_list.hpp new file mode 100644 index 00000000..8f94f030 --- /dev/null +++ b/boost/mp11/detail/mp_is_value_list.hpp @@ -0,0 +1,41 @@ +#ifndef BOOST_MP11_DETAIL_MP_IS_VALUE_LIST_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_IS_VALUE_LIST_HPP_INCLUDED + +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_is_value_list +namespace detail +{ + +template struct mp_is_value_list_impl +{ + using type = mp_false; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto... A> struct mp_is_value_list_impl> +{ + using type = mp_true; +}; + +#endif + +} // namespace detail + +template using mp_is_value_list = typename detail::mp_is_value_list_impl::type; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_IS_VALUE_LIST_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_list.hpp b/boost/mp11/detail/mp_list.hpp new file mode 100644 index 00000000..8e8d3e5e --- /dev/null +++ b/boost/mp11/detail/mp_list.hpp @@ -0,0 +1,24 @@ +#ifndef BOOST_MP11_DETAIL_MP_LIST_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_LIST_HPP_INCLUDED + +// Copyright 2015, 2016 Peter Dimov. +// +// 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 + +namespace boost +{ +namespace mp11 +{ + +// mp_list +template struct mp_list +{ +}; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_LIST_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_list_v.hpp b/boost/mp11/detail/mp_list_v.hpp new file mode 100644 index 00000000..bc05238a --- /dev/null +++ b/boost/mp11/detail/mp_list_v.hpp @@ -0,0 +1,27 @@ +#ifndef BOOST_MP11_DETAIL_MP_LIST_V_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_LIST_V_HPP_INCLUDED + +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// http://www.boost.org/LICENSE_1_0.txt + +#include + +namespace boost +{ +namespace mp11 +{ + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +// mp_list_v +template struct mp_list_v +{ +}; + +#endif + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_LIST_V_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_map_find.hpp b/boost/mp11/detail/mp_map_find.hpp new file mode 100644 index 00000000..2fb70d8e --- /dev/null +++ b/boost/mp11/detail/mp_map_find.hpp @@ -0,0 +1,87 @@ +#ifndef BOOST_MP11_DETAIL_MP_MAP_FIND_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_MAP_FIND_HPP_INCLUDED + +// Copyright 2015 Peter Dimov. +// +// 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 + +#include +#include + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1930 ) + +// not exactly good practice, but... +namespace std +{ + template class tuple; +} + +#endif + +namespace boost +{ +namespace mp11 +{ + +// mp_map_find +namespace detail +{ + +#if !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1930 ) + +template using mpmf_wrap = mp_identity; +template using mpmf_unwrap = typename T::type; + +#else + +template struct mpmf_tuple {}; + +template struct mpmf_wrap_impl +{ + using type = mp_identity; +}; + +template struct mpmf_wrap_impl< std::tuple > +{ + using type = mp_identity< mpmf_tuple >; +}; + +template using mpmf_wrap = typename mpmf_wrap_impl::type; + +template struct mpmf_unwrap_impl +{ + using type = typename T::type; +}; + +template struct mpmf_unwrap_impl< mp_identity< mpmf_tuple > > +{ + using type = std::tuple; +}; + +template using mpmf_unwrap = typename mpmf_unwrap_impl::type; + +#endif // #if !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1930 ) + +template struct mp_map_find_impl; + +template class M, class... T, class K> struct mp_map_find_impl, K> +{ + using U = mp_inherit...>; + + template class L, class... U> static mp_identity> f( mp_identity>* ); + static mp_identity f( ... ); + + using type = mpmf_unwrap< decltype( f( static_cast(0) ) ) >; +}; + +} // namespace detail + +template using mp_map_find = typename detail::mp_map_find_impl::type; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_MAP_FIND_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_min_element.hpp b/boost/mp11/detail/mp_min_element.hpp new file mode 100644 index 00000000..55c21acd --- /dev/null +++ b/boost/mp11/detail/mp_min_element.hpp @@ -0,0 +1,51 @@ +#ifndef BOOST_MP11_DETAIL_MP_MIN_ELEMENT_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_MIN_ELEMENT_HPP_INCLUDED + +// Copyright 2015-2017 Peter Dimov. +// +// 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 + +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_min_element +namespace detail +{ + +template class P> struct select_min +{ + template using fn = mp_if, T1, T2>; +}; + +} // namespace detail + +template class P> using mp_min_element = mp_fold_q, mp_first, detail::select_min

>; +template using mp_min_element_q = mp_min_element; + +// mp_max_element +namespace detail +{ + +template class P> struct select_max +{ + template using fn = mp_if, T1, T2>; +}; + +} // namespace detail + +template class P> using mp_max_element = mp_fold_q, mp_first, detail::select_max

>; +template using mp_max_element_q = mp_max_element; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_MIN_ELEMENT_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_plus.hpp b/boost/mp11/detail/mp_plus.hpp new file mode 100644 index 00000000..5c9417cd --- /dev/null +++ b/boost/mp11/detail/mp_plus.hpp @@ -0,0 +1,84 @@ +#ifndef BOOST_MP11_DETAIL_MP_PLUS_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_PLUS_HPP_INCLUDED + +// Copyright 2015 Peter Dimov. +// +// 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 + +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_plus +namespace detail +{ + +#if defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, != 0 ) && !BOOST_MP11_WORKAROUND( BOOST_MP11_CLANG, != 0 ) + +// msvc fails with parser stack overflow for large sizeof...(T) +// clang exceeds -fbracket-depth, which defaults to 256 + +template struct mp_plus_impl +{ + static const auto _v = (T::value + ... + 0); + using type = std::integral_constant::type, _v>; +}; + +#else + +template struct mp_plus_impl; + +template<> struct mp_plus_impl<> +{ + using type = std::integral_constant; +}; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 40800 ) + +template struct mp_plus_impl +{ + static const decltype(T1::value + mp_plus_impl::type::value) _v = T1::value + mp_plus_impl::type::value; + using type = std::integral_constant::type, _v>; +}; + +template struct mp_plus_impl +{ + static const + decltype(T1::value + T2::value + T3::value + T4::value + T5::value + T6::value + T7::value + T8::value + T9::value + T10::value + mp_plus_impl::type::value) + _v = T1::value + T2::value + T3::value + T4::value + T5::value + T6::value + T7::value + T8::value + T9::value + T10::value + mp_plus_impl::type::value; + using type = std::integral_constant::type, _v>; +}; + +#else + +template struct mp_plus_impl +{ + static const auto _v = T1::value + mp_plus_impl::type::value; + using type = std::integral_constant::type, _v>; +}; + +template struct mp_plus_impl +{ + static const auto _v = T1::value + T2::value + T3::value + T4::value + T5::value + T6::value + T7::value + T8::value + T9::value + T10::value + mp_plus_impl::type::value; + using type = std::integral_constant::type, _v>; +}; + +#endif + +#endif + +} // namespace detail + +template using mp_plus = typename detail::mp_plus_impl::type; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_PLUS_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_remove_if.hpp b/boost/mp11/detail/mp_remove_if.hpp new file mode 100644 index 00000000..9687b4a1 --- /dev/null +++ b/boost/mp11/detail/mp_remove_if.hpp @@ -0,0 +1,48 @@ +#ifndef BOOST_MP11_DETAIL_MP_REMOVE_IF_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_REMOVE_IF_HPP_INCLUDED + +// Copyright 2015-2019 Peter Dimov. +// +// 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 + +#include +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_remove_if +namespace detail +{ + +template class P> struct mp_remove_if_impl +{ +}; + +template class L, class... T, template class P> struct mp_remove_if_impl, P> +{ +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) + template struct _f { using type = mp_if, mp_list<>, mp_list>; }; + using type = mp_append, typename _f::type...>; +#else + template using _f = mp_if, mp_list<>, mp_list>; + using type = mp_append, _f...>; +#endif +}; + +} // namespace detail + +template class P> using mp_remove_if = typename detail::mp_remove_if_impl::type; +template using mp_remove_if_q = mp_remove_if; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_REMOVE_IF_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_rename.hpp b/boost/mp11/detail/mp_rename.hpp new file mode 100644 index 00000000..dde8f6f4 --- /dev/null +++ b/boost/mp11/detail/mp_rename.hpp @@ -0,0 +1,54 @@ +#ifndef BOOST_MP11_DETAIL_MP_RENAME_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_RENAME_HPP_INCLUDED + +// Copyright 2015-2023 Peter Dimov. +// +// 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 + +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_rename +namespace detail +{ + +template class B> struct mp_rename_impl +{ +// An error "no type named 'type'" here means that the first argument to mp_rename is not a list +}; + +template class L, class... T, template class B> struct mp_rename_impl, B>: mp_defer +{ +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto... A, template class B> struct mp_rename_impl, B>: mp_defer...> +{ +}; + +#endif + +} // namespace detail + +template class B> using mp_rename = typename detail::mp_rename_impl::type; + +// mp_apply +template class F, class L> using mp_apply = typename detail::mp_rename_impl::type; + +// mp_apply_q +template using mp_apply_q = typename detail::mp_rename_impl::type; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_RENAME_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_value.hpp b/boost/mp11/detail/mp_value.hpp new file mode 100644 index 00000000..d0e59825 --- /dev/null +++ b/boost/mp11/detail/mp_value.hpp @@ -0,0 +1,25 @@ +#ifndef BOOST_MP11_DETAIL_MP_VALUE_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_VALUE_HPP_INCLUDED + +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +namespace boost +{ +namespace mp11 +{ + +template using mp_value = std::integral_constant; + +} // namespace mp11 +} // namespace boost + +#endif // #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +#endif // #ifndef BOOST_MP11_DETAIL_MP_VALUE_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_void.hpp b/boost/mp11/detail/mp_void.hpp new file mode 100644 index 00000000..a7ac7b71 --- /dev/null +++ b/boost/mp11/detail/mp_void.hpp @@ -0,0 +1,32 @@ +#ifndef BOOST_MP11_DETAIL_MP_VOID_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_VOID_HPP_INCLUDED + +// Copyright 2015-2017 Peter Dimov. +// +// 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 + +namespace boost +{ +namespace mp11 +{ + +// mp_void +namespace detail +{ + +template struct mp_void_impl +{ + using type = void; +}; + +} // namespace detail + +template using mp_void = typename detail::mp_void_impl::type; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_VOID_HPP_INCLUDED diff --git a/boost/mp11/detail/mp_with_index.hpp b/boost/mp11/detail/mp_with_index.hpp new file mode 100644 index 00000000..b6932f2d --- /dev/null +++ b/boost/mp11/detail/mp_with_index.hpp @@ -0,0 +1,385 @@ +#ifndef BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED + +// Copyright 2017 Peter Dimov. +// +// 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 + +#include +#include +#include +#include +#include + +#if defined( BOOST_MP11_HAS_CXX14_CONSTEXPR ) +# define BOOST_MP11_CONSTEXPR14 constexpr +#else +# define BOOST_MP11_CONSTEXPR14 +#endif + +#if defined( __GNUC__ ) || defined( __clang__ ) +# define BOOST_MP11_UNREACHABLE_DEFAULT default: __builtin_unreachable(); +#elif defined( _MSC_VER ) +# define BOOST_MP11_UNREACHABLE_DEFAULT default: __assume(false); +#else +# define BOOST_MP11_UNREACHABLE_DEFAULT +#endif + +namespace boost +{ +namespace mp11 +{ + +namespace detail +{ + +template struct mp_with_index_impl_ +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + if( i < N / 2 ) + { + return mp_with_index_impl_::template call( i, std::forward(f) ); + } + else + { + return mp_with_index_impl_::template call( i - N/2, std::forward(f) ); + } + } +}; + +template<> struct mp_with_index_impl_<0> +{ +}; + +template<> struct mp_with_index_impl_<1> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t /*i*/, F && f ) + { + return std::forward(f)( mp_size_t() ); + } +}; + +template<> struct mp_with_index_impl_<2> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<3> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<4> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<5> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<6> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<7> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<8> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<9> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<10> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<11> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + case 10: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<12> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + case 10: return std::forward(f)( mp_size_t() ); + case 11: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<13> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + case 10: return std::forward(f)( mp_size_t() ); + case 11: return std::forward(f)( mp_size_t() ); + case 12: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<14> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + case 10: return std::forward(f)( mp_size_t() ); + case 11: return std::forward(f)( mp_size_t() ); + case 12: return std::forward(f)( mp_size_t() ); + case 13: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<15> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + case 10: return std::forward(f)( mp_size_t() ); + case 11: return std::forward(f)( mp_size_t() ); + case 12: return std::forward(f)( mp_size_t() ); + case 13: return std::forward(f)( mp_size_t() ); + case 14: return std::forward(f)( mp_size_t() ); + } + } +}; + +template<> struct mp_with_index_impl_<16> +{ + template static BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) call( std::size_t i, F && f ) + { + switch( i ) + { + BOOST_MP11_UNREACHABLE_DEFAULT + case 0: return std::forward(f)( mp_size_t() ); + case 1: return std::forward(f)( mp_size_t() ); + case 2: return std::forward(f)( mp_size_t() ); + case 3: return std::forward(f)( mp_size_t() ); + case 4: return std::forward(f)( mp_size_t() ); + case 5: return std::forward(f)( mp_size_t() ); + case 6: return std::forward(f)( mp_size_t() ); + case 7: return std::forward(f)( mp_size_t() ); + case 8: return std::forward(f)( mp_size_t() ); + case 9: return std::forward(f)( mp_size_t() ); + case 10: return std::forward(f)( mp_size_t() ); + case 11: return std::forward(f)( mp_size_t() ); + case 12: return std::forward(f)( mp_size_t() ); + case 13: return std::forward(f)( mp_size_t() ); + case 14: return std::forward(f)( mp_size_t() ); + case 15: return std::forward(f)( mp_size_t() ); + } + } +}; + +} // namespace detail + +template inline BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) mp_with_index( std::size_t i, F && f ) +{ + assert( i < N ); + return detail::mp_with_index_impl_::template call<0>( i, std::forward(f) ); +} + +template inline BOOST_MP11_CONSTEXPR14 decltype(std::declval()(std::declval>())) mp_with_index( std::size_t i, F && f ) +{ + return mp_with_index( i, std::forward(f) ); +} + +#undef BOOST_MP11_CONSTEXPR14 +#undef BOOST_MP11_UNREACHABLE_DEFAULT + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_WITH_INDEX_HPP_INCLUDED diff --git a/boost/mp11/function.hpp b/boost/mp11/function.hpp new file mode 100644 index 00000000..e20b4520 --- /dev/null +++ b/boost/mp11/function.hpp @@ -0,0 +1,222 @@ +#ifndef BOOST_MP11_FUNCTION_HPP_INCLUDED +#define BOOST_MP11_FUNCTION_HPP_INCLUDED + +// Copyright 2015-2019 Peter Dimov. +// +// 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_void +// in detail/mp_void.hpp + +// mp_and +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1910 ) + +namespace detail +{ + +template struct mp_and_impl; + +} // namespace detail + +template using mp_and = mp_to_bool< typename detail::mp_and_impl::type >; + +namespace detail +{ + +template<> struct mp_and_impl<> +{ + using type = mp_true; +}; + +template struct mp_and_impl +{ + using type = T; +}; + +template struct mp_and_impl +{ + using type = mp_eval_if< mp_not, T1, mp_and, T... >; +}; + +} // namespace detail + +#else + +namespace detail +{ + +template struct mp_and_impl +{ + using type = mp_false; +}; + +template struct mp_and_impl< mp_list, mp_void...> > +{ + using type = mp_true; +}; + +} // namespace detail + +template using mp_and = typename detail::mp_and_impl>::type; + +#endif + +// mp_all +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86355 +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, != 0 ) + +template using mp_all = mp_bool< mp_count_if< mp_list, mp_not >::value == 0 >; + +#else + +template using mp_all = mp_bool< mp_count< mp_list...>, mp_false >::value == 0 >; + +#endif + +// mp_or +namespace detail +{ + +template struct mp_or_impl; + +} // namespace detail + +template using mp_or = mp_to_bool< typename detail::mp_or_impl::type >; + +namespace detail +{ + +template<> struct mp_or_impl<> +{ + using type = mp_false; +}; + +template struct mp_or_impl +{ + using type = T; +}; + +template struct mp_or_impl +{ + using type = mp_eval_if< T1, T1, mp_or, T... >; +}; + +} // namespace detail + +// mp_any +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86356 +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, != 0 ) + +template using mp_any = mp_bool< mp_count_if< mp_list, mp_to_bool >::value != 0 >; + +#else + +template using mp_any = mp_bool< mp_count< mp_list...>, mp_true >::value != 0 >; + +#endif + +// mp_same +namespace detail +{ + +template struct mp_same_impl; + +template<> struct mp_same_impl<> +{ + using type = mp_true; +}; + +template struct mp_same_impl +{ + using type = mp_bool< mp_count, T1>::value == sizeof...(T) >; +}; + +} // namespace detail + +template using mp_same = typename detail::mp_same_impl::type; + +// mp_similar +namespace detail +{ + +template struct mp_similar_impl; + +template<> struct mp_similar_impl<> +{ + using type = mp_true; +}; + +template struct mp_similar_impl +{ + using type = mp_true; +}; + +template struct mp_similar_impl +{ + using type = mp_true; +}; + +template struct mp_similar_impl +{ + using type = mp_false; +}; + +template class L, class... T1, class... T2> struct mp_similar_impl, L> +{ + using type = mp_true; +}; + +template class L, class... T> struct mp_similar_impl, L> +{ + using type = mp_true; +}; + +template struct mp_similar_impl +{ + using type = mp_all< typename mp_similar_impl::type, typename mp_similar_impl::type, typename mp_similar_impl::type... >; +}; + +} // namespace detail + +template using mp_similar = typename detail::mp_similar_impl::type; + +#if BOOST_MP11_GCC +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wsign-compare" +#endif + +// mp_less +template using mp_less = mp_bool<(T1::value < 0 && T2::value >= 0) || ((T1::value < T2::value) && !(T1::value >= 0 && T2::value < 0))>; + +#if BOOST_MP11_GCC +# pragma GCC diagnostic pop +#endif + +// mp_min +template using mp_min = mp_min_element, mp_less>; + +// mp_max +template using mp_max = mp_max_element, mp_less>; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_FUNCTION_HPP_INCLUDED diff --git a/boost/mp11/integer_sequence.hpp b/boost/mp11/integer_sequence.hpp new file mode 100644 index 00000000..83e24501 --- /dev/null +++ b/boost/mp11/integer_sequence.hpp @@ -0,0 +1,112 @@ +#ifndef BOOST_MP11_INTEGER_SEQUENCE_HPP_INCLUDED +#define BOOST_MP11_INTEGER_SEQUENCE_HPP_INCLUDED + +// Copyright 2015, 2017, 2019 Peter Dimov. +// +// 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 + +#include +#include + +#if defined(__has_builtin) +# if __has_builtin(__make_integer_seq) +# define BOOST_MP11_HAS_MAKE_INTEGER_SEQ +# endif +#endif + +namespace boost +{ +namespace mp11 +{ + +// integer_sequence +template struct integer_sequence +{ +}; + +#if defined(BOOST_MP11_HAS_MAKE_INTEGER_SEQ) + +template using make_integer_sequence = __make_integer_seq; + +#else + +// detail::make_integer_sequence_impl +namespace detail +{ + +// iseq_if_c +template struct iseq_if_c_impl; + +template struct iseq_if_c_impl +{ + using type = T; +}; + +template struct iseq_if_c_impl +{ + using type = E; +}; + +template using iseq_if_c = typename iseq_if_c_impl::type; + +// iseq_identity +template struct iseq_identity +{ + using type = T; +}; + +template struct append_integer_sequence; + +template struct append_integer_sequence, integer_sequence> +{ + using type = integer_sequence< T, I..., ( J + sizeof...(I) )... >; +}; + +template struct make_integer_sequence_impl; + +template struct make_integer_sequence_impl_ +{ +private: + + static_assert( N >= 0, "make_integer_sequence: N must not be negative" ); + + static T const M = N / 2; + static T const R = N % 2; + + using S1 = typename make_integer_sequence_impl::type; + using S2 = typename append_integer_sequence::type; + using S3 = typename make_integer_sequence_impl::type; + using S4 = typename append_integer_sequence::type; + +public: + + using type = S4; +}; + +template struct make_integer_sequence_impl: iseq_if_c>, iseq_if_c>, make_integer_sequence_impl_ > > +{ +}; + +} // namespace detail + +// make_integer_sequence +template using make_integer_sequence = typename detail::make_integer_sequence_impl::type; + +#endif // defined(BOOST_MP11_HAS_MAKE_INTEGER_SEQ) + +// index_sequence +template using index_sequence = integer_sequence; + +// make_index_sequence +template using make_index_sequence = make_integer_sequence; + +// index_sequence_for +template using index_sequence_for = make_integer_sequence; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_INTEGER_SEQUENCE_HPP_INCLUDED diff --git a/boost/mp11/integral.hpp b/boost/mp11/integral.hpp new file mode 100644 index 00000000..1b4fea3e --- /dev/null +++ b/boost/mp11/integral.hpp @@ -0,0 +1,42 @@ +#ifndef BOOST_MP11_INTEGRAL_HPP_INCLUDED +#define BOOST_MP11_INTEGRAL_HPP_INCLUDED + +// Copyright 2015 Peter Dimov. +// +// 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 + +#include +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_bool +template using mp_bool = std::integral_constant; + +using mp_true = mp_bool; +using mp_false = mp_bool; + +// mp_to_bool +template using mp_to_bool = mp_bool( T::value )>; + +// mp_not +template using mp_not = mp_bool< !T::value >; + +// mp_int +template using mp_int = std::integral_constant; + +// mp_size_t +template using mp_size_t = std::integral_constant; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_INTEGRAL_HPP_INCLUDED diff --git a/boost/mp11/list.hpp b/boost/mp11/list.hpp new file mode 100644 index 00000000..36467644 --- /dev/null +++ b/boost/mp11/list.hpp @@ -0,0 +1,472 @@ +#ifndef BOOST_MP11_LIST_HPP_INCLUDED +#define BOOST_MP11_LIST_HPP_INCLUDED + +// Copyright 2015-2023 Peter Dimov. +// +// 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_list +// in detail/mp_list.hpp + +// mp_list_c +template using mp_list_c = mp_list...>; + +// mp_list_v +// in detail/mp_list_v.hpp + +// mp_is_list +// in detail/mp_is_list.hpp + +// mp_is_value_list +// in detail/mp_is_value_list.hpp + +// mp_size +namespace detail +{ + +template struct mp_size_impl +{ +// An error "no type named 'type'" here means that the argument to mp_size is not a list +}; + +template class L, class... T> struct mp_size_impl> +{ + using type = mp_size_t; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto... A> struct mp_size_impl> +{ + using type = mp_size_t; +}; + +#endif + +} // namespace detail + +template using mp_size = typename detail::mp_size_impl::type; + +// mp_empty +template using mp_empty = mp_bool< mp_size::value == 0 >; + +// mp_assign +namespace detail +{ + +template struct mp_assign_impl +{ +// An error "no type named 'type'" here means that the arguments to mp_assign aren't lists +}; + +template class L1, class... T, template class L2, class... U> struct mp_assign_impl, L2> +{ + using type = L1; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L1, auto... A, template class L2, class... U> struct mp_assign_impl, L2> +{ + using type = L1; +}; + +template class L1, class... T, template class L2, auto... B> struct mp_assign_impl, L2> +{ + using type = L1...>; +}; + +template class L1, auto... A, template class L2, auto... B> struct mp_assign_impl, L2> +{ + using type = L1; +}; + +#endif + +} // namespace detail + +template using mp_assign = typename detail::mp_assign_impl::type; + +// mp_clear +template using mp_clear = mp_assign>; + +// mp_front +// in detail/mp_front.hpp + +// mp_pop_front +namespace detail +{ + +template struct mp_pop_front_impl +{ +// An error "no type named 'type'" here means that the argument to mp_pop_front +// is either not a list, or is an empty list +}; + +template class L, class T1, class... T> struct mp_pop_front_impl> +{ + using type = L; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto... A> struct mp_pop_front_impl> +{ + using type = L; +}; + +#endif + +} // namespace detail + +template using mp_pop_front = typename detail::mp_pop_front_impl::type; + +// mp_first +template using mp_first = mp_front; + +// mp_rest +template using mp_rest = mp_pop_front; + +// mp_second +namespace detail +{ + +template struct mp_second_impl +{ +// An error "no type named 'type'" here means that the argument to mp_second +// is either not a list, or has fewer than two elements +}; + +template class L, class T1, class T2, class... T> struct mp_second_impl> +{ + using type = T2; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto A2, auto... A> struct mp_second_impl> +{ + using type = mp_value; +}; + +#endif + +} // namespace detail + +template using mp_second = typename detail::mp_second_impl::type; + +// mp_third +namespace detail +{ + +template struct mp_third_impl +{ +// An error "no type named 'type'" here means that the argument to mp_third +// is either not a list, or has fewer than three elements +}; + +template class L, class T1, class T2, class T3, class... T> struct mp_third_impl> +{ + using type = T3; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto A2, auto A3, auto... A> struct mp_third_impl> +{ + using type = mp_value; +}; + +#endif + +} // namespace detail + +template using mp_third = typename detail::mp_third_impl::type; + +// mp_push_front +namespace detail +{ + +template struct mp_push_front_impl +{ +// An error "no type named 'type'" here means that the first argument to mp_push_front is not a list +}; + +template class L, class... U, class... T> struct mp_push_front_impl, T...> +{ + using type = L; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto... A, class... T> struct mp_push_front_impl, T...> +{ + using type = L; +}; + +#endif + +} // namespace detail + +template using mp_push_front = typename detail::mp_push_front_impl::type; + +// mp_push_back +namespace detail +{ + +template struct mp_push_back_impl +{ +// An error "no type named 'type'" here means that the first argument to mp_push_back is not a list +}; + +template class L, class... U, class... T> struct mp_push_back_impl, T...> +{ + using type = L; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto... A, class... T> struct mp_push_back_impl, T...> +{ + using type = L; +}; + +#endif + +} // namespace detail + +template using mp_push_back = typename detail::mp_push_back_impl::type; + +// mp_rename +// mp_apply +// mp_apply_q +// in detail/mp_rename.hpp + +// mp_rename_v +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +namespace detail +{ + +template class B> struct mp_rename_v_impl +{ +// An error "no type named 'type'" here means that the first argument to mp_rename_v is not a list +}; + +template class L, class... T, template class B> struct mp_rename_v_impl, B> +{ + using type = B; +}; + +template class L, auto... A, template class B> struct mp_rename_v_impl, B> +{ + using type = B; +}; + +} // namespace detail + +template class B> using mp_rename_v = typename detail::mp_rename_v_impl::type; + +#endif + +// mp_replace_front +namespace detail +{ + +template struct mp_replace_front_impl +{ +// An error "no type named 'type'" here means that the first argument to mp_replace_front +// is either not a list, or is an empty list +}; + +template class L, class U1, class... U, class T> struct mp_replace_front_impl, T> +{ + using type = L; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto... A, class T> struct mp_replace_front_impl, T> +{ + using type = L; +}; + +#endif + +} // namespace detail + +template using mp_replace_front = typename detail::mp_replace_front_impl::type; + +// mp_replace_first +template using mp_replace_first = typename detail::mp_replace_front_impl::type; + +// mp_replace_second +namespace detail +{ + +template struct mp_replace_second_impl +{ +// An error "no type named 'type'" here means that the first argument to mp_replace_second +// is either not a list, or has fewer than two elements +}; + +template class L, class U1, class U2, class... U, class T> struct mp_replace_second_impl, T> +{ + using type = L; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto A2, auto... A, class T> struct mp_replace_second_impl, T> +{ + using type = L; +}; + +#endif + +} // namespace detail + +template using mp_replace_second = typename detail::mp_replace_second_impl::type; + +// mp_replace_third +namespace detail +{ + +template struct mp_replace_third_impl +{ +// An error "no type named 'type'" here means that the first argument to mp_replace_third +// is either not a list, or has fewer than three elements +}; + +template class L, class U1, class U2, class U3, class... U, class T> struct mp_replace_third_impl, T> +{ + using type = L; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto A2, auto A3, auto... A, class T> struct mp_replace_third_impl, T> +{ + using type = L; +}; + +#endif + +} // namespace detail + +template using mp_replace_third = typename detail::mp_replace_third_impl::type; + +// mp_transform_front +namespace detail +{ + +template class F> struct mp_transform_front_impl +{ +// An error "no type named 'type'" here means that the first argument to mp_transform_front +// is either not a list, or is an empty list +}; + +template class L, class U1, class... U, template class F> struct mp_transform_front_impl, F> +{ + using type = L, U...>; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto... A, template class F> struct mp_transform_front_impl, F> +{ + using type = L>::value, A...>; +}; + +#endif + +} // namespace detail + +template class F> using mp_transform_front = typename detail::mp_transform_front_impl::type; +template using mp_transform_front_q = mp_transform_front; + +// mp_transform_first +template class F> using mp_transform_first = typename detail::mp_transform_front_impl::type; +template using mp_transform_first_q = mp_transform_first; + +// mp_transform_second +namespace detail +{ + +template class F> struct mp_transform_second_impl +{ +// An error "no type named 'type'" here means that the first argument to mp_transform_second +// is either not a list, or has fewer than two elements +}; + +template class L, class U1, class U2, class... U, template class F> struct mp_transform_second_impl, F> +{ + using type = L, U...>; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto A2, auto... A, template class F> struct mp_transform_second_impl, F> +{ + using type = L>::value, A...>; +}; + +#endif + +} // namespace detail + +template class F> using mp_transform_second = typename detail::mp_transform_second_impl::type; +template using mp_transform_second_q = mp_transform_second; + +// mp_transform_third +namespace detail +{ + +template class F> struct mp_transform_third_impl +{ +// An error "no type named 'type'" here means that the first argument to mp_transform_third +// is either not a list, or has fewer than three elements +}; + +template class L, class U1, class U2, class U3, class... U, template class F> struct mp_transform_third_impl, F> +{ + using type = L, U...>; +}; + +#if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) + +template class L, auto A1, auto A2, auto A3, auto... A, template class F> struct mp_transform_third_impl, F> +{ + using type = L>::value, A...>; +}; + +#endif + +} // namespace detail + +template class F> using mp_transform_third = typename detail::mp_transform_third_impl::type; +template using mp_transform_third_q = mp_transform_third; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_LIST_HPP_INCLUDED diff --git a/boost/mp11/set.hpp b/boost/mp11/set.hpp new file mode 100644 index 00000000..808636b7 --- /dev/null +++ b/boost/mp11/set.hpp @@ -0,0 +1,188 @@ +#ifndef BOOST_MP11_SET_HPP_INCLUDED +#define BOOST_MP11_SET_HPP_INCLUDED + +// Copyright 2015, 2019 Peter Dimov. +// +// 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_set_contains +namespace detail +{ + +template struct mp_set_contains_impl +{ +}; + +template class L, class... T, class V> struct mp_set_contains_impl, V> +{ + using type = mp_to_bool, mp_inherit...> > >; +}; + +} // namespace detail + +template using mp_set_contains = typename detail::mp_set_contains_impl::type; + +// mp_set_push_back +namespace detail +{ + +template struct mp_set_push_back_impl +{ +}; + +template class L, class... U> struct mp_set_push_back_impl> +{ + using type = L; +}; + +template class L, class... U, class T1, class... T> struct mp_set_push_back_impl, T1, T...> +{ + using S = mp_if, T1>, L, L>; + using type = typename mp_set_push_back_impl::type; +}; + +} // namespace detail + +template using mp_set_push_back = typename detail::mp_set_push_back_impl::type; + +// mp_set_push_front +namespace detail +{ + +template struct mp_set_push_front_impl +{ +}; + +template class L, class... U> struct mp_set_push_front_impl> +{ + using type = L; +}; + +template class L, class... U, class T1> struct mp_set_push_front_impl, T1> +{ + using type = mp_if, T1>, L, L>; +}; + +template class L, class... U, class T1, class... T> struct mp_set_push_front_impl, T1, T...> +{ + using S = typename mp_set_push_front_impl, T...>::type; + using type = typename mp_set_push_front_impl::type; +}; + +} // namespace detail + +template using mp_set_push_front = typename detail::mp_set_push_front_impl::type; + +// mp_is_set +namespace detail +{ + +template struct mp_is_set_impl +{ + using type = mp_false; +}; + +template class L, class... T> struct mp_is_set_impl> +{ + using type = mp_to_bool, mp_set_push_back, T...> > >; +}; + +} // namespace detail + +template using mp_is_set = typename detail::mp_is_set_impl::type; + +// mp_set_union +namespace detail +{ + +template struct mp_set_union_impl +{ +}; + +template<> struct mp_set_union_impl<> +{ + using type = mp_list<>; +}; + +template class L, class... T> struct mp_set_union_impl> +{ + using type = L; +}; + +template class L1, class... T1, template class L2, class... T2> struct mp_set_union_impl, L2> +{ + using type = mp_set_push_back, T2...>; +}; + +template using mp_set_union_ = typename mp_set_union_impl, L...>>::type; + +template struct mp_set_union_impl: mp_defer +{ +}; + +} // namespace detail + +template using mp_set_union = typename detail::mp_set_union_impl::type; + +// mp_set_intersection +namespace detail +{ + +template struct in_all_sets +{ + template using fn = mp_all< mp_set_contains... >; +}; + +template using mp_set_intersection_ = mp_if< mp_all...>, mp_copy_if_q> >; + +template struct mp_set_intersection_impl +{ +}; + +template<> struct mp_set_intersection_impl<> +{ + using type = mp_list<>; +}; + +template struct mp_set_intersection_impl: mp_defer +{ +}; + +} // namespace detail + +template using mp_set_intersection = typename detail::mp_set_intersection_impl::type; + +// mp_set_difference +namespace detail +{ + +template struct in_any_set +{ + template using fn = mp_any< mp_set_contains... >; +}; + +} // namespace detail + +template using mp_set_difference = mp_if< mp_all...>, mp_remove_if_q> >; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_SET_HPP_INCLUDED diff --git a/boost/mp11/utility.hpp b/boost/mp11/utility.hpp new file mode 100644 index 00000000..4010aee2 --- /dev/null +++ b/boost/mp11/utility.hpp @@ -0,0 +1,169 @@ +#ifndef BOOST_MP11_UTILITY_HPP_INCLUDED +#define BOOST_MP11_UTILITY_HPP_INCLUDED + +// Copyright 2015-2020 Peter Dimov. +// +// 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 + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_identity +template struct mp_identity +{ + using type = T; +}; + +// mp_identity_t +template using mp_identity_t = typename mp_identity::type; + +// mp_inherit +template struct mp_inherit: T... {}; + +// mp_if, mp_if_c +// mp_valid +// mp_defer +// moved to detail/mp_defer.hpp + +// mp_eval_if, mp_eval_if_c +namespace detail +{ + +template class F, class... U> struct mp_eval_if_c_impl; + +template class F, class... U> struct mp_eval_if_c_impl +{ + using type = T; +}; + +template class F, class... U> struct mp_eval_if_c_impl: mp_defer +{ +}; + +} // namespace detail + +template class F, class... U> using mp_eval_if_c = typename detail::mp_eval_if_c_impl::type; +template class F, class... U> using mp_eval_if = typename detail::mp_eval_if_c_impl(C::value), T, F, U...>::type; +template using mp_eval_if_q = typename detail::mp_eval_if_c_impl(C::value), T, Q::template fn, U...>::type; + +// mp_eval_if_not +template class F, class... U> using mp_eval_if_not = mp_eval_if, T, F, U...>; +template using mp_eval_if_not_q = mp_eval_if, T, Q::template fn, U...>; + +// mp_eval_or +template class F, class... U> using mp_eval_or = mp_eval_if_not, T, F, U...>; +template using mp_eval_or_q = mp_eval_or; + +// mp_valid_and_true +template class F, class... T> using mp_valid_and_true = mp_eval_or; +template using mp_valid_and_true_q = mp_valid_and_true; + +// mp_cond + +// so elegant; so doesn't work +// template using mp_cond = mp_eval_if; + +namespace detail +{ + +template struct mp_cond_impl; + +} // namespace detail + +template using mp_cond = typename detail::mp_cond_impl::type; + +namespace detail +{ + +template using mp_cond_ = mp_eval_if; + +template struct mp_cond_impl: mp_defer +{ +}; + +} // namespace detail + +// mp_quote +template class F> struct mp_quote +{ + // the indirection through mp_defer works around the language inability + // to expand T... into a fixed parameter list of an alias template + + template using fn = typename mp_defer::type; +}; + +// mp_quote_trait +template class F> struct mp_quote_trait +{ + template using fn = typename F::type; +}; + +// mp_invoke_q +#if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1900 ) + +namespace detail +{ + +template struct mp_invoke_q_impl: mp_defer {}; + +} // namespace detail + +template using mp_invoke_q = typename detail::mp_invoke_q_impl::type; + +#elif BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 50000 ) + +template using mp_invoke_q = typename mp_defer::type; + +#else + +template using mp_invoke_q = typename Q::template fn; + +#endif + +// mp_not_fn

+template class P> struct mp_not_fn +{ + template using fn = mp_not< mp_invoke_q, T...> >; +}; + +template using mp_not_fn_q = mp_not_fn; + +// mp_compose +namespace detail +{ + +template using mp_compose_helper = mp_list< mp_apply_q >; + +} // namespace detail + +#if !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1900 ) + +template class... F> struct mp_compose +{ + template using fn = mp_front< mp_fold...>, mp_list, detail::mp_compose_helper> >; +}; + +#endif + +template struct mp_compose_q +{ + template using fn = mp_front< mp_fold, mp_list, detail::mp_compose_helper> >; +}; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED diff --git a/boost/mp11/version.hpp b/boost/mp11/version.hpp new file mode 100644 index 00000000..ab5e09c3 --- /dev/null +++ b/boost/mp11/version.hpp @@ -0,0 +1,16 @@ +#ifndef BOOST_MP11_VERSION_HPP_INCLUDED +#define BOOST_MP11_VERSION_HPP_INCLUDED + +// Copyright 2019 Peter Dimov +// +// 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 + +// Same format as BOOST_VERSION: +// major * 100000 + minor * 100 + patch + +#define BOOST_MP11_VERSION 108400 + +#endif // #ifndef BOOST_MP11_VERSION_HPP_INCLUDED diff --git a/boost/mpl/O1_size.hpp b/boost/mpl/O1_size.hpp new file mode 100644 index 00000000..98bd3a74 --- /dev/null +++ b/boost/mpl/O1_size.hpp @@ -0,0 +1,40 @@ + +#ifndef BOOST_MPL_O1_SIZE_HPP_INCLUDED +#define BOOST_MPL_O1_SIZE_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +// returns sequence size if it's an O(1) operation; otherwise returns -1 +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + > +struct O1_size + : O1_size_impl< typename sequence_tag::type > + ::template apply< Sequence > +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1, O1_size, (Sequence)) +}; + +BOOST_MPL_AUX_NA_SPEC(1, O1_size) + +}} + +#endif // BOOST_MPL_O1_SIZE_HPP_INCLUDED diff --git a/boost/mpl/O1_size_fwd.hpp b/boost/mpl/O1_size_fwd.hpp new file mode 100644 index 00000000..c84a7a56 --- /dev/null +++ b/boost/mpl/O1_size_fwd.hpp @@ -0,0 +1,24 @@ + +#ifndef BOOST_MPL_O1_SIZE_FWD_HPP_INCLUDED +#define BOOST_MPL_O1_SIZE_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +template< typename Tag > struct O1_size_impl; +template< typename Sequence > struct O1_size; + +}} + +#endif // BOOST_MPL_O1_SIZE_FWD_HPP_INCLUDED diff --git a/boost/mpl/advance.hpp b/boost/mpl/advance.hpp new file mode 100644 index 00000000..1af60041 --- /dev/null +++ b/boost/mpl/advance.hpp @@ -0,0 +1,76 @@ + +#ifndef BOOST_MPL_ADVANCE_HPP_INCLUDED +#define BOOST_MPL_ADVANCE_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +// default implementation for forward/bidirectional iterators +template< typename Tag > +struct advance_impl +{ + template< typename Iterator, typename N > struct apply + { + typedef typename less< N,long_<0> >::type backward_; + typedef typename if_< backward_, negate, N >::type offset_; + + typedef typename if_< + backward_ + , aux::advance_backward< BOOST_MPL_AUX_VALUE_WKND(offset_)::value > + , aux::advance_forward< BOOST_MPL_AUX_VALUE_WKND(offset_)::value > + >::type f_; + + typedef typename apply_wrap1::type type; + }; +}; + + +template< + typename BOOST_MPL_AUX_NA_PARAM(Iterator) + , typename BOOST_MPL_AUX_NA_PARAM(N) + > +struct advance + : advance_impl< typename tag::type > + ::template apply +{ +}; + +template< + typename Iterator + , BOOST_MPL_AUX_NTTP_DECL(long, N) + > +struct advance_c + : advance_impl< typename tag::type > + ::template apply > +{ +}; + +BOOST_MPL_AUX_NA_SPEC(2, advance) + +}} + +#endif // BOOST_MPL_ADVANCE_HPP_INCLUDED diff --git a/boost/mpl/advance_fwd.hpp b/boost/mpl/advance_fwd.hpp new file mode 100644 index 00000000..80384101 --- /dev/null +++ b/boost/mpl/advance_fwd.hpp @@ -0,0 +1,28 @@ + +#ifndef BOOST_MPL_ADVANCE_FWD_HPP_INCLUDED +#define BOOST_MPL_ADVANCE_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include + +namespace boost { namespace mpl { + +BOOST_MPL_AUX_COMMON_NAME_WKND(advance) + +template< typename Tag > struct advance_impl; +template< typename Iterator, typename N > struct advance; + +}} + +#endif // BOOST_MPL_ADVANCE_FWD_HPP_INCLUDED diff --git a/boost/mpl/at.hpp b/boost/mpl/at.hpp new file mode 100644 index 00000000..aa90e59c --- /dev/null +++ b/boost/mpl/at.hpp @@ -0,0 +1,52 @@ + +#ifndef BOOST_MPL_AT_HPP_INCLUDED +#define BOOST_MPL_AT_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + , typename BOOST_MPL_AUX_NA_PARAM(N) + > +struct at + : at_impl< typename sequence_tag::type > + ::template apply< Sequence,N > +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,at,(Sequence,N)) +}; + +template< + typename Sequence + , BOOST_MPL_AUX_NTTP_DECL(long, N) + > +struct at_c + : at_impl< typename sequence_tag::type > + ::template apply< Sequence,mpl::long_ > +{ +}; + +BOOST_MPL_AUX_NA_SPEC(2, at) + +}} + +#endif // BOOST_MPL_AT_HPP_INCLUDED diff --git a/boost/mpl/at_fwd.hpp b/boost/mpl/at_fwd.hpp new file mode 100644 index 00000000..6aaae383 --- /dev/null +++ b/boost/mpl/at_fwd.hpp @@ -0,0 +1,24 @@ + +#ifndef BOOST_MPL_AT_FWD_HPP_INCLUDED +#define BOOST_MPL_AT_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +template< typename Tag > struct at_impl; +template< typename Sequence, typename N > struct at; + +}} + +#endif // BOOST_MPL_AT_FWD_HPP_INCLUDED diff --git a/boost/mpl/aux_/O1_size_impl.hpp b/boost/mpl/aux_/O1_size_impl.hpp new file mode 100644 index 00000000..3bcbd0f7 --- /dev/null +++ b/boost/mpl/aux_/O1_size_impl.hpp @@ -0,0 +1,87 @@ + +#ifndef BOOST_MPL_O1_SIZE_IMPL_HPP_INCLUDED +#define BOOST_MPL_O1_SIZE_IMPL_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +// default implementation - returns 'Sequence::size' if sequence has a 'size' +// member, and -1 otherwise; conrete sequences might override it by +// specializing either the 'O1_size_impl' or the primary 'O1_size' template + +# if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ + && !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + +namespace aux { +template< typename Sequence > struct O1_size_impl + : Sequence::size +{ +}; +} + +template< typename Tag > +struct O1_size_impl +{ + template< typename Sequence > struct apply +#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING) + : if_< + aux::has_size + , aux::O1_size_impl + , long_<-1> + >::type + { +#else + { + typedef typename if_< + aux::has_size + , aux::O1_size_impl + , long_<-1> + >::type type; + + BOOST_STATIC_CONSTANT(long, value = + (if_< + aux::has_size + , aux::O1_size_impl + , long_<-1> + >::type::value) + ); +#endif + }; +}; + +# else // BOOST_MSVC + +template< typename Tag > +struct O1_size_impl +{ + template< typename Sequence > struct apply + : long_<-1> + { + }; +}; + +# endif + +}} + +#endif // BOOST_MPL_O1_SIZE_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/advance_backward.hpp b/boost/mpl/aux_/advance_backward.hpp new file mode 100644 index 00000000..df567932 --- /dev/null +++ b/boost/mpl/aux_/advance_backward.hpp @@ -0,0 +1,128 @@ + +#if !defined(BOOST_PP_IS_ITERATING) + +///// header body + +#ifndef BOOST_MPL_AUX778076_ADVANCE_BACKWARD_HPP_INCLUDED +#define BOOST_MPL_AUX778076_ADVANCE_BACKWARD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +# include +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER advance_backward.hpp +# include + +#else + +# include +# include +# include + +# include +# include +# include + +namespace boost { namespace mpl { namespace aux { + +// forward declaration +template< BOOST_MPL_AUX_NTTP_DECL(long, N) > struct advance_backward; + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(0, BOOST_MPL_LIMIT_UNROLLING, )) +# include BOOST_PP_ITERATE() + +// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING +template< BOOST_MPL_AUX_NTTP_DECL(long, N) > +struct advance_backward +{ + template< typename Iterator > struct apply + { + typedef typename apply_wrap1< + advance_backward + , Iterator + >::type chunk_result_; + + typedef typename apply_wrap1< + advance_backward<( + (N - BOOST_MPL_LIMIT_UNROLLING) < 0 + ? 0 + : N - BOOST_MPL_LIMIT_UNROLLING + )> + , chunk_result_ + >::type type; + }; +}; + +}}} + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS +#endif // BOOST_MPL_AUX778076_ADVANCE_BACKWARD_HPP_INCLUDED + +///// iteration, depth == 1 + +// For gcc 4.4 compatability, we must include the +// BOOST_PP_ITERATION_DEPTH test inside an #else clause. +#else // BOOST_PP_IS_ITERATING +#if BOOST_PP_ITERATION_DEPTH() == 1 +#define i_ BOOST_PP_FRAME_ITERATION(1) + +template<> +struct advance_backward< BOOST_PP_FRAME_ITERATION(1) > +{ + template< typename Iterator > struct apply + { + typedef Iterator iter0; + +#if i_ > 0 +# define BOOST_PP_ITERATION_PARAMS_2 \ + (3,(1, BOOST_PP_FRAME_ITERATION(1), )) +# include BOOST_PP_ITERATE() +#endif + + typedef BOOST_PP_CAT(iter,BOOST_PP_FRAME_ITERATION(1)) type; + }; + +#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) + /// ETI workaround + template<> struct apply + { + typedef int type; + }; +#endif +}; + +#undef i_ + +///// iteration, depth == 2 + +#elif BOOST_PP_ITERATION_DEPTH() == 2 + +# define AUX778076_ITER_0 BOOST_PP_CAT(iter,BOOST_PP_DEC(BOOST_PP_FRAME_ITERATION(2))) +# define AUX778076_ITER_1 BOOST_PP_CAT(iter,BOOST_PP_FRAME_ITERATION(2)) + + typedef typename prior::type AUX778076_ITER_1; + +# undef AUX778076_ITER_1 +# undef AUX778076_ITER_0 + +#endif // BOOST_PP_ITERATION_DEPTH() +#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/aux_/advance_forward.hpp b/boost/mpl/aux_/advance_forward.hpp new file mode 100644 index 00000000..62b0101c --- /dev/null +++ b/boost/mpl/aux_/advance_forward.hpp @@ -0,0 +1,127 @@ + +#if !defined(BOOST_PP_IS_ITERATING) + +///// header body + +#ifndef BOOST_MPL_AUX_ADVANCE_FORWARD_HPP_INCLUDED +#define BOOST_MPL_AUX_ADVANCE_FORWARD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +# include +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER advance_forward.hpp +# include + +#else + +# include +# include +# include + +# include +# include +# include + +namespace boost { namespace mpl { namespace aux { + +// forward declaration +template< BOOST_MPL_AUX_NTTP_DECL(long, N) > struct advance_forward; + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(0, BOOST_MPL_LIMIT_UNROLLING, )) +# include BOOST_PP_ITERATE() + +// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING +template< BOOST_MPL_AUX_NTTP_DECL(long, N) > +struct advance_forward +{ + template< typename Iterator > struct apply + { + typedef typename apply_wrap1< + advance_forward + , Iterator + >::type chunk_result_; + + typedef typename apply_wrap1< + advance_forward<( + (N - BOOST_MPL_LIMIT_UNROLLING) < 0 + ? 0 + : N - BOOST_MPL_LIMIT_UNROLLING + )> + , chunk_result_ + >::type type; + }; +}; + +}}} + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS +#endif // BOOST_MPL_AUX_ADVANCE_FORWARD_HPP_INCLUDED + +///// iteration, depth == 1 + +// For gcc 4.4 compatability, we must include the +// BOOST_PP_ITERATION_DEPTH test inside an #else clause. +#else // BOOST_PP_IS_ITERATING +#if BOOST_PP_ITERATION_DEPTH() == 1 +#define i_ BOOST_PP_FRAME_ITERATION(1) + +template<> +struct advance_forward< BOOST_PP_FRAME_ITERATION(1) > +{ + template< typename Iterator > struct apply + { + typedef Iterator iter0; + +#if i_ > 0 +# define BOOST_PP_ITERATION_PARAMS_2 \ + (3,(1, i_, )) +# include BOOST_PP_ITERATE() +#endif + typedef BOOST_PP_CAT(iter,i_) type; + }; + +#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) + /// ETI workaround + template<> struct apply + { + typedef int type; + }; +#endif +}; + +#undef i_ + +///// iteration, depth == 2 + +#elif BOOST_PP_ITERATION_DEPTH() == 2 + +# define AUX778076_ITER_0 BOOST_PP_CAT(iter,BOOST_PP_DEC(BOOST_PP_FRAME_ITERATION(2))) +# define AUX778076_ITER_1 BOOST_PP_CAT(iter,BOOST_PP_FRAME_ITERATION(2)) + + typedef typename next::type AUX778076_ITER_1; + +# undef AUX778076_ITER_1 +# undef AUX778076_ITER_0 + +#endif // BOOST_PP_ITERATION_DEPTH() +#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/aux_/at_impl.hpp b/boost/mpl/aux_/at_impl.hpp new file mode 100644 index 00000000..92393748 --- /dev/null +++ b/boost/mpl/aux_/at_impl.hpp @@ -0,0 +1,45 @@ + +#ifndef BOOST_MPL_AUX_AT_IMPL_HPP_INCLUDED +#define BOOST_MPL_AUX_AT_IMPL_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include + +namespace boost { namespace mpl { + +// default implementation; conrete sequences might override it by +// specializing either the 'at_impl' or the primary 'at' template + +template< typename Tag > +struct at_impl +{ + template< typename Sequence, typename N > struct apply + { + typedef typename advance< + typename begin::type + , N + >::type iter_; + + typedef typename deref::type type; + }; +}; + +BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(2, at_impl) + +}} + +#endif // BOOST_MPL_AUX_AT_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/begin_end_impl.hpp b/boost/mpl/aux_/begin_end_impl.hpp new file mode 100644 index 00000000..58b70dd1 --- /dev/null +++ b/boost/mpl/aux_/begin_end_impl.hpp @@ -0,0 +1,101 @@ + +#ifndef BOOST_MPL_AUX_BEGIN_END_IMPL_HPP_INCLUDED +#define BOOST_MPL_AUX_BEGIN_END_IMPL_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + + +namespace aux { + +template< typename Sequence > +struct begin_type +{ + typedef typename Sequence::begin type; +}; +template< typename Sequence > +struct end_type +{ + typedef typename Sequence::end type; +}; + +} + +// default implementation; conrete sequences might override it by +// specializing either the 'begin_impl/end_impl' or the primary +// 'begin/end' templates + +template< typename Tag > +struct begin_impl +{ + template< typename Sequence > struct apply + { + typedef typename eval_if, + aux::begin_type, void_>::type type; + }; +}; + +template< typename Tag > +struct end_impl +{ + template< typename Sequence > struct apply + { + typedef typename eval_if, + aux::end_type, void_>::type type; + }; +}; + +// specialize 'begin_trait/end_trait' for two pre-defined tags + +# define AUX778076_IMPL_SPEC(name, tag, result) \ +template<> \ +struct name##_impl \ +{ \ + template< typename Sequence > struct apply \ + { \ + typedef result type; \ + }; \ +}; \ +/**/ + +// a sequence with nested 'begin/end' typedefs; just query them +AUX778076_IMPL_SPEC(begin, nested_begin_end_tag, typename Sequence::begin) +AUX778076_IMPL_SPEC(end, nested_begin_end_tag, typename Sequence::end) + +// if a type 'T' does not contain 'begin/end' or 'tag' members +// and doesn't specialize either 'begin/end' or 'begin_impl/end_impl' +// templates, then we end up here +AUX778076_IMPL_SPEC(begin, non_sequence_tag, void_) +AUX778076_IMPL_SPEC(end, non_sequence_tag, void_) +AUX778076_IMPL_SPEC(begin, na, void_) +AUX778076_IMPL_SPEC(end, na, void_) + +# undef AUX778076_IMPL_SPEC + + +BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(1,begin_impl) +BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(1,end_impl) + +}} + +#endif // BOOST_MPL_AUX_BEGIN_END_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/clear_impl.hpp b/boost/mpl/aux_/clear_impl.hpp new file mode 100644 index 00000000..20b270c0 --- /dev/null +++ b/boost/mpl/aux_/clear_impl.hpp @@ -0,0 +1,35 @@ + +#ifndef BOOST_MPL_AUX_CLEAR_IMPL_HPP_INCLUDED +#define BOOST_MPL_AUX_CLEAR_IMPL_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include + +namespace boost { namespace mpl { + +// no default implementation; the definition is needed to make MSVC happy + +template< typename Tag > +struct clear_impl +{ + template< typename Sequence > struct apply; +}; + +BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1, clear_impl) + +}} + +#endif // BOOST_MPL_AUX_CLEAR_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/config/typeof.hpp b/boost/mpl/aux_/config/typeof.hpp new file mode 100644 index 00000000..cde6179c --- /dev/null +++ b/boost/mpl/aux_/config/typeof.hpp @@ -0,0 +1,38 @@ + +#ifndef BOOST_MPL_AUX_CONFIG_TYPEOF_HPP_INCLUDED +#define BOOST_MPL_AUX_CONFIG_TYPEOF_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2003-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include + +#if !defined(BOOST_MPL_CFG_HAS_TYPEOF) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) \ + && ( defined(BOOST_MPL_CFG_GCC) && BOOST_MPL_CFG_GCC >= 0x0302 \ + || defined(__MWERKS__) && __MWERKS__ >= 0x3000 \ + ) + +# define BOOST_MPL_CFG_HAS_TYPEOF + +#endif + + +#if !defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) \ + && defined(BOOST_MPL_CFG_HAS_TYPEOF) + +# define BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +#endif + +#endif // BOOST_MPL_AUX_CONFIG_TYPEOF_HPP_INCLUDED diff --git a/boost/mpl/aux_/fold_impl.hpp b/boost/mpl/aux_/fold_impl.hpp new file mode 100644 index 00000000..97c88c5b --- /dev/null +++ b/boost/mpl/aux_/fold_impl.hpp @@ -0,0 +1,43 @@ + +#ifndef BOOST_MPL_AUX_FOLD_IMPL_HPP_INCLUDED +#define BOOST_MPL_AUX_FOLD_IMPL_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +# include +# include +# include +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +# include +# include +# endif +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER fold_impl.hpp +# include + +#else + +# define AUX778076_FOLD_IMPL_OP(iter) typename deref::type +# define AUX778076_FOLD_IMPL_NAME_PREFIX fold +# include + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS +#endif // BOOST_MPL_AUX_FOLD_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/fold_impl_body.hpp b/boost/mpl/aux_/fold_impl_body.hpp new file mode 100644 index 00000000..c5e16601 --- /dev/null +++ b/boost/mpl/aux_/fold_impl_body.hpp @@ -0,0 +1,365 @@ + +// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION + +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +# include +# include +# include +# include +# include +# include + +# include +# include +# include + +// local macros, #undef-ined at the end of the header + +# define AUX778076_ITER_FOLD_STEP(unused, i, unused2) \ + typedef typename apply2< \ + ForwardOp \ + , BOOST_PP_CAT(state,i) \ + , AUX778076_FOLD_IMPL_OP(BOOST_PP_CAT(iter,i)) \ + >::type BOOST_PP_CAT(state,BOOST_PP_INC(i)); \ + typedef typename mpl::next::type \ + BOOST_PP_CAT(iter,BOOST_PP_INC(i)); \ + /**/ + +# define AUX778076_FOLD_IMPL_NAME \ + BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_impl) \ + /**/ + +# define AUX778076_FOLD_CHUNK_NAME \ + BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_chunk) \ + /**/ + +namespace boost { namespace mpl { namespace aux { + +/// forward declaration +template< + BOOST_MPL_AUX_NTTP_DECL(int, N) + , typename First + , typename Last + , typename State + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME; + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +# if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x600) + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(0, BOOST_MPL_LIMIT_UNROLLING, )) +# include BOOST_PP_ITERATE() + +// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING +template< + BOOST_MPL_AUX_NTTP_DECL(int, N) + , typename First + , typename Last + , typename State + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME +{ + typedef AUX778076_FOLD_IMPL_NAME< + BOOST_MPL_LIMIT_UNROLLING + , First + , Last + , State + , ForwardOp + > chunk_; + + typedef AUX778076_FOLD_IMPL_NAME< + ( (N - BOOST_MPL_LIMIT_UNROLLING) < 0 ? 0 : N - BOOST_MPL_LIMIT_UNROLLING ) + , typename chunk_::iterator + , Last + , typename chunk_::state + , ForwardOp + > res_; + + typedef typename res_::state state; + typedef typename res_::iterator iterator; +}; + +// fallback implementation for sequences of unknown size +template< + typename First + , typename Last + , typename State + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME<-1,First,Last,State,ForwardOp> + : AUX778076_FOLD_IMPL_NAME< + -1 + , typename mpl::next::type + , Last + , typename apply2::type + , ForwardOp + > +{ +}; + +template< + typename Last + , typename State + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME<-1,Last,Last,State,ForwardOp> +{ + typedef State state; + typedef Last iterator; +}; + +# else // BOOST_WORKAROUND(BOOST_BORLANDC, < 0x600) + +// Borland have some serious problems with the unrolled version, so +// we always use a basic implementation +template< + BOOST_MPL_AUX_NTTP_DECL(int, N) + , typename First + , typename Last + , typename State + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME +{ + typedef AUX778076_FOLD_IMPL_NAME< + -1 + , typename mpl::next::type + , Last + , typename apply2::type + , ForwardOp + > res_; + + typedef typename res_::state state; + typedef typename res_::iterator iterator; + typedef state type; +}; + +template< + BOOST_MPL_AUX_NTTP_DECL(int, N) + , typename Last + , typename State + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME +{ + typedef State state; + typedef Last iterator; + typedef state type; +}; + +# endif // BOOST_WORKAROUND(BOOST_BORLANDC, < 0x600) + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +template< BOOST_MPL_AUX_NTTP_DECL(int, N) > +struct AUX778076_FOLD_CHUNK_NAME; + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(0, BOOST_MPL_LIMIT_UNROLLING, )) +# include BOOST_PP_ITERATE() + +// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING +template< BOOST_MPL_AUX_NTTP_DECL(int, N) > +struct AUX778076_FOLD_CHUNK_NAME +{ + template< + typename First + , typename Last + , typename State + , typename ForwardOp + > + struct result_ + { + typedef AUX778076_FOLD_IMPL_NAME< + BOOST_MPL_LIMIT_UNROLLING + , First + , Last + , State + , ForwardOp + > chunk_; + + typedef AUX778076_FOLD_IMPL_NAME< + ( (N - BOOST_MPL_LIMIT_UNROLLING) < 0 ? 0 : N - BOOST_MPL_LIMIT_UNROLLING ) + , typename chunk_::iterator + , Last + , typename chunk_::state + , ForwardOp + > res_; + + typedef typename res_::state state; + typedef typename res_::iterator iterator; + }; +}; + +// fallback implementation for sequences of unknown size +template< + typename First + , typename Last + , typename State + , typename ForwardOp + > +struct BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_step); + +template< + typename Last + , typename State + > +struct BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_null_step) +{ + typedef Last iterator; + typedef State state; +}; + +template<> +struct AUX778076_FOLD_CHUNK_NAME<-1> +{ + template< + typename First + , typename Last + , typename State + , typename ForwardOp + > + struct result_ + { + typedef typename if_< + typename is_same::type + , BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_null_step) + , BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_step) + >::type res_; + + typedef typename res_::state state; + typedef typename res_::iterator iterator; + }; + +#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) + /// ETI workaround + template<> struct result_ + { + typedef int state; + typedef int iterator; + }; +#endif +}; + +template< + typename First + , typename Last + , typename State + , typename ForwardOp + > +struct BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_step) +{ + // can't inherit here - it breaks MSVC 7.0 + typedef AUX778076_FOLD_CHUNK_NAME<-1>::template result_< + typename mpl::next::type + , Last + , typename apply2::type + , ForwardOp + > chunk_; + + typedef typename chunk_::state state; + typedef typename chunk_::iterator iterator; +}; + +template< + BOOST_MPL_AUX_NTTP_DECL(int, N) + , typename First + , typename Last + , typename State + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME + : AUX778076_FOLD_CHUNK_NAME + ::template result_ +{ +}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +}}} + +# undef AUX778076_FOLD_IMPL_NAME +# undef AUX778076_FOLD_CHUNK_NAME +# undef AUX778076_ITER_FOLD_STEP + +#undef AUX778076_FOLD_IMPL_OP +#undef AUX778076_FOLD_IMPL_NAME_PREFIX + +///// iteration + +#else + +# define n_ BOOST_PP_FRAME_ITERATION(1) + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template< + typename First + , typename Last + , typename State + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME +{ + typedef First iter0; + typedef State state0; + + BOOST_MPL_PP_REPEAT(n_, AUX778076_ITER_FOLD_STEP, unused) + + typedef BOOST_PP_CAT(state,n_) state; + typedef BOOST_PP_CAT(iter,n_) iterator; +}; + +#else + +template<> struct AUX778076_FOLD_CHUNK_NAME +{ + template< + typename First + , typename Last + , typename State + , typename ForwardOp + > + struct result_ + { + typedef First iter0; + typedef State state0; + + BOOST_MPL_PP_REPEAT(n_, AUX778076_ITER_FOLD_STEP, unused) + + typedef BOOST_PP_CAT(state,n_) state; + typedef BOOST_PP_CAT(iter,n_) iterator; + }; + +#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) + /// ETI workaround + template<> struct result_ + { + typedef int state; + typedef int iterator; + }; +#endif +}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +# undef n_ + +#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/aux_/has_begin.hpp b/boost/mpl/aux_/has_begin.hpp new file mode 100644 index 00000000..4ee415cb --- /dev/null +++ b/boost/mpl/aux_/has_begin.hpp @@ -0,0 +1,23 @@ + +#ifndef BOOST_MPL_AUX_HAS_BEGIN_HPP_INCLUDED +#define BOOST_MPL_AUX_HAS_BEGIN_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2002-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include + +namespace boost { namespace mpl { namespace aux { +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_begin, begin, true) +}}} + +#endif // BOOST_MPL_AUX_HAS_BEGIN_HPP_INCLUDED diff --git a/boost/mpl/aux_/has_size.hpp b/boost/mpl/aux_/has_size.hpp new file mode 100644 index 00000000..ff29913f --- /dev/null +++ b/boost/mpl/aux_/has_size.hpp @@ -0,0 +1,23 @@ + +#ifndef BOOST_MPL_AUX_HAS_SIZE_HPP_INCLUDED +#define BOOST_MPL_AUX_HAS_SIZE_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2002-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include + +namespace boost { namespace mpl { namespace aux { +BOOST_MPL_HAS_XXX_TRAIT_DEF(size) +}}} + +#endif // BOOST_MPL_AUX_HAS_SIZE_HPP_INCLUDED diff --git a/boost/mpl/aux_/inserter_algorithm.hpp b/boost/mpl/aux_/inserter_algorithm.hpp new file mode 100644 index 00000000..20ae8161 --- /dev/null +++ b/boost/mpl/aux_/inserter_algorithm.hpp @@ -0,0 +1,159 @@ + +#ifndef BOOST_MPL_AUX_INSERTER_ALGORITHM_HPP_INCLUDED +#define BOOST_MPL_AUX_INSERTER_ALGORITHM_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2003-2004 +// Copyright David Abrahams 2003-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +# define BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF(arity, name) \ +BOOST_MPL_AUX_COMMON_NAME_WKND(name) \ +template< \ + BOOST_MPL_PP_DEFAULT_PARAMS(arity, typename P, na) \ + > \ +struct name \ + : aux::name##_impl \ +{ \ +}; \ +\ +template< \ + BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), typename P) \ + > \ +struct name< BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P),na > \ + : if_< has_push_back< typename clear::type> \ + , aux::name##_impl< \ + BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ + , back_inserter< typename clear::type > \ + > \ + , aux::reverse_##name##_impl< \ + BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ + , front_inserter< typename clear::type > \ + > \ + >::type \ +{ \ +}; \ +\ +template< \ + BOOST_MPL_PP_DEFAULT_PARAMS(arity, typename P, na) \ + > \ +struct reverse_##name \ + : aux::reverse_##name##_impl \ +{ \ +}; \ +\ +template< \ + BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), typename P) \ + > \ +struct reverse_##name< BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P),na > \ + : if_< has_push_back \ + , aux::reverse_##name##_impl< \ + BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ + , back_inserter< typename clear::type > \ + > \ + , aux::name##_impl< \ + BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ + , front_inserter< typename clear::type > \ + > \ + >::type \ +{ \ +}; \ +BOOST_MPL_AUX_NA_SPEC(arity, name) \ +BOOST_MPL_AUX_NA_SPEC(arity, reverse_##name) \ +/**/ + +#else + +# define BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF(arity, name) \ +BOOST_MPL_AUX_COMMON_NAME_WKND(name) \ +template< \ + BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), typename P) \ + > \ +struct def_##name##_impl \ + : if_< has_push_back \ + , aux::name##_impl< \ + BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ + , back_inserter< typename clear::type > \ + > \ + , aux::reverse_##name##_impl< \ + BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ + , front_inserter< typename clear::type > \ + > \ + >::type \ +{ \ +}; \ +\ +template< \ + BOOST_MPL_PP_DEFAULT_PARAMS(arity, typename P, na) \ + > \ +struct name \ +{ \ + typedef typename eval_if< \ + is_na \ + , def_##name##_impl \ + , aux::name##_impl \ + >::type type; \ +}; \ +\ +template< \ + BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), typename P) \ + > \ +struct def_reverse_##name##_impl \ + : if_< has_push_back \ + , aux::reverse_##name##_impl< \ + BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ + , back_inserter< typename clear::type > \ + > \ + , aux::name##_impl< \ + BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \ + , front_inserter< typename clear::type > \ + > \ + >::type \ +{ \ +}; \ +template< \ + BOOST_MPL_PP_DEFAULT_PARAMS(arity, typename P, na) \ + > \ +struct reverse_##name \ +{ \ + typedef typename eval_if< \ + is_na \ + , def_reverse_##name##_impl \ + , aux::reverse_##name##_impl \ + >::type type; \ +}; \ +BOOST_MPL_AUX_NA_SPEC(arity, name) \ +BOOST_MPL_AUX_NA_SPEC(arity, reverse_##name) \ +/**/ + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_MPL_AUX_INSERTER_ALGORITHM_HPP_INCLUDED diff --git a/boost/mpl/aux_/iter_fold_impl.hpp b/boost/mpl/aux_/iter_fold_impl.hpp new file mode 100644 index 00000000..b4d2922f --- /dev/null +++ b/boost/mpl/aux_/iter_fold_impl.hpp @@ -0,0 +1,42 @@ + +#ifndef BOOST_MPL_AUX_ITER_FOLD_IMPL_HPP_INCLUDED +#define BOOST_MPL_AUX_ITER_FOLD_IMPL_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +# include +# include +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +# include +# include +# endif +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER iter_fold_impl.hpp +# include + +#else + +# define AUX778076_FOLD_IMPL_OP(iter) iter +# define AUX778076_FOLD_IMPL_NAME_PREFIX iter_fold +# include + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS +#endif // BOOST_MPL_AUX_ITER_FOLD_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/msvc_type.hpp b/boost/mpl/aux_/msvc_type.hpp new file mode 100644 index 00000000..bea244f3 --- /dev/null +++ b/boost/mpl/aux_/msvc_type.hpp @@ -0,0 +1,62 @@ + +#ifndef BOOST_MPL_AUX_MSVC_TYPE_HPP_INCLUDED +#define BOOST_MPL_AUX_MSVC_TYPE_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2001-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include + +namespace boost { namespace mpl { namespace aux { + +#if defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG) + +template< bool > struct msvc_type_impl +{ + template< typename T > struct result_ + { + typedef typename T::type type; + }; +}; + +template<> struct msvc_type_impl +{ + template< typename T > struct result_ + { + typedef result_ type; + }; +}; + +template< typename T > struct msvc_type + : msvc_type_impl< is_msvc_eti_arg::value > + ::template result_ +{ +}; + +#else // BOOST_MPL_CFG_MSVC_70_ETI_BUG + +template< typename T > struct msvc_type +{ + typedef typename T::type type; +}; + +template<> struct msvc_type +{ + typedef int type; +}; + +#endif + +}}} + +#endif // BOOST_MPL_AUX_MSVC_TYPE_HPP_INCLUDED diff --git a/boost/mpl/aux_/push_back_impl.hpp b/boost/mpl/aux_/push_back_impl.hpp new file mode 100644 index 00000000..27e7a604 --- /dev/null +++ b/boost/mpl/aux_/push_back_impl.hpp @@ -0,0 +1,70 @@ + +#ifndef BOOST_MPL_AUX_PUSH_BACK_IMPL_HPP_INCLUDED +#define BOOST_MPL_AUX_PUSH_BACK_IMPL_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2008 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { namespace mpl { + +struct has_push_back_arg {}; + +// agurt 05/feb/04: no default implementation; the stub definition is needed +// to enable the default 'has_push_back' implementation below +template< typename Tag > +struct push_back_impl +{ + template< typename Sequence, typename T > struct apply + { + // should be instantiated only in the context of 'has_push_back_impl'; + // if you've got an assert here, you are requesting a 'push_back' + // specialization that doesn't exist. + BOOST_MPL_ASSERT_MSG( + ( boost::is_same< T, has_push_back_arg >::value ) + , REQUESTED_PUSH_BACK_SPECIALIZATION_FOR_SEQUENCE_DOES_NOT_EXIST + , ( Sequence ) + ); + }; +}; + +template< typename Tag > +struct has_push_back_impl +{ + template< typename Seq > struct apply +#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING) + : aux::has_type< push_back< Seq, has_push_back_arg > > + { +#else + { + typedef aux::has_type< push_back< Seq, has_push_back_arg > > type; + BOOST_STATIC_CONSTANT(bool, value = + (aux::has_type< push_back< Seq, has_push_back_arg > >::value) + ); +#endif + }; +}; + +BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(2, push_back_impl) +BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1, has_push_back_impl) + +}} + +#endif // BOOST_MPL_AUX_PUSH_BACK_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/push_front_impl.hpp b/boost/mpl/aux_/push_front_impl.hpp new file mode 100644 index 00000000..5b83ee76 --- /dev/null +++ b/boost/mpl/aux_/push_front_impl.hpp @@ -0,0 +1,71 @@ + +#ifndef BOOST_MPL_AUX_PUSH_FRONT_IMPL_HPP_INCLUDED +#define BOOST_MPL_AUX_PUSH_FRONT_IMPL_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2008 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { namespace mpl { + +struct has_push_front_arg {}; + +// agurt 05/feb/04: no default implementation; the stub definition is needed +// to enable the default 'has_push_front' implementation below + +template< typename Tag > +struct push_front_impl +{ + template< typename Sequence, typename T > struct apply + { + // should be instantiated only in the context of 'has_push_front_impl'; + // if you've got an assert here, you are requesting a 'push_front' + // specialization that doesn't exist. + BOOST_MPL_ASSERT_MSG( + ( boost::is_same< T, has_push_front_arg >::value ) + , REQUESTED_PUSH_FRONT_SPECIALIZATION_FOR_SEQUENCE_DOES_NOT_EXIST + , ( Sequence ) + ); + }; +}; + +template< typename Tag > +struct has_push_front_impl +{ + template< typename Seq > struct apply +#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING) + : aux::has_type< push_front< Seq, has_push_front_arg > > + { +#else + { + typedef aux::has_type< push_front< Seq, has_push_front_arg > > type; + BOOST_STATIC_CONSTANT(bool, value = + (aux::has_type< push_front< Seq, has_push_front_arg > >::value) + ); +#endif + }; +}; + +BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(2, push_front_impl) +BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1, has_push_front_impl) + +}} + +#endif // BOOST_MPL_AUX_PUSH_FRONT_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/reverse_fold_impl.hpp b/boost/mpl/aux_/reverse_fold_impl.hpp new file mode 100644 index 00000000..a27a35fa --- /dev/null +++ b/boost/mpl/aux_/reverse_fold_impl.hpp @@ -0,0 +1,44 @@ + +#ifndef BOOST_MPL_AUX_REVERSE_FOLD_IMPL_HPP_INCLUDED +#define BOOST_MPL_AUX_REVERSE_FOLD_IMPL_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +# include +# include +# include +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + || defined(BOOST_MPL_CFG_NO_NONTYPE_TEMPLATE_PARTIAL_SPEC) +# include +# include +# endif +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER reverse_fold_impl.hpp +# include + +#else + +# define AUX778076_FOLD_IMPL_OP(iter) typename deref::type +# define AUX778076_FOLD_IMPL_NAME_PREFIX reverse_fold +# include + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS +#endif // BOOST_MPL_AUX_REVERSE_FOLD_IMPL_HPP_INCLUDED diff --git a/boost/mpl/aux_/reverse_fold_impl_body.hpp b/boost/mpl/aux_/reverse_fold_impl_body.hpp new file mode 100644 index 00000000..0f800106 --- /dev/null +++ b/boost/mpl/aux_/reverse_fold_impl_body.hpp @@ -0,0 +1,412 @@ + +// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION! + +#if !defined(BOOST_PP_IS_ITERATING) + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +# include +# include +# include +# include + +# include +# include +# include +# include +# include + +// local macros, #undef-ined at the end of the header + +# define AUX778076_ITER_FOLD_FORWARD_STEP(unused, n_, unused2) \ + typedef typename apply2< \ + ForwardOp \ + , BOOST_PP_CAT(fwd_state,n_) \ + , AUX778076_FOLD_IMPL_OP(BOOST_PP_CAT(iter,n_)) \ + >::type BOOST_PP_CAT(fwd_state,BOOST_PP_INC(n_)); \ + typedef typename mpl::next::type \ + BOOST_PP_CAT(iter,BOOST_PP_INC(n_)); \ + /**/ + +# define AUX778076_ITER_FOLD_BACKWARD_STEP_FUNC(n_) \ + typedef typename apply2< \ + BackwardOp \ + , BOOST_PP_CAT(bkwd_state,n_) \ + , AUX778076_FOLD_IMPL_OP(BOOST_PP_CAT(iter,BOOST_PP_DEC(n_))) \ + >::type BOOST_PP_CAT(bkwd_state,BOOST_PP_DEC(n_)); \ + /**/ + +# define AUX778076_ITER_FOLD_BACKWARD_STEP(unused, n_, j) \ + AUX778076_ITER_FOLD_BACKWARD_STEP_FUNC( \ + BOOST_PP_SUB_D(1,j,n_) \ + ) \ + /**/ + +# define AUX778076_FIRST_BACKWARD_STATE_TYPEDEF(n_) \ + typedef typename nested_chunk::state BOOST_PP_CAT(bkwd_state,n_); + /**/ + +# define AUX778076_FOLD_IMPL_NAME \ + BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_impl) \ + /**/ + +# define AUX778076_FOLD_CHUNK_NAME \ + BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_chunk) \ + /**/ + +namespace boost { namespace mpl { namespace aux { + +/// forward declaration +template< + BOOST_MPL_AUX_NTTP_DECL(long, N) + , typename First + , typename Last + , typename State + , typename BackwardOp + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME; + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_MPL_CFG_NO_NONTYPE_TEMPLATE_PARTIAL_SPEC) + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(0, BOOST_MPL_LIMIT_UNROLLING, )) +# include BOOST_PP_ITERATE() + +// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING +template< + BOOST_MPL_AUX_NTTP_DECL(long, N) + , typename First + , typename Last + , typename State + , typename BackwardOp + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME +{ + typedef First iter0; + typedef State fwd_state0; + + BOOST_MPL_PP_REPEAT( + BOOST_MPL_LIMIT_UNROLLING + , AUX778076_ITER_FOLD_FORWARD_STEP + , unused + ) + + typedef AUX778076_FOLD_IMPL_NAME< + ( (N - BOOST_MPL_LIMIT_UNROLLING) < 0 ? 0 : N - BOOST_MPL_LIMIT_UNROLLING ) + , BOOST_PP_CAT(iter,BOOST_MPL_LIMIT_UNROLLING) + , Last + , BOOST_PP_CAT(fwd_state,BOOST_MPL_LIMIT_UNROLLING) + , BackwardOp + , ForwardOp + > nested_chunk; + + AUX778076_FIRST_BACKWARD_STATE_TYPEDEF(BOOST_MPL_LIMIT_UNROLLING) + + BOOST_MPL_PP_REPEAT( + BOOST_MPL_LIMIT_UNROLLING + , AUX778076_ITER_FOLD_BACKWARD_STEP + , BOOST_MPL_LIMIT_UNROLLING + ) + + typedef bkwd_state0 state; + typedef typename nested_chunk::iterator iterator; +}; + +// fallback implementation for sequences of unknown size +template< + typename First + , typename Last + , typename State + , typename BackwardOp + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME<-1,First,Last,State,BackwardOp,ForwardOp> +{ + typedef AUX778076_FOLD_IMPL_NAME< + -1 + , typename mpl::next::type + , Last + , typename apply2::type + , BackwardOp + , ForwardOp + > nested_step; + + typedef typename apply2< + BackwardOp + , typename nested_step::state + , AUX778076_FOLD_IMPL_OP(First) + >::type state; + + typedef typename nested_step::iterator iterator; +}; + +template< + typename Last + , typename State + , typename BackwardOp + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME<-1,Last,Last,State,BackwardOp,ForwardOp> +{ + typedef State state; + typedef Last iterator; +}; + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +template< BOOST_MPL_AUX_NTTP_DECL(long, N) > +struct AUX778076_FOLD_CHUNK_NAME; + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(0, BOOST_MPL_LIMIT_UNROLLING, )) +# include BOOST_PP_ITERATE() + +// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING +template< BOOST_MPL_AUX_NTTP_DECL(long, N) > +struct AUX778076_FOLD_CHUNK_NAME +{ + template< + typename First + , typename Last + , typename State + , typename BackwardOp + , typename ForwardOp + > + struct result_ + { + typedef First iter0; + typedef State fwd_state0; + + BOOST_MPL_PP_REPEAT( + BOOST_MPL_LIMIT_UNROLLING + , AUX778076_ITER_FOLD_FORWARD_STEP + , unused + ) + + typedef AUX778076_FOLD_IMPL_NAME< + ( (N - BOOST_MPL_LIMIT_UNROLLING) < 0 ? 0 : N - BOOST_MPL_LIMIT_UNROLLING ) + , BOOST_PP_CAT(iter,BOOST_MPL_LIMIT_UNROLLING) + , Last + , BOOST_PP_CAT(fwd_state,BOOST_MPL_LIMIT_UNROLLING) + , BackwardOp + , ForwardOp + > nested_chunk; + + AUX778076_FIRST_BACKWARD_STATE_TYPEDEF(BOOST_MPL_LIMIT_UNROLLING) + + BOOST_MPL_PP_REPEAT( + BOOST_MPL_LIMIT_UNROLLING + , AUX778076_ITER_FOLD_BACKWARD_STEP + , BOOST_MPL_LIMIT_UNROLLING + ) + + typedef bkwd_state0 state; + typedef typename nested_chunk::iterator iterator; + }; +}; + +// fallback implementation for sequences of unknown size +template< + typename First + , typename Last + , typename State + , typename BackwardOp + , typename ForwardOp + > +struct BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_step); + +template< + typename Last + , typename State + > +struct BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_null_step) +{ + typedef Last iterator; + typedef State state; +}; + +template<> +struct AUX778076_FOLD_CHUNK_NAME<-1> +{ + template< + typename First + , typename Last + , typename State + , typename BackwardOp + , typename ForwardOp + > + struct result_ + { + typedef typename if_< + typename is_same::type + , BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_null_step) + , BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_step) + >::type res_; + + typedef typename res_::state state; + typedef typename res_::iterator iterator; + }; + +#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) + /// ETI workaround + template<> struct result_ + { + typedef int state; + typedef int iterator; + }; +#endif +}; + +template< + typename First + , typename Last + , typename State + , typename BackwardOp + , typename ForwardOp + > +struct BOOST_PP_CAT(AUX778076_FOLD_IMPL_NAME_PREFIX,_step) +{ + typedef AUX778076_FOLD_CHUNK_NAME<-1>::template result_< + typename mpl::next::type + , Last + , typename apply2::type + , BackwardOp + , ForwardOp + > nested_step; + + typedef typename apply2< + BackwardOp + , typename nested_step::state + , AUX778076_FOLD_IMPL_OP(First) + >::type state; + + typedef typename nested_step::iterator iterator; +}; + +template< + BOOST_MPL_AUX_NTTP_DECL(long, N) + , typename First + , typename Last + , typename State + , typename BackwardOp + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME + : AUX778076_FOLD_CHUNK_NAME + ::template result_ +{ +}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +}}} + +# undef AUX778076_FIRST_BACKWARD_STATE_TYPEDEF +# undef AUX778076_ITER_FOLD_BACKWARD_STEP +# undef AUX778076_ITER_FOLD_BACKWARD_STEP_FUNC +# undef AUX778076_ITER_FOLD_FORWARD_STEP + +#undef AUX778076_FOLD_IMPL_OP +#undef AUX778076_FOLD_IMPL_NAME_PREFIX + +///// iteration + +#else + +# define n_ BOOST_PP_FRAME_ITERATION(1) + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_MPL_CFG_NO_NONTYPE_TEMPLATE_PARTIAL_SPEC) + +template< + typename First + , typename Last + , typename State + , typename BackwardOp + , typename ForwardOp + > +struct AUX778076_FOLD_IMPL_NAME +{ + typedef First iter0; + typedef State fwd_state0; + + BOOST_MPL_PP_REPEAT( + n_ + , AUX778076_ITER_FOLD_FORWARD_STEP + , unused + ) + + typedef BOOST_PP_CAT(fwd_state,n_) BOOST_PP_CAT(bkwd_state,n_); + + BOOST_MPL_PP_REPEAT( + n_ + , AUX778076_ITER_FOLD_BACKWARD_STEP + , n_ + ) + + typedef bkwd_state0 state; + typedef BOOST_PP_CAT(iter,n_) iterator; +}; + +#else + +template<> struct AUX778076_FOLD_CHUNK_NAME +{ + template< + typename First + , typename Last + , typename State + , typename BackwardOp + , typename ForwardOp + > + struct result_ + { + typedef First iter0; + typedef State fwd_state0; + + BOOST_MPL_PP_REPEAT( + n_ + , AUX778076_ITER_FOLD_FORWARD_STEP + , unused + ) + + typedef BOOST_PP_CAT(fwd_state,n_) BOOST_PP_CAT(bkwd_state,n_); + + BOOST_MPL_PP_REPEAT( + n_ + , AUX778076_ITER_FOLD_BACKWARD_STEP + , n_ + ) + + typedef bkwd_state0 state; + typedef BOOST_PP_CAT(iter,n_) iterator; + }; + +#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) + /// ETI workaround + template<> struct result_ + { + typedef int state; + typedef int iterator; + }; +#endif +}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +# undef n_ + +#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/aux_/sequence_wrapper.hpp b/boost/mpl/aux_/sequence_wrapper.hpp new file mode 100644 index 00000000..3f5e5530 --- /dev/null +++ b/boost/mpl/aux_/sequence_wrapper.hpp @@ -0,0 +1,292 @@ + +// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION + +#if !defined(BOOST_PP_IS_ITERATING) + +///// header body + +// Copyright Aleksey Gurtovoy 2000-2008 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +# include +# include +# include + +# include +# include +# include +# include +# include +# include +# include +# include + +#if defined(BOOST_MPL_PREPROCESSING_MODE) +# undef LONG_MAX +#endif + +namespace boost { namespace mpl { + +#if !defined(AUX778076_SEQUENCE_BASE_NAME) +# define AUX778076_SEQUENCE_BASE_NAME AUX778076_SEQUENCE_NAME +#endif + +#if !defined(AUX778076_SEQUENCE_INTEGRAL_WRAPPER) + +# define AUX778076_SEQUENCE_PARAM_NAME T +# define AUX778076_SEQUENCE_TEMPLATE_PARAM typename T +# define AUX778076_SEQUENCE_DEFAULT na + +# define AUX778076_SEQUENCE_NAME_N(n) \ + BOOST_PP_CAT(AUX778076_SEQUENCE_BASE_NAME,n) \ + /**/ + +# define AUX778076_SEQUENCE_PARAMS() \ + BOOST_PP_ENUM_PARAMS( \ + AUX778076_SEQUENCE_LIMIT \ + , AUX778076_SEQUENCE_TEMPLATE_PARAM \ + ) \ + /**/ + +# define AUX778076_SEQUENCE_ARGS() \ + BOOST_PP_ENUM_PARAMS( \ + AUX778076_SEQUENCE_LIMIT \ + , T \ + ) \ + /**/ + +# define AUX778076_SEQUENCE_DEFAULT_PARAMS() \ + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( \ + AUX778076_SEQUENCE_LIMIT \ + , AUX778076_SEQUENCE_TEMPLATE_PARAM \ + , AUX778076_SEQUENCE_DEFAULT \ + ) \ + /**/ + +# define AUX778076_SEQUENCE_N_PARAMS(n) \ + BOOST_PP_ENUM_PARAMS(n, AUX778076_SEQUENCE_TEMPLATE_PARAM) \ + /**/ + +# define AUX778076_SEQUENCE_N_ARGS(n) \ + BOOST_PP_ENUM_PARAMS(n, T) \ + /**/ + +# define AUX778076_SEQUENCE_N_PARTIAL_SPEC_ARGS(n) \ + BOOST_PP_ENUM_PARAMS(n, T) \ + BOOST_PP_COMMA_IF(n) \ + BOOST_PP_ENUM( \ + BOOST_PP_SUB_D(1,AUX778076_SEQUENCE_LIMIT,n) \ + , BOOST_PP_TUPLE_ELEM_3_2 \ + , AUX778076_SEQUENCE_DEFAULT \ + ) \ + /**/ + +#else // AUX778076_SEQUENCE_INTEGRAL_WRAPPER + +# define AUX778076_SEQUENCE_PARAM_NAME C +# define AUX778076_SEQUENCE_TEMPLATE_PARAM BOOST_MPL_AUX_NTTP_DECL(long, C) +# define AUX778076_SEQUENCE_DEFAULT LONG_MAX + +# define AUX778076_SEQUENCE_PARAMS() \ + typename T, BOOST_PP_ENUM_PARAMS( \ + AUX778076_SEQUENCE_LIMIT \ + , AUX778076_SEQUENCE_TEMPLATE_PARAM \ + ) \ + /**/ + +# define AUX778076_SEQUENCE_ARGS() \ + T, BOOST_PP_ENUM_PARAMS( \ + AUX778076_SEQUENCE_LIMIT \ + , C \ + ) \ + /**/ + +# define AUX778076_SEQUENCE_DEFAULT_PARAMS() \ + typename T, \ + BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( \ + AUX778076_SEQUENCE_LIMIT \ + , AUX778076_SEQUENCE_TEMPLATE_PARAM \ + , AUX778076_SEQUENCE_DEFAULT \ + ) \ + /**/ + +# define AUX778076_SEQUENCE_N_PARAMS(n) \ + typename T BOOST_PP_COMMA_IF(n) \ + BOOST_PP_ENUM_PARAMS(n, AUX778076_SEQUENCE_TEMPLATE_PARAM) \ + /**/ + +# if !defined(AUX778076_SEQUENCE_CONVERT_CN_TO) +# define AUX778076_SEQUENCE_CONVERT_CN_TO(z,n,TARGET) BOOST_PP_CAT(C,n) +# endif + +# define AUX778076_SEQUENCE_N_ARGS(n) \ + T BOOST_PP_COMMA_IF(n) \ + BOOST_PP_ENUM(n,AUX778076_SEQUENCE_CONVERT_CN_TO,T) \ + /**/ + +# define AUX778076_SEQUENCE_N_PARTIAL_SPEC_ARGS(n) \ + T, BOOST_PP_ENUM_PARAMS(n, C) \ + BOOST_PP_COMMA_IF(n) \ + BOOST_PP_ENUM( \ + BOOST_PP_SUB_D(1,AUX778076_SEQUENCE_LIMIT,n) \ + , BOOST_PP_TUPLE_ELEM_3_2 \ + , AUX778076_SEQUENCE_DEFAULT \ + ) \ + /**/ + +#endif // AUX778076_SEQUENCE_INTEGRAL_WRAPPER + + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +// forward declaration +template< + AUX778076_SEQUENCE_DEFAULT_PARAMS() + > +struct AUX778076_SEQUENCE_NAME; +#else +namespace aux { +template< BOOST_MPL_AUX_NTTP_DECL(int, N) > +struct BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_chooser); +} +#endif + +#define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(0, AUX778076_SEQUENCE_LIMIT, )) +#include BOOST_PP_ITERATE() + +// real C++ version is already taken care of +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +namespace aux { +// ???_count_args +#define AUX778076_COUNT_ARGS_PREFIX AUX778076_SEQUENCE_NAME +#define AUX778076_COUNT_ARGS_DEFAULT AUX778076_SEQUENCE_DEFAULT +#define AUX778076_COUNT_ARGS_PARAM_NAME AUX778076_SEQUENCE_PARAM_NAME +#define AUX778076_COUNT_ARGS_TEMPLATE_PARAM AUX778076_SEQUENCE_TEMPLATE_PARAM +#define AUX778076_COUNT_ARGS_ARITY AUX778076_SEQUENCE_LIMIT +#define AUX778076_COUNT_ARGS_USE_STANDARD_PP_PRIMITIVES +#include + +template< + AUX778076_SEQUENCE_PARAMS() + > +struct BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_impl) +{ + typedef aux::BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_count_args)< + BOOST_PP_ENUM_PARAMS(AUX778076_SEQUENCE_LIMIT, AUX778076_SEQUENCE_PARAM_NAME) + > arg_num_; + + typedef typename aux::BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_chooser)< arg_num_::value > + ::template result_< AUX778076_SEQUENCE_ARGS() >::type type; +}; + +} // namespace aux + +template< + AUX778076_SEQUENCE_DEFAULT_PARAMS() + > +struct AUX778076_SEQUENCE_NAME + : aux::BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_impl)< + AUX778076_SEQUENCE_ARGS() + >::type +{ + typedef typename aux::BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_impl)< + AUX778076_SEQUENCE_ARGS() + >::type type; +}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +# undef AUX778076_SEQUENCE_N_PARTIAL_SPEC_ARGS +# undef AUX778076_SEQUENCE_N_ARGS +# undef AUX778076_SEQUENCE_CONVERT_CN_TO +# undef AUX778076_SEQUENCE_N_PARAMS +# undef AUX778076_SEQUENCE_DEFAULT_PARAMS +# undef AUX778076_SEQUENCE_ARGS +# undef AUX778076_SEQUENCE_PARAMS +# undef AUX778076_SEQUENCE_NAME_N +# undef AUX778076_SEQUENCE_DEFAULT +# undef AUX778076_SEQUENCE_TEMPLATE_PARAM +# undef AUX778076_SEQUENCE_PARAM_NAME +# undef AUX778076_SEQUENCE_LIMIT +# undef AUX778076_SEQUENCE_BASE_NAME +# undef AUX778076_SEQUENCE_NAME +# undef AUX778076_SEQUENCE_INTEGRAL_WRAPPER + +}} + +///// iteration + +#else +#define i_ BOOST_PP_FRAME_ITERATION(1) + +# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +#if i_ == AUX778076_SEQUENCE_LIMIT + +/// primary template (not a specialization!) +template< + AUX778076_SEQUENCE_N_PARAMS(i_) + > +struct AUX778076_SEQUENCE_NAME + : AUX778076_SEQUENCE_NAME_N(i_)< AUX778076_SEQUENCE_N_ARGS(i_) > +{ + typedef typename AUX778076_SEQUENCE_NAME_N(i_)< AUX778076_SEQUENCE_N_ARGS(i_) >::type type; +}; + +#else + +template< + AUX778076_SEQUENCE_N_PARAMS(i_) + > +struct AUX778076_SEQUENCE_NAME< AUX778076_SEQUENCE_N_PARTIAL_SPEC_ARGS(i_) > + : AUX778076_SEQUENCE_NAME_N(i_)< AUX778076_SEQUENCE_N_ARGS(i_) > +{ +#if i_ > 0 || defined(AUX778076_SEQUENCE_INTEGRAL_WRAPPER) + typedef typename AUX778076_SEQUENCE_NAME_N(i_)< AUX778076_SEQUENCE_N_ARGS(i_) >::type type; +#else + typedef AUX778076_SEQUENCE_NAME_N(i_)< AUX778076_SEQUENCE_N_ARGS(i_) >::type type; +#endif +}; + +#endif // i_ == AUX778076_SEQUENCE_LIMIT + +# else + +namespace aux { + +template<> +struct BOOST_PP_CAT(AUX778076_SEQUENCE_NAME,_chooser) +{ + template< + AUX778076_SEQUENCE_PARAMS() + > + struct result_ + { +#if i_ > 0 || defined(AUX778076_SEQUENCE_INTEGRAL_WRAPPER) + typedef typename AUX778076_SEQUENCE_NAME_N(i_)< + AUX778076_SEQUENCE_N_ARGS(i_) + >::type type; +#else + typedef AUX778076_SEQUENCE_NAME_N(i_)< + AUX778076_SEQUENCE_N_ARGS(i_) + >::type type; +#endif + }; +}; + +} // namespace aux + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#undef i_ +#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/aux_/traits_lambda_spec.hpp b/boost/mpl/aux_/traits_lambda_spec.hpp new file mode 100644 index 00000000..4a7ff26b --- /dev/null +++ b/boost/mpl/aux_/traits_lambda_spec.hpp @@ -0,0 +1,63 @@ + +#ifndef BOOST_MPL_AUX_TRAITS_LAMBDA_SPEC_HPP_INCLUDED +#define BOOST_MPL_AUX_TRAITS_LAMBDA_SPEC_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2008 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include + +#if !defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT) + +# define BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(i, trait) /**/ + +#elif !defined(BOOST_MPL_CFG_MSVC_ETI_BUG) + +# define BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(i, trait) \ +template<> struct trait \ +{ \ + template< BOOST_MPL_PP_PARAMS(i, typename T) > struct apply \ + { \ + }; \ +}; \ +/**/ + +#else + +# define BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(i, trait) \ +template<> struct trait \ +{ \ + template< BOOST_MPL_PP_PARAMS(i, typename T) > struct apply \ + { \ + }; \ +}; \ +template<> struct trait \ +{ \ + template< BOOST_MPL_PP_PARAMS(i, typename T) > struct apply \ + { \ + typedef int type; \ + }; \ +}; \ +/**/ + +#endif // BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT + + +#define BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(i, trait) \ + BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(i, trait) \ + template<> struct trait {}; \ +/**/ + +#endif // BOOST_MPL_AUX_TRAITS_LAMBDA_SPEC_HPP_INCLUDED diff --git a/boost/mpl/back_fwd.hpp b/boost/mpl/back_fwd.hpp new file mode 100644 index 00000000..119722c3 --- /dev/null +++ b/boost/mpl/back_fwd.hpp @@ -0,0 +1,24 @@ + +#ifndef BOOST_MPL_BACK_FWD_HPP_INCLUDED +#define BOOST_MPL_BACK_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +template< typename Tag > struct back_impl; +template< typename Sequence > struct back; + +}} + +#endif // BOOST_MPL_BACK_FWD_HPP_INCLUDED diff --git a/boost/mpl/back_inserter.hpp b/boost/mpl/back_inserter.hpp new file mode 100644 index 00000000..8fc4083c --- /dev/null +++ b/boost/mpl/back_inserter.hpp @@ -0,0 +1,34 @@ + +#ifndef BOOST_MPL_BACK_INSERTER_HPP_INCLUDED +#define BOOST_MPL_BACK_INSERTER_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2003-2004 +// Copyright David Abrahams 2003-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include + +namespace boost { +namespace mpl { + +template< + typename Sequence + > +struct back_inserter + : inserter< Sequence,push_back<> > +{ +}; + +}} + +#endif // BOOST_MPL_BACK_INSERTER_HPP_INCLUDED diff --git a/boost/mpl/begin_end.hpp b/boost/mpl/begin_end.hpp new file mode 100644 index 00000000..b7074afd --- /dev/null +++ b/boost/mpl/begin_end.hpp @@ -0,0 +1,57 @@ + +#ifndef BOOST_MPL_BEGIN_END_HPP_INCLUDED +#define BOOST_MPL_BEGIN_END_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +// agurt, 13/sep/02: switched from inheritance to typedef; MSVC is more +// happy this way (less ETI-related errors), and it doesn't affect +// anything else +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + > +struct begin +{ + typedef typename sequence_tag::type tag_; + typedef typename begin_impl< tag_ > + ::template apply< Sequence >::type type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,begin,(Sequence)) +}; + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + > +struct end +{ + typedef typename sequence_tag::type tag_; + typedef typename end_impl< tag_ > + ::template apply< Sequence >::type type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,end,(Sequence)) +}; + +BOOST_MPL_AUX_NA_SPEC(1, begin) +BOOST_MPL_AUX_NA_SPEC(1, end) + +}} + +#endif // BOOST_MPL_BEGIN_END_HPP_INCLUDED diff --git a/boost/mpl/begin_end_fwd.hpp b/boost/mpl/begin_end_fwd.hpp new file mode 100644 index 00000000..70ef9efe --- /dev/null +++ b/boost/mpl/begin_end_fwd.hpp @@ -0,0 +1,27 @@ + +#ifndef BOOST_MPL_BEGIN_END_FWD_HPP_INCLUDED +#define BOOST_MPL_BEGIN_END_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +template< typename Tag > struct begin_impl; +template< typename Tag > struct end_impl; + +template< typename Sequence > struct begin; +template< typename Sequence > struct end; + +}} + +#endif // BOOST_MPL_BEGIN_END_FWD_HPP_INCLUDED diff --git a/boost/mpl/bitand.hpp b/boost/mpl/bitand.hpp new file mode 100644 index 00000000..3d759807 --- /dev/null +++ b/boost/mpl/bitand.hpp @@ -0,0 +1,45 @@ + +#ifndef BOOST_MPL_BITAND_HPP_INCLUDED +#define BOOST_MPL_BITAND_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2009 +// Copyright Jaap Suter 2003 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +// agurt, 23/jan/10: workaround a conflict with header's +// macros, see http://tinyurl.com/ycwdxco; 'defined(bitand)' +// has to be checked in a separate condition, otherwise GCC complains +// about 'bitand' being an alternative token +#if defined(_MSC_VER) +#ifndef __GCCXML__ +#if defined(bitand) +# pragma push_macro("bitand") +# undef bitand +# define bitand(x) +#endif +#endif +#endif + +#define AUX778076_OP_NAME bitand_ +#define AUX778076_OP_PREFIX bitand +#define AUX778076_OP_TOKEN & +#include + +#if defined(_MSC_VER) && !defined(__clang__) +#ifndef __GCCXML__ +#if defined(bitand) +# pragma pop_macro("bitand") +#endif +#endif +#endif + +#endif // BOOST_MPL_BITAND_HPP_INCLUDED diff --git a/boost/mpl/clear.hpp b/boost/mpl/clear.hpp new file mode 100644 index 00000000..c6b95edf --- /dev/null +++ b/boost/mpl/clear.hpp @@ -0,0 +1,39 @@ + +#ifndef BOOST_MPL_CLEAR_HPP_INCLUDED +#define BOOST_MPL_CLEAR_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + > +struct clear + : clear_impl< typename sequence_tag::type > + ::template apply< Sequence > +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,clear,(Sequence)) +}; + +BOOST_MPL_AUX_NA_SPEC(1, clear) + +}} + +#endif // BOOST_MPL_CLEAR_HPP_INCLUDED diff --git a/boost/mpl/clear_fwd.hpp b/boost/mpl/clear_fwd.hpp new file mode 100644 index 00000000..d14a1d2b --- /dev/null +++ b/boost/mpl/clear_fwd.hpp @@ -0,0 +1,24 @@ + +#ifndef BOOST_MPL_CLEAR_FWD_HPP_INCLUDED +#define BOOST_MPL_CLEAR_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +template< typename Tag > struct clear_impl; +template< typename Sequence > struct clear; + +}} + +#endif // BOOST_MPL_CLEAR_FWD_HPP_INCLUDED diff --git a/boost/mpl/deref.hpp b/boost/mpl/deref.hpp new file mode 100644 index 00000000..1105ec90 --- /dev/null +++ b/boost/mpl/deref.hpp @@ -0,0 +1,41 @@ + +#ifndef BOOST_MPL_DEREF_HPP_INCLUDED +#define BOOST_MPL_DEREF_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2002-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include + +namespace boost { namespace mpl { + +template< + typename BOOST_MPL_AUX_NA_PARAM(Iterator) + > +struct deref +{ +#if !defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG) + typedef typename Iterator::type type; +#else + typedef typename aux::msvc_type::type type; +#endif + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,deref,(Iterator)) +}; + +BOOST_MPL_AUX_NA_SPEC(1, deref) + +}} + +#endif // BOOST_MPL_DEREF_HPP_INCLUDED diff --git a/boost/mpl/distance.hpp b/boost/mpl/distance.hpp new file mode 100644 index 00000000..95f4f335 --- /dev/null +++ b/boost/mpl/distance.hpp @@ -0,0 +1,78 @@ + +#ifndef BOOST_MPL_DISTANCE_HPP_INCLUDED +#define BOOST_MPL_DISTANCE_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace mpl { + +// default implementation for forward/bidirectional iterators +template< typename Tag > struct distance_impl +{ + template< typename First, typename Last > struct apply +#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING) + : aux::msvc_eti_base< typename iter_fold< + iterator_range + , mpl::long_<0> + , next<> + >::type > + { +#else + { + typedef typename iter_fold< + iterator_range + , mpl::long_<0> + , next<> + >::type type; + + BOOST_STATIC_CONSTANT(long, value = + (iter_fold< + iterator_range + , mpl::long_<0> + , next<> + >::type::value) + ); +#endif + }; +}; + +template< + typename BOOST_MPL_AUX_NA_PARAM(First) + , typename BOOST_MPL_AUX_NA_PARAM(Last) + > +struct distance + : distance_impl< typename tag::type > + ::template apply +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(2, distance, (First, Last)) +}; + +BOOST_MPL_AUX_NA_SPEC(2, distance) + +}} + +#endif // BOOST_MPL_DISTANCE_HPP_INCLUDED diff --git a/boost/mpl/distance_fwd.hpp b/boost/mpl/distance_fwd.hpp new file mode 100644 index 00000000..a69a7c51 --- /dev/null +++ b/boost/mpl/distance_fwd.hpp @@ -0,0 +1,28 @@ + +#ifndef BOOST_MPL_DISTANCE_FWD_HPP_INCLUDED +#define BOOST_MPL_DISTANCE_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include + +namespace boost { namespace mpl { + +BOOST_MPL_AUX_COMMON_NAME_WKND(distance) + +template< typename Tag > struct distance_impl; +template< typename First, typename Last > struct distance; + +}} + +#endif // BOOST_MPL_DISTANCE_FWD_HPP_INCLUDED diff --git a/boost/mpl/empty_fwd.hpp b/boost/mpl/empty_fwd.hpp new file mode 100644 index 00000000..551c9660 --- /dev/null +++ b/boost/mpl/empty_fwd.hpp @@ -0,0 +1,24 @@ + +#ifndef BOOST_MPL_EMPTY_FWD_HPP_INCLUDED +#define BOOST_MPL_EMPTY_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +template< typename Tag > struct empty_impl; +template< typename Sequence > struct empty; + +}} + +#endif // BOOST_MPL_EMPTY_FWD_HPP_INCLUDED diff --git a/boost/mpl/fold.hpp b/boost/mpl/fold.hpp new file mode 100644 index 00000000..0bc67ef3 --- /dev/null +++ b/boost/mpl/fold.hpp @@ -0,0 +1,48 @@ + +#ifndef BOOST_MPL_FOLD_HPP_INCLUDED +#define BOOST_MPL_FOLD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2001-2004 +// Copyright David Abrahams 2001-2002 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + , typename BOOST_MPL_AUX_NA_PARAM(State) + , typename BOOST_MPL_AUX_NA_PARAM(ForwardOp) + > +struct fold +{ + typedef typename aux::fold_impl< + ::boost::mpl::O1_size::value + , typename begin::type + , typename end::type + , State + , ForwardOp + >::state type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(3,fold,(Sequence,State,ForwardOp)) +}; + +BOOST_MPL_AUX_NA_SPEC(3, fold) + +}} + +#endif // BOOST_MPL_FOLD_HPP_INCLUDED diff --git a/boost/mpl/front_fwd.hpp b/boost/mpl/front_fwd.hpp new file mode 100644 index 00000000..f01282a7 --- /dev/null +++ b/boost/mpl/front_fwd.hpp @@ -0,0 +1,24 @@ + +#ifndef BOOST_MPL_FRONT_FWD_HPP_INCLUDED +#define BOOST_MPL_FRONT_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +template< typename Tag > struct front_impl; +template< typename Sequence > struct front; + +}} + +#endif // BOOST_MPL_FRONT_FWD_HPP_INCLUDED diff --git a/boost/mpl/front_inserter.hpp b/boost/mpl/front_inserter.hpp new file mode 100644 index 00000000..0a6b197e --- /dev/null +++ b/boost/mpl/front_inserter.hpp @@ -0,0 +1,33 @@ + +#ifndef BOOST_MPL_FRONT_INSERTER_HPP_INCLUDED +#define BOOST_MPL_FRONT_INSERTER_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2003-2004 +// Copyright David Abrahams 2003-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include + +namespace boost { namespace mpl { + +template< + typename Sequence + > +struct front_inserter + : inserter< Sequence,push_front<> > +{ +}; + +}} + +#endif // BOOST_MPL_FRONT_INSERTER_HPP_INCLUDED diff --git a/boost/mpl/inserter.hpp b/boost/mpl/inserter.hpp new file mode 100644 index 00000000..964df7f6 --- /dev/null +++ b/boost/mpl/inserter.hpp @@ -0,0 +1,32 @@ + +#ifndef BOOST_MPL_INSERTER_HPP_INCLUDED +#define BOOST_MPL_INSERTER_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2003-2004 +// Copyright David Abrahams 2003-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +template< + typename Sequence + , typename Operation + > +struct inserter +{ + typedef Sequence state; + typedef Operation operation; +}; + +}} + +#endif // BOOST_MPL_INSERTER_HPP_INCLUDED diff --git a/boost/mpl/is_sequence.hpp b/boost/mpl/is_sequence.hpp new file mode 100644 index 00000000..68e036fa --- /dev/null +++ b/boost/mpl/is_sequence.hpp @@ -0,0 +1,112 @@ + +#ifndef BOOST_MPL_IS_SEQUENCE_HPP_INCLUDED +#define BOOST_MPL_IS_SEQUENCE_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2002-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) +# include +#elif BOOST_WORKAROUND(BOOST_MSVC, == 1300) +# include +#endif + +#include + +namespace boost { namespace mpl { + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + +namespace aux { + +// agurt, 11/jun/03: +// MSVC 6.5/7.0 fails if 'has_begin' is instantiated on a class type that has a +// 'begin' member that doesn't name a type; e.g. 'has_begin< std::vector >' +// would fail; requiring 'T' to have _both_ 'tag' and 'begin' members workarounds +// the issue for most real-world cases +template< typename T > struct is_sequence_impl + : and_< + identity< aux::has_tag > + , identity< aux::has_begin > + > +{ +}; + +} // namespace aux + +template< + typename BOOST_MPL_AUX_NA_PARAM(T) + > +struct is_sequence + : if_< +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) + aux::msvc_is_class +#else + boost::is_class +#endif + , aux::is_sequence_impl + , bool_ + >::type +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1, is_sequence, (T)) +}; + +#elif defined(BOOST_MPL_CFG_NO_HAS_XXX) + +template< + typename BOOST_MPL_AUX_NA_PARAM(T) + > +struct is_sequence + : bool_ +{ +}; + +#else + +template< + typename BOOST_MPL_AUX_NA_PARAM(T) + > +struct is_sequence + : not_< is_same< typename begin::type, void_ > > +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1, is_sequence, (T)) +}; + +#endif // BOOST_MSVC + +#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) +template<> struct is_sequence + : bool_ +{ +}; +#endif + +BOOST_MPL_AUX_NA_SPEC_NO_ETI(1, is_sequence) + +}} + +#endif // BOOST_MPL_IS_SEQUENCE_HPP_INCLUDED diff --git a/boost/mpl/iter_fold.hpp b/boost/mpl/iter_fold.hpp new file mode 100644 index 00000000..1b56b790 --- /dev/null +++ b/boost/mpl/iter_fold.hpp @@ -0,0 +1,49 @@ + +#ifndef BOOST_MPL_ITER_FOLD_HPP_INCLUDED +#define BOOST_MPL_ITER_FOLD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2001-2004 +// Copyright David Abrahams 2001-2002 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + , typename BOOST_MPL_AUX_NA_PARAM(State) + , typename BOOST_MPL_AUX_NA_PARAM(ForwardOp) + > +struct iter_fold +{ + typedef typename aux::iter_fold_impl< + ::boost::mpl::O1_size::value + , typename begin::type + , typename end::type + , State + , typename lambda::type + >::state type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(3,iter_fold,(Sequence,State,ForwardOp)) +}; + +BOOST_MPL_AUX_NA_SPEC(3, iter_fold) + +}} + +#endif // BOOST_MPL_ITER_FOLD_HPP_INCLUDED diff --git a/boost/mpl/iterator_category.hpp b/boost/mpl/iterator_category.hpp new file mode 100644 index 00000000..d5ea4afe --- /dev/null +++ b/boost/mpl/iterator_category.hpp @@ -0,0 +1,35 @@ + +#ifndef BOOST_MPL_ITERATOR_CATEGORY_HPP_INCLUDED +#define BOOST_MPL_ITERATOR_CATEGORY_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include + +namespace boost { namespace mpl { + +template< + typename BOOST_MPL_AUX_NA_PARAM(Iterator) + > +struct iterator_category +{ + typedef typename Iterator::category type; + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,iterator_category,(Iterator)) +}; + +BOOST_MPL_AUX_NA_SPEC(1, iterator_category) + +}} + +#endif // BOOST_MPL_ITERATOR_CATEGORY_HPP_INCLUDED diff --git a/boost/mpl/iterator_range.hpp b/boost/mpl/iterator_range.hpp new file mode 100644 index 00000000..a637e224 --- /dev/null +++ b/boost/mpl/iterator_range.hpp @@ -0,0 +1,42 @@ + +#ifndef BOOST_MPL_ITERATOR_RANGE_HPP_INCLUDED +#define BOOST_MPL_ITERATOR_RANGE_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2001-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include + +namespace boost { namespace mpl { + +struct iterator_range_tag; + +template< + typename BOOST_MPL_AUX_NA_PARAM(First) + , typename BOOST_MPL_AUX_NA_PARAM(Last) + > +struct iterator_range +{ + typedef iterator_range_tag tag; + typedef iterator_range type; + typedef First begin; + typedef Last end; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,iterator_range,(First,Last)) +}; + +BOOST_MPL_AUX_NA_SPEC(2, iterator_range) + +}} + +#endif // BOOST_MPL_ITERATOR_RANGE_HPP_INCLUDED diff --git a/boost/mpl/iterator_tags.hpp b/boost/mpl/iterator_tags.hpp new file mode 100644 index 00000000..7c3116ab --- /dev/null +++ b/boost/mpl/iterator_tags.hpp @@ -0,0 +1,27 @@ + +#ifndef BOOST_MPL_ITERATOR_TAG_HPP_INCLUDED +#define BOOST_MPL_ITERATOR_TAG_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include + +namespace boost { namespace mpl { + +struct forward_iterator_tag : int_<0> { typedef forward_iterator_tag type; }; +struct bidirectional_iterator_tag : int_<1> { typedef bidirectional_iterator_tag type; }; +struct random_access_iterator_tag : int_<2> { typedef random_access_iterator_tag type; }; + +}} + +#endif // BOOST_MPL_ITERATOR_TAG_HPP_INCLUDED diff --git a/boost/mpl/limits/unrolling.hpp b/boost/mpl/limits/unrolling.hpp new file mode 100644 index 00000000..6dba9422 --- /dev/null +++ b/boost/mpl/limits/unrolling.hpp @@ -0,0 +1,21 @@ + +#ifndef BOOST_MPL_LIMITS_UNROLLING_HPP_INCLUDED +#define BOOST_MPL_LIMITS_UNROLLING_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_LIMIT_UNROLLING) +# define BOOST_MPL_LIMIT_UNROLLING 4 +#endif + +#endif // BOOST_MPL_LIMITS_UNROLLING_HPP_INCLUDED diff --git a/boost/mpl/limits/vector.hpp b/boost/mpl/limits/vector.hpp new file mode 100644 index 00000000..90075891 --- /dev/null +++ b/boost/mpl/limits/vector.hpp @@ -0,0 +1,21 @@ + +#ifndef BOOST_MPL_LIMITS_VECTOR_HPP_INCLUDED +#define BOOST_MPL_LIMITS_VECTOR_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_LIMIT_VECTOR_SIZE) +# define BOOST_MPL_LIMIT_VECTOR_SIZE 20 +#endif + +#endif // BOOST_MPL_LIMITS_VECTOR_HPP_INCLUDED diff --git a/boost/mpl/long.hpp b/boost/mpl/long.hpp new file mode 100644 index 00000000..c4552673 --- /dev/null +++ b/boost/mpl/long.hpp @@ -0,0 +1,22 @@ + +#ifndef BOOST_MPL_LONG_HPP_INCLUDED +#define BOOST_MPL_LONG_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include + +#define AUX_WRAPPER_VALUE_TYPE long +#include + +#endif // BOOST_MPL_LONG_HPP_INCLUDED diff --git a/boost/mpl/long_fwd.hpp b/boost/mpl/long_fwd.hpp new file mode 100644 index 00000000..5f62f2b8 --- /dev/null +++ b/boost/mpl/long_fwd.hpp @@ -0,0 +1,27 @@ + +#ifndef BOOST_MPL_LONG_FWD_HPP_INCLUDED +#define BOOST_MPL_LONG_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include + +BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN + +template< BOOST_MPL_AUX_NTTP_DECL(long, N) > struct long_; + +BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE +BOOST_MPL_AUX_ADL_BARRIER_DECL(long_) + +#endif // BOOST_MPL_LONG_FWD_HPP_INCLUDED diff --git a/boost/mpl/min_max.hpp b/boost/mpl/min_max.hpp new file mode 100644 index 00000000..77545cd3 --- /dev/null +++ b/boost/mpl/min_max.hpp @@ -0,0 +1,46 @@ + +#ifndef BOOST_MPL_MIN_MAX_HPP_INCLUDED +#define BOOST_MPL_MIN_MAX_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2008 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include + +namespace boost { namespace mpl { + +template< + typename BOOST_MPL_AUX_NA_PARAM(N1) + , typename BOOST_MPL_AUX_NA_PARAM(N2) + > +struct min + : if_< less,N1,N2 > +{ +}; + +template< + typename BOOST_MPL_AUX_NA_PARAM(N1) + , typename BOOST_MPL_AUX_NA_PARAM(N2) + > +struct max + : if_< less,N2,N1 > +{ +}; + +BOOST_MPL_AUX_NA_SPEC(2, min) +BOOST_MPL_AUX_NA_SPEC(2, max) + +}} + +#endif // BOOST_MPL_MIN_MAX_HPP_INCLUDED diff --git a/boost/mpl/minus.hpp b/boost/mpl/minus.hpp new file mode 100644 index 00000000..9f29f74b --- /dev/null +++ b/boost/mpl/minus.hpp @@ -0,0 +1,21 @@ + +#ifndef BOOST_MPL_MINUS_HPP_INCLUDED +#define BOOST_MPL_MINUS_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#define AUX778076_OP_NAME minus +#define AUX778076_OP_TOKEN - +#include + +#endif // BOOST_MPL_MINUS_HPP_INCLUDED diff --git a/boost/mpl/negate.hpp b/boost/mpl/negate.hpp new file mode 100644 index 00000000..d6aa0654 --- /dev/null +++ b/boost/mpl/negate.hpp @@ -0,0 +1,81 @@ + +#ifndef BOOST_MPL_NEGATE_HPP_INCLUDED +#define BOOST_MPL_NEGATE_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +template< typename Tag > struct negate_impl; + +template< typename T > struct negate_tag +{ + typedef typename T::tag type; +}; + +template< + typename BOOST_MPL_AUX_NA_PARAM(N) + > +struct negate +#if !defined(BOOST_MPL_CFG_MSVC_ETI_BUG) + : negate_impl< + typename negate_tag::type + >::template apply::type +#else + : aux::msvc_eti_base< typename apply_wrap1< + negate_impl< typename negate_tag::type > + , N + >::type >::type +#endif +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1, negate, (N)) +}; + +BOOST_MPL_AUX_NA_SPEC(1, negate) + + +#if defined(BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC) +namespace aux { +template< typename T, T n > struct negate_wknd +{ + BOOST_STATIC_CONSTANT(T, value = -n); + typedef integral_c type; +}; +} +#endif + +template<> +struct negate_impl +{ +#if defined(BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC) + template< typename N > struct apply + : aux::negate_wknd< typename N::value_type, N::value > +#else + template< typename N > struct apply + : integral_c< typename N::value_type, (-N::value) > +#endif + { + }; +}; + +}} + +#endif // BOOST_MPL_NEGATE_HPP_INCLUDED diff --git a/boost/mpl/pair.hpp b/boost/mpl/pair.hpp new file mode 100644 index 00000000..67c01d73 --- /dev/null +++ b/boost/mpl/pair.hpp @@ -0,0 +1,70 @@ + +#ifndef BOOST_MPL_PAIR_HPP_INCLUDED +#define BOOST_MPL_PAIR_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2001-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include + +namespace boost { namespace mpl { + +template< + typename BOOST_MPL_AUX_NA_PARAM(T1) + , typename BOOST_MPL_AUX_NA_PARAM(T2) + > +struct pair +{ + typedef pair type; + typedef T1 first; + typedef T2 second; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,pair,(T1,T2)) +}; + +template< + typename BOOST_MPL_AUX_NA_PARAM(P) + > +struct first +{ +#if !defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG) + typedef typename P::first type; +#else + typedef typename aux::msvc_eti_base

::first type; +#endif + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,first,(P)) +}; + +template< + typename BOOST_MPL_AUX_NA_PARAM(P) + > +struct second +{ +#if !defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG) + typedef typename P::second type; +#else + typedef typename aux::msvc_eti_base

::second type; +#endif + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,second,(P)) +}; + + +BOOST_MPL_AUX_NA_SPEC_NO_ETI(2, pair) +BOOST_MPL_AUX_NA_SPEC(1, first) +BOOST_MPL_AUX_NA_SPEC(1, second) + +}} + +#endif // BOOST_MPL_PAIR_HPP_INCLUDED diff --git a/boost/mpl/pair_view.hpp b/boost/mpl/pair_view.hpp new file mode 100644 index 00000000..a72cf928 --- /dev/null +++ b/boost/mpl/pair_view.hpp @@ -0,0 +1,169 @@ + +#ifndef BOOST_MPL_PAIR_VIEW_HPP_INCLUDED +#define BOOST_MPL_PAIR_VIEW_HPP_INCLUDED + +// Copyright David Abrahams 2003-2004 +// Copyright Aleksey Gurtovoy 2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +namespace aux { +struct pair_iter_tag; + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template< typename Iter1, typename Iter2, typename Category > +struct pair_iter; + +template< typename Category > struct prior_pair_iter +{ + template< typename Iter1, typename Iter2 > struct apply + { + typedef typename mpl::prior::type i1_; + typedef typename mpl::prior::type i2_; + typedef pair_iter type; + }; +}; + +template<> struct prior_pair_iter +{ + template< typename Iter1, typename Iter2 > struct apply + { + typedef pair_iter type; + }; +}; + +#endif +} + +template< + typename Iter1 + , typename Iter2 + , typename Category + > +struct pair_iter +{ + typedef aux::pair_iter_tag tag; + typedef Category category; + typedef Iter1 first; + typedef Iter2 second; + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + typedef pair< + typename deref::type + , typename deref::type + > type; + + typedef typename mpl::next::type i1_; + typedef typename mpl::next::type i2_; + typedef pair_iter next; + + typedef apply_wrap2< aux::prior_pair_iter,Iter1,Iter2 >::type prior; +#endif +}; + + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template< typename Iter1, typename Iter2, typename C > +struct deref< pair_iter > +{ + typedef pair< + typename deref::type + , typename deref::type + > type; +}; + +template< typename Iter1, typename Iter2, typename C > +struct next< pair_iter > +{ + typedef typename mpl::next::type i1_; + typedef typename mpl::next::type i2_; + typedef pair_iter type; +}; + +template< typename Iter1, typename Iter2, typename C > +struct prior< pair_iter > +{ + typedef typename mpl::prior::type i1_; + typedef typename mpl::prior::type i2_; + typedef pair_iter type; +}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + +template<> struct advance_impl +{ + template< typename Iter, typename D > struct apply + { + typedef typename mpl::advance< typename Iter::first,D >::type i1_; + typedef typename mpl::advance< typename Iter::second,D >::type i2_; + typedef pair_iter type; + }; +}; + +template<> struct distance_impl +{ + template< typename Iter1, typename Iter2 > struct apply + { + // agurt, 10/nov/04: MSVC 6.5 ICE-s on forwarding + typedef typename mpl::distance< + typename first::type + , typename first::type + >::type type; + }; +}; + + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence1) + , typename BOOST_MPL_AUX_NA_PARAM(Sequence2) + > +struct pair_view +{ + typedef nested_begin_end_tag tag; + + typedef typename begin::type iter1_; + typedef typename begin::type iter2_; + typedef typename min< + typename iterator_category::type + , typename iterator_category::type + >::type category_; + + typedef pair_iter begin; + + typedef pair_iter< + typename end::type + , typename end::type + , category_ + > end; +}; + +BOOST_MPL_AUX_NA_SPEC(2, pair_view) + +}} + +#endif // BOOST_MPL_PAIR_VIEW_HPP_INCLUDED diff --git a/boost/mpl/plus.hpp b/boost/mpl/plus.hpp new file mode 100644 index 00000000..455920b5 --- /dev/null +++ b/boost/mpl/plus.hpp @@ -0,0 +1,21 @@ + +#ifndef BOOST_MPL_PLUS_HPP_INCLUDED +#define BOOST_MPL_PLUS_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#define AUX778076_OP_NAME plus +#define AUX778076_OP_TOKEN + +#include + +#endif // BOOST_MPL_PLUS_HPP_INCLUDED diff --git a/boost/mpl/pop_back_fwd.hpp b/boost/mpl/pop_back_fwd.hpp new file mode 100644 index 00000000..70957046 --- /dev/null +++ b/boost/mpl/pop_back_fwd.hpp @@ -0,0 +1,24 @@ + +#ifndef BOOST_MPL_POP_BACK_FWD_HPP_INCLUDED +#define BOOST_MPL_POP_BACK_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +template< typename Tag > struct pop_back_impl; +template< typename Sequence > struct pop_back; + +}} + +#endif // BOOST_MPL_POP_BACK_FWD_HPP_INCLUDED diff --git a/boost/mpl/pop_front_fwd.hpp b/boost/mpl/pop_front_fwd.hpp new file mode 100644 index 00000000..719c8b21 --- /dev/null +++ b/boost/mpl/pop_front_fwd.hpp @@ -0,0 +1,24 @@ + +#ifndef BOOST_MPL_POP_FRONT_FWD_HPP_INCLUDED +#define BOOST_MPL_POP_FRONT_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +template< typename Tag > struct pop_front_impl; +template< typename Sequence > struct pop_front; + +}} + +#endif // BOOST_MPL_POP_FRONT_FWD_HPP_INCLUDED diff --git a/boost/mpl/prior.hpp b/boost/mpl/prior.hpp new file mode 100644 index 00000000..849802cf --- /dev/null +++ b/boost/mpl/prior.hpp @@ -0,0 +1,19 @@ + +#ifndef BOOST_MPL_PRIOR_HPP_INCLUDED +#define BOOST_MPL_PRIOR_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include + +#endif // BOOST_MPL_PRIOR_HPP_INCLUDED diff --git a/boost/mpl/push_back.hpp b/boost/mpl/push_back.hpp new file mode 100644 index 00000000..95a2587b --- /dev/null +++ b/boost/mpl/push_back.hpp @@ -0,0 +1,53 @@ + +#ifndef BOOST_MPL_PUSH_BACK_HPP_INCLUDED +#define BOOST_MPL_PUSH_BACK_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + , typename BOOST_MPL_AUX_NA_PARAM(T) + > +struct push_back + : push_back_impl< typename sequence_tag::type > + ::template apply< Sequence,T > +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,push_back,(Sequence,T)) +}; + + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + > +struct has_push_back + : has_push_back_impl< typename sequence_tag::type > + ::template apply< Sequence > +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,has_push_back,(Sequence)) +}; + + +BOOST_MPL_AUX_NA_SPEC(2, push_back) +BOOST_MPL_AUX_NA_SPEC(1, has_push_back) + +}} + +#endif // BOOST_MPL_PUSH_BACK_HPP_INCLUDED diff --git a/boost/mpl/push_back_fwd.hpp b/boost/mpl/push_back_fwd.hpp new file mode 100644 index 00000000..7a4f7a75 --- /dev/null +++ b/boost/mpl/push_back_fwd.hpp @@ -0,0 +1,24 @@ + +#ifndef BOOST_MPL_PUSH_BACK_FWD_HPP_INCLUDED +#define BOOST_MPL_PUSH_BACK_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +template< typename Tag > struct push_back_impl; +template< typename Sequence, typename T > struct push_back; + +}} + +#endif // BOOST_MPL_PUSH_BACK_FWD_HPP_INCLUDED diff --git a/boost/mpl/push_front.hpp b/boost/mpl/push_front.hpp new file mode 100644 index 00000000..e4d0dfb7 --- /dev/null +++ b/boost/mpl/push_front.hpp @@ -0,0 +1,52 @@ + +#ifndef BOOST_MPL_PUSH_FRONT_HPP_INCLUDED +#define BOOST_MPL_PUSH_FRONT_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + , typename BOOST_MPL_AUX_NA_PARAM(T) + > +struct push_front + : push_front_impl< typename sequence_tag::type > + ::template apply< Sequence,T > +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,push_front,(Sequence,T)) +}; + + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + > +struct has_push_front + : has_push_front_impl< typename sequence_tag::type > + ::template apply< Sequence > +{ + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,has_push_front,(Sequence)) +}; + +BOOST_MPL_AUX_NA_SPEC(2, push_front) +BOOST_MPL_AUX_NA_SPEC(1, has_push_front) + +}} + +#endif // BOOST_MPL_PUSH_FRONT_HPP_INCLUDED diff --git a/boost/mpl/push_front_fwd.hpp b/boost/mpl/push_front_fwd.hpp new file mode 100644 index 00000000..d6ad5af5 --- /dev/null +++ b/boost/mpl/push_front_fwd.hpp @@ -0,0 +1,24 @@ + +#ifndef BOOST_MPL_PUSH_FRONT_FWD_HPP_INCLUDED +#define BOOST_MPL_PUSH_FRONT_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +template< typename Tag > struct push_front_impl; +template< typename Sequence, typename T > struct push_front; + +}} + +#endif // BOOST_MPL_PUSH_FRONT_FWD_HPP_INCLUDED diff --git a/boost/mpl/reverse_fold.hpp b/boost/mpl/reverse_fold.hpp new file mode 100644 index 00000000..87c26a9a --- /dev/null +++ b/boost/mpl/reverse_fold.hpp @@ -0,0 +1,50 @@ + +#ifndef BOOST_MPL_REVERSE_FOLD_HPP_INCLUDED +#define BOOST_MPL_REVERSE_FOLD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2001-2004 +// Copyright David Abrahams 2001-2002 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + , typename BOOST_MPL_AUX_NA_PARAM(State) + , typename BOOST_MPL_AUX_NA_PARAM(BackwardOp) + , typename ForwardOp = arg<1> + > +struct reverse_fold +{ + typedef typename aux::reverse_fold_impl< + ::boost::mpl::O1_size::value + , typename begin::type + , typename end::type + , State + , BackwardOp + , ForwardOp + >::state type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(3,reverse_fold,(Sequence,State,BackwardOp)) +}; + +BOOST_MPL_AUX_NA_SPEC(3, reverse_fold) + +}} + +#endif // BOOST_MPL_REVERSE_FOLD_HPP_INCLUDED diff --git a/boost/mpl/sequence_tag.hpp b/boost/mpl/sequence_tag.hpp new file mode 100644 index 00000000..f87d92b2 --- /dev/null +++ b/boost/mpl/sequence_tag.hpp @@ -0,0 +1,124 @@ + +#ifndef BOOST_MPL_SEQUENCE_TAG_HPP_INCLUDED +#define BOOST_MPL_SEQUENCE_TAG_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +// agurt, 27/nov/02: have to use a simplistic 'sequence_tag' implementation +// on MSVC to avoid dreadful "internal structure overflow" error +#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ + || defined(BOOST_MPL_CFG_NO_HAS_XXX) + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + > +struct sequence_tag +{ + typedef typename Sequence::tag type; +}; + +#elif BOOST_WORKAROUND(BOOST_MSVC, == 1300) + +// agurt, 07/feb/03: workaround for what seems to be MSVC 7.0-specific ETI issue + +namespace aux { + +template< bool > +struct sequence_tag_impl +{ + template< typename Sequence > struct result_ + { + typedef typename Sequence::tag type; + }; +}; + +template<> +struct sequence_tag_impl +{ + template< typename Sequence > struct result_ + { + typedef int type; + }; +}; + +} // namespace aux + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + > +struct sequence_tag + : aux::sequence_tag_impl< !aux::is_msvc_eti_arg::value > + ::template result_ +{ +}; + +#else + +namespace aux { + +template< bool has_tag_, bool has_begin_ > +struct sequence_tag_impl +{ + // agurt 24/nov/02: MSVC 6.5 gets confused in 'sequence_tag_impl' + // specialization below, if we name it 'result_' here + template< typename Sequence > struct result2_; +}; + +# define AUX_CLASS_SEQUENCE_TAG_SPEC(has_tag, has_begin, result_type) \ +template<> struct sequence_tag_impl \ +{ \ + template< typename Sequence > struct result2_ \ + { \ + typedef result_type type; \ + }; \ +}; \ +/**/ + +AUX_CLASS_SEQUENCE_TAG_SPEC(true, true, typename Sequence::tag) +AUX_CLASS_SEQUENCE_TAG_SPEC(true, false, typename Sequence::tag) +AUX_CLASS_SEQUENCE_TAG_SPEC(false, true, nested_begin_end_tag) +AUX_CLASS_SEQUENCE_TAG_SPEC(false, false, non_sequence_tag) + +# undef AUX_CLASS_SEQUENCE_TAG_SPEC + +} // namespace aux + +template< + typename BOOST_MPL_AUX_NA_PARAM(Sequence) + > +struct sequence_tag + : aux::sequence_tag_impl< + ::boost::mpl::aux::has_tag::value + , ::boost::mpl::aux::has_begin::value + >::template result2_ +{ +}; + +#endif // BOOST_MSVC + +BOOST_MPL_AUX_NA_SPEC(1, sequence_tag) + +}} + +#endif // BOOST_MPL_SEQUENCE_TAG_HPP_INCLUDED diff --git a/boost/mpl/sequence_tag_fwd.hpp b/boost/mpl/sequence_tag_fwd.hpp new file mode 100644 index 00000000..4b0ed6f6 --- /dev/null +++ b/boost/mpl/sequence_tag_fwd.hpp @@ -0,0 +1,26 @@ + +#ifndef BOOST_MPL_SEQUENCE_TAG_FWD_HPP_INCLUDED +#define BOOST_MPL_SEQUENCE_TAG_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +struct nested_begin_end_tag; +struct non_sequence_tag; + +template< typename Sequence > struct sequence_tag; + +}} + +#endif // BOOST_MPL_SEQUENCE_TAG_FWD_HPP_INCLUDED diff --git a/boost/mpl/size_fwd.hpp b/boost/mpl/size_fwd.hpp new file mode 100644 index 00000000..c72628dd --- /dev/null +++ b/boost/mpl/size_fwd.hpp @@ -0,0 +1,24 @@ + +#ifndef BOOST_MPL_SIZE_FWD_HPP_INCLUDED +#define BOOST_MPL_SIZE_FWD_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +namespace boost { namespace mpl { + +template< typename Tag > struct size_impl; +template< typename Sequence > struct size; + +}} + +#endif // BOOST_MPL_SIZE_FWD_HPP_INCLUDED diff --git a/boost/mpl/transform.hpp b/boost/mpl/transform.hpp new file mode 100644 index 00000000..4d3e2a04 --- /dev/null +++ b/boost/mpl/transform.hpp @@ -0,0 +1,145 @@ + +#ifndef BOOST_MPL_TRANSFORM_HPP_INCLUDED +#define BOOST_MPL_TRANSFORM_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// Copyright David Abrahams 2003-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +namespace aux { + +template< + typename Seq + , typename Op + , typename In + > +struct transform1_impl + : fold< + Seq + , typename In::state + , bind2< typename lambda< typename In::operation >::type + , _1 + , bind1< typename lambda::type, _2> + > + > +{ +}; + +template< + typename Seq + , typename Op + , typename In + > +struct reverse_transform1_impl + : reverse_fold< + Seq + , typename In::state + , bind2< typename lambda< typename In::operation >::type + , _1 + , bind1< typename lambda::type, _2> + > + > +{ +}; + +template< + typename Seq1 + , typename Seq2 + , typename Op + , typename In + > +struct transform2_impl + : fold< + pair_view + , typename In::state + , bind2< typename lambda< typename In::operation >::type + , _1 + , bind2< + typename lambda::type + , bind1,_2> + , bind1,_2> + > + > + > +{ +}; + +template< + typename Seq1 + , typename Seq2 + , typename Op + , typename In + > +struct reverse_transform2_impl + : reverse_fold< + pair_view + , typename In::state + , bind2< typename lambda< typename In::operation >::type + , _1 + , bind2< typename lambda< Op >::type + , bind1,_2> + , bind1,_2> + > + > + > +{ +}; + +} // namespace aux + +BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF(3, transform1) +BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF(4, transform2) + +#define AUX778076_TRANSFORM_DEF(name) \ +template< \ + typename BOOST_MPL_AUX_NA_PARAM(Seq1) \ + , typename BOOST_MPL_AUX_NA_PARAM(Seq2OrOperation) \ + , typename BOOST_MPL_AUX_NA_PARAM(OperationOrInserter) \ + , typename BOOST_MPL_AUX_NA_PARAM(Inserter) \ + > \ +struct name \ +{ \ + typedef typename eval_if< \ + or_< \ + is_na \ + , is_lambda_expression< Seq2OrOperation > \ + , not_< is_sequence > \ + > \ + , name##1 \ + , name##2 \ + >::type type; \ +}; \ +BOOST_MPL_AUX_NA_SPEC(4, name) \ +/**/ + +AUX778076_TRANSFORM_DEF(transform) +AUX778076_TRANSFORM_DEF(reverse_transform) + +#undef AUX778076_TRANSFORM_DEF + +}} + +#endif // BOOST_MPL_TRANSFORM_HPP_INCLUDED diff --git a/boost/mpl/vector.hpp b/boost/mpl/vector.hpp new file mode 100644 index 00000000..479983d5 --- /dev/null +++ b/boost/mpl/vector.hpp @@ -0,0 +1,57 @@ + +#ifndef BOOST_MPL_VECTOR_HPP_INCLUDED +#define BOOST_MPL_VECTOR_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +# include +# include + +# include +# include +# include + +#if !defined(BOOST_NEEDS_TOKEN_PASTING_OP_FOR_TOKENS_JUXTAPOSING) +# define AUX778076_VECTOR_HEADER \ + BOOST_PP_CAT(vector, BOOST_MPL_LIMIT_VECTOR_SIZE).hpp \ + /**/ +#else +# define AUX778076_VECTOR_HEADER \ + BOOST_PP_CAT(vector, BOOST_MPL_LIMIT_VECTOR_SIZE)##.hpp \ + /**/ +#endif + +# include BOOST_PP_STRINGIZE(boost/mpl/vector/AUX778076_VECTOR_HEADER) +# undef AUX778076_VECTOR_HEADER +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER vector.hpp +# include + +#else + +# include + +# define AUX778076_SEQUENCE_NAME vector +# define AUX778076_SEQUENCE_LIMIT BOOST_MPL_LIMIT_VECTOR_SIZE +# include + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS +#endif // BOOST_MPL_VECTOR_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/O1_size.hpp b/boost/mpl/vector/aux_/O1_size.hpp new file mode 100644 index 00000000..ac9e3cf8 --- /dev/null +++ b/boost/mpl/vector/aux_/O1_size.hpp @@ -0,0 +1,56 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_O1_SIZE_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_O1_SIZE_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +template<> +struct O1_size_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + : Vector::size + { + }; +}; + +#else + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template< long N > +struct O1_size_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + : mpl::long_ + { + }; +}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +}} + +#endif // BOOST_MPL_VECTOR_AUX_O1_SIZE_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/at.hpp b/boost/mpl/vector/aux_/at.hpp new file mode 100644 index 00000000..d7b14d42 --- /dev/null +++ b/boost/mpl/vector/aux_/at.hpp @@ -0,0 +1,116 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_AT_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_AT_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +template< typename Vector, long n_ > +struct v_at_impl +{ + typedef long_< (Vector::lower_bound_::value + n_) > index_; + typedef __typeof__( Vector::item_(index_()) ) type; +}; + + +template< typename Vector, long n_ > +struct v_at + : aux::wrapped_type< typename v_at_impl::type > +{ +}; + +template<> +struct at_impl< aux::vector_tag > +{ + template< typename Vector, typename N > struct apply + : v_at< + Vector + , BOOST_MPL_AUX_VALUE_WKND(N)::value + > + { + }; +}; + +#else + +# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_MPL_CFG_NO_NONTYPE_TEMPLATE_PARTIAL_SPEC) + +template< typename Vector, BOOST_MPL_AUX_NTTP_DECL(long, n_) > struct v_at; + +template< BOOST_MPL_AUX_NTTP_DECL(long, n_) > +struct at_impl< aux::vector_tag > +{ + template< typename Vector, typename N > struct apply +#if !defined(BOOST_BORLANDC) + : v_at< + Vector + , BOOST_MPL_AUX_VALUE_WKND(N)::value + > + { +#else + { + typedef typename v_at< + Vector + , BOOST_MPL_AUX_VALUE_WKND(N)::value + >::type type; +#endif + }; +}; + +# else + +namespace aux { + +template< BOOST_MPL_AUX_NTTP_DECL(long, n_) > struct v_at_impl +{ + template< typename V > struct result_; +}; + +// to work around ETI, etc. +template<> struct v_at_impl<-1> +{ + template< typename V > struct result_ + { + typedef void_ type; + }; +}; + +} // namespace aux + +template< typename T, BOOST_MPL_AUX_NTTP_DECL(long, n_) > +struct v_at + : aux::v_at_impl::template result_ +{ +}; + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +}} + +#endif // BOOST_MPL_VECTOR_AUX_AT_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/back.hpp b/boost/mpl/vector/aux_/back.hpp new file mode 100644 index 00000000..b66363ec --- /dev/null +++ b/boost/mpl/vector/aux_/back.hpp @@ -0,0 +1,59 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_BACK_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_BACK_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +template<> +struct back_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + : v_at< + Vector + , prior::type::value + > + { + }; +}; + +#else + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template< long n_ > +struct back_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +}} + +#endif // BOOST_MPL_VECTOR_AUX_BACK_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/begin_end.hpp b/boost/mpl/vector/aux_/begin_end.hpp new file mode 100644 index 00000000..aa344515 --- /dev/null +++ b/boost/mpl/vector/aux_/begin_end.hpp @@ -0,0 +1,49 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_BEGIN_END_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_BEGIN_END_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +# include +# include +# include + +namespace boost { namespace mpl { + +template<> +struct begin_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + { + typedef v_iter type; + }; +}; + +template<> +struct end_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + { + typedef v_iter type; + }; +}; + +}} + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +#endif // BOOST_MPL_VECTOR_AUX_BEGIN_END_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/clear.hpp b/boost/mpl/vector/aux_/clear.hpp new file mode 100644 index 00000000..b06d8be7 --- /dev/null +++ b/boost/mpl/vector/aux_/clear.hpp @@ -0,0 +1,55 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_CLEAR_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_CLEAR_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +template<> +struct clear_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +#else + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template< long N > +struct clear_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +}} + +#endif // BOOST_MPL_VECTOR_AUX_CLEAR_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/empty.hpp b/boost/mpl/vector/aux_/empty.hpp new file mode 100644 index 00000000..5490a5f7 --- /dev/null +++ b/boost/mpl/vector/aux_/empty.hpp @@ -0,0 +1,68 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_EMPTY_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_EMPTY_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +template<> +struct empty_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + : is_same< + typename Vector::lower_bound_ + , typename Vector::upper_bound_ + > + { + }; +}; + +#else + +template<> +struct empty_impl< aux::vector_tag<0> > +{ + template< typename Vector > struct apply + : true_ + { + }; +}; + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template< long N > +struct empty_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +}} + +#endif // BOOST_MPL_VECTOR_AUX_EMPTY_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/front.hpp b/boost/mpl/vector/aux_/front.hpp new file mode 100644 index 00000000..a358db52 --- /dev/null +++ b/boost/mpl/vector/aux_/front.hpp @@ -0,0 +1,56 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_FRONT_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_FRONT_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2008 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +template<> +struct front_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + : v_at + { + }; +}; + +#else + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template< BOOST_MPL_AUX_NTTP_DECL(long, n_) > +struct front_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +}} + +#endif // BOOST_MPL_VECTOR_AUX_FRONT_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/include_preprocessed.hpp b/boost/mpl/vector/aux_/include_preprocessed.hpp new file mode 100644 index 00000000..a676116f --- /dev/null +++ b/boost/mpl/vector/aux_/include_preprocessed.hpp @@ -0,0 +1,55 @@ + +// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION + +// Copyright Aleksey Gurtovoy 2000-2006 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include + +#include +#include + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) +# define AUX778076_INCLUDE_DIR typeof_based +#elif defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + || defined(BOOST_MPL_CFG_NO_NONTYPE_TEMPLATE_PARTIAL_SPEC) +# define AUX778076_INCLUDE_DIR no_ctps +#else +# define AUX778076_INCLUDE_DIR plain +#endif + +#if !defined(BOOST_NEEDS_TOKEN_PASTING_OP_FOR_TOKENS_JUXTAPOSING) +# define AUX778076_HEADER \ + AUX778076_INCLUDE_DIR/BOOST_MPL_PREPROCESSED_HEADER \ +/**/ +#else +# define AUX778076_HEADER \ + BOOST_PP_CAT(AUX778076_INCLUDE_DIR,/)##BOOST_MPL_PREPROCESSED_HEADER \ +/**/ +#endif + + +#if BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(700)) +# define AUX778076_INCLUDE_STRING BOOST_PP_STRINGIZE(boost/mpl/vector/aux_/preprocessed/AUX778076_HEADER) +# include AUX778076_INCLUDE_STRING +# undef AUX778076_INCLUDE_STRING +#else +# include BOOST_PP_STRINGIZE(boost/mpl/vector/aux_/preprocessed/AUX778076_HEADER) +#endif + +# undef AUX778076_HEADER +# undef AUX778076_INCLUDE_DIR + +#undef BOOST_MPL_PREPROCESSED_HEADER diff --git a/boost/mpl/vector/aux_/item.hpp b/boost/mpl/vector/aux_/item.hpp new file mode 100644 index 00000000..71538ceb --- /dev/null +++ b/boost/mpl/vector/aux_/item.hpp @@ -0,0 +1,103 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_ITEM_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_ITEM_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +template< + typename T + , typename Base + , int at_front = 0 + > +struct v_item + : Base +{ + typedef typename Base::upper_bound_ index_; + typedef typename next::type upper_bound_; + typedef typename next::type size; + typedef Base base; + typedef v_item type; + + // agurt 10/sep/04: MWCW <= 9.3 workaround here and below; the compiler + // breaks if using declaration comes _before_ the new overload + static aux::type_wrapper item_(index_); + using Base::item_; +}; + +template< + typename T + , typename Base + > +struct v_item + : Base +{ + typedef typename prior::type index_; + typedef index_ lower_bound_; + typedef typename next::type size; + typedef Base base; + typedef v_item type; + + static aux::type_wrapper item_(index_); + using Base::item_; +}; + +// "erasure" item +template< + typename Base + , int at_front + > +struct v_mask + : Base +{ + typedef typename prior::type index_; + typedef index_ upper_bound_; + typedef typename prior::type size; + typedef Base base; + typedef v_mask type; + + static aux::type_wrapper item_(index_); + using Base::item_; +}; + +template< + typename Base + > +struct v_mask + : Base +{ + typedef typename Base::lower_bound_ index_; + typedef typename next::type lower_bound_; + typedef typename prior::type size; + typedef Base base; + typedef v_mask type; + + static aux::type_wrapper item_(index_); + using Base::item_; +}; + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +}} + +#endif // BOOST_MPL_VECTOR_AUX_ITEM_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/iterator.hpp b/boost/mpl/vector/aux_/iterator.hpp new file mode 100644 index 00000000..32df3156 --- /dev/null +++ b/boost/mpl/vector/aux_/iterator.hpp @@ -0,0 +1,130 @@ + +#ifndef BOOST_MPL_AUX_VECTOR_ITERATOR_HPP_INCLUDED +#define BOOST_MPL_AUX_VECTOR_ITERATOR_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +template< + typename Vector + , BOOST_MPL_AUX_NTTP_DECL(long, n_) + > +struct v_iter +{ + typedef aux::v_iter_tag tag; + typedef random_access_iterator_tag category; + typedef typename v_at::type type; + + typedef Vector vector_; + typedef mpl::long_ pos; + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + enum { + next_ = n_ + 1 + , prior_ = n_ - 1 + , pos_ = n_ + }; + + typedef v_iter next; + typedef v_iter prior; +#endif + +}; + + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template< + typename Vector + , BOOST_MPL_AUX_NTTP_DECL(long, n_) + > +struct next< v_iter > +{ + typedef v_iter type; +}; + +template< + typename Vector + , BOOST_MPL_AUX_NTTP_DECL(long, n_) + > +struct prior< v_iter > +{ + typedef v_iter type; +}; + +template< + typename Vector + , BOOST_MPL_AUX_NTTP_DECL(long, n_) + , typename Distance + > +struct advance< v_iter,Distance> +{ + typedef v_iter< + Vector + , (n_ + BOOST_MPL_AUX_NESTED_VALUE_WKND(long, Distance)) + > type; +}; + +template< + typename Vector + , BOOST_MPL_AUX_NTTP_DECL(long, n_) + , BOOST_MPL_AUX_NTTP_DECL(long, m_) + > +struct distance< v_iter, v_iter > + : mpl::long_<(m_ - n_)> +{ +}; + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +template<> struct advance_impl +{ + template< typename Iterator, typename N > struct apply + { + enum { pos_ = Iterator::pos_, n_ = N::value }; + typedef v_iter< + typename Iterator::vector_ + , (pos_ + n_) + > type; + }; +}; + +template<> struct distance_impl +{ + template< typename Iter1, typename Iter2 > struct apply + { + enum { pos1_ = Iter1::pos_, pos2_ = Iter2::pos_ }; + typedef long_<( pos2_ - pos1_ )> type; + BOOST_STATIC_CONSTANT(long, value = ( pos2_ - pos1_ )); + }; +}; + +#endif + +}} + +#endif // BOOST_MPL_AUX_VECTOR_ITERATOR_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/numbered.hpp b/boost/mpl/vector/aux_/numbered.hpp new file mode 100644 index 00000000..b3f03873 --- /dev/null +++ b/boost/mpl/vector/aux_/numbered.hpp @@ -0,0 +1,218 @@ + +// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION + +#if defined(BOOST_PP_IS_ITERATING) + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include + +#define i_ BOOST_PP_FRAME_ITERATION(1) + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +# define AUX778076_VECTOR_TAIL(vector, i_, T) \ + BOOST_PP_CAT(vector,i_)< \ + BOOST_PP_ENUM_PARAMS(i_, T) \ + > \ + /**/ + +#if i_ > 0 +template< + BOOST_PP_ENUM_PARAMS(i_, typename T) + > +struct BOOST_PP_CAT(vector,i_) + : v_item< + BOOST_PP_CAT(T,BOOST_PP_DEC(i_)) + , AUX778076_VECTOR_TAIL(vector,BOOST_PP_DEC(i_),T) + > +{ + typedef BOOST_PP_CAT(vector,i_) type; +}; +#endif + +# undef AUX778076_VECTOR_TAIL + +#else // "brute force" implementation + +# if i_ > 0 + +template< + BOOST_PP_ENUM_PARAMS(i_, typename T) + > +struct BOOST_PP_CAT(vector,i_) +{ + typedef aux::vector_tag tag; + typedef BOOST_PP_CAT(vector,i_) type; + +# define AUX778076_VECTOR_ITEM(unused, i_, unused2) \ + typedef BOOST_PP_CAT(T,i_) BOOST_PP_CAT(item,i_); \ + /**/ + + BOOST_PP_REPEAT(i_, AUX778076_VECTOR_ITEM, unused) +# undef AUX778076_VECTOR_ITEM + typedef void_ BOOST_PP_CAT(item,i_); + typedef BOOST_PP_CAT(T,BOOST_PP_DEC(i_)) back; + + // Borland forces us to use 'type' here (instead of the class name) + typedef v_iter begin; + typedef v_iter end; +}; + +template<> +struct push_front_impl< aux::vector_tag > +{ + template< typename Vector, typename T > struct apply + { + typedef BOOST_PP_CAT(vector,i_)< + T + BOOST_PP_COMMA_IF(BOOST_PP_DEC(i_)) + BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(i_), typename Vector::item) + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + { + typedef BOOST_PP_CAT(vector,BOOST_PP_DEC(i_))< + BOOST_PP_ENUM_SHIFTED_PARAMS(i_, typename Vector::item) + > type; + }; +}; + + +template<> +struct push_back_impl< aux::vector_tag > +{ + template< typename Vector, typename T > struct apply + { + typedef BOOST_PP_CAT(vector,i_)< + BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(i_), typename Vector::item) + BOOST_PP_COMMA_IF(BOOST_PP_DEC(i_)) + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + { + typedef BOOST_PP_CAT(vector,BOOST_PP_DEC(i_))< + BOOST_PP_ENUM_PARAMS(BOOST_PP_DEC(i_), typename Vector::item) + > type; + }; +}; + +# endif // i_ > 0 + +# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && !defined(BOOST_MPL_CFG_NO_NONTYPE_TEMPLATE_PARTIAL_SPEC) + +template< typename V > +struct v_at +{ + typedef typename V::BOOST_PP_CAT(item,i_) type; +}; + +# else + +namespace aux { +template<> struct v_at_impl +{ + template< typename V_ > struct result_ + { + typedef typename V_::BOOST_PP_CAT(item,i_) type; + }; +}; +} + +template<> +struct at_impl< aux::vector_tag > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +#if i_ > 0 +template<> +struct front_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; +#endif + +template<> +struct size_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + : long_ + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag > + : size_impl< aux::vector_tag > +{ +}; + +template<> +struct clear_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +#undef i_ + +#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/vector/aux_/numbered_c.hpp b/boost/mpl/vector/aux_/numbered_c.hpp new file mode 100644 index 00000000..4c159f94 --- /dev/null +++ b/boost/mpl/vector/aux_/numbered_c.hpp @@ -0,0 +1,77 @@ + +// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION + +#if defined(BOOST_PP_IS_ITERATING) + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include + +#define i_ BOOST_PP_FRAME_ITERATION(1) + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +# define AUX778076_VECTOR_TAIL(vector, i_, C) \ + BOOST_PP_CAT(BOOST_PP_CAT(vector,i_),_c) \ + /**/ + +#if i_ > 0 +template< + typename T + , BOOST_PP_ENUM_PARAMS(i_, T C) + > +struct BOOST_PP_CAT(BOOST_PP_CAT(vector,i_),_c) + : v_item< + integral_c + , AUX778076_VECTOR_TAIL(vector,BOOST_PP_DEC(i_),C) + > +{ + typedef BOOST_PP_CAT(BOOST_PP_CAT(vector,i_),_c) type; + typedef T value_type; +}; +#endif + +# undef AUX778076_VECTOR_TAIL + +#else // "brute force" implementation + +# define AUX778076_VECTOR_C_PARAM_FUNC(unused, i_, param) \ + BOOST_PP_COMMA_IF(i_) \ + integral_c \ + /**/ + +template< + typename T + , BOOST_PP_ENUM_PARAMS(i_, T C) + > +struct BOOST_PP_CAT(BOOST_PP_CAT(vector,i_),_c) + : BOOST_PP_CAT(vector,i_)< BOOST_PP_REPEAT(i_,AUX778076_VECTOR_C_PARAM_FUNC,C) > +{ + typedef BOOST_PP_CAT(BOOST_PP_CAT(vector,i_),_c) type; + typedef T value_type; +}; + +# undef AUX778076_VECTOR_C_PARAM_FUNC + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +#undef i_ + +#endif // BOOST_PP_IS_ITERATING diff --git a/boost/mpl/vector/aux_/pop_back.hpp b/boost/mpl/vector/aux_/pop_back.hpp new file mode 100644 index 00000000..1d95e355 --- /dev/null +++ b/boost/mpl/vector/aux_/pop_back.hpp @@ -0,0 +1,40 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_POP_BACK_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_POP_BACK_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +# include +# include + +namespace boost { namespace mpl { + +template<> +struct pop_back_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + { + typedef v_mask type; + }; +}; + +}} + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +#endif // BOOST_MPL_VECTOR_AUX_POP_BACK_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/pop_front.hpp b/boost/mpl/vector/aux_/pop_front.hpp new file mode 100644 index 00000000..c94b8711 --- /dev/null +++ b/boost/mpl/vector/aux_/pop_front.hpp @@ -0,0 +1,40 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_POP_FRONT_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_POP_FRONT_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +# include +# include + +namespace boost { namespace mpl { + +template<> +struct pop_front_impl< aux::vector_tag > +{ + template< typename Vector > struct apply + { + typedef v_mask type; + }; +}; + +}} + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +#endif // BOOST_MPL_VECTOR_AUX_POP_FRONT_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/preprocessed/no_ctps/vector10.hpp b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector10.hpp new file mode 100644 index 00000000..c79a1ac6 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector10.hpp @@ -0,0 +1,1528 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector10.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +namespace aux { +template<> struct v_at_impl<0> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item0 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<0> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct size_impl< aux::vector_tag<0> > +{ + template< typename Vector > struct apply + : long_<0> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<0> > + : size_impl< aux::vector_tag<0> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<0> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0 + > +struct vector1 +{ + typedef aux::vector_tag<1> tag; + typedef vector1 type; + typedef T0 item0; + typedef void_ item1; + typedef T0 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,1 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<0> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector1< + T + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<1> > +{ + template< typename Vector > struct apply + { + typedef vector0< + + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<0> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector1< + + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<1> > +{ + template< typename Vector > struct apply + { + typedef vector0< + + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<1> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item1 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<1> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<1> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<1> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<1> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<1> > +{ + template< typename Vector > struct apply + : long_<1> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<1> > + : size_impl< aux::vector_tag<1> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<1> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1 + > +struct vector2 +{ + typedef aux::vector_tag<2> tag; + typedef vector2 type; + typedef T0 item0; + typedef T1 item1; + + + typedef void_ item2; + typedef T1 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,2 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<1> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector2< + T + , + typename Vector::item0 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<2> > +{ + template< typename Vector > struct apply + { + typedef vector1< + typename Vector::item1 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<1> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector2< + typename Vector::item0 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<2> > +{ + template< typename Vector > struct apply + { + typedef vector1< + typename Vector::item0 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<2> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item2 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<2> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<2> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<2> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<2> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<2> > +{ + template< typename Vector > struct apply + : long_<2> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<2> > + : size_impl< aux::vector_tag<2> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<2> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2 + > +struct vector3 +{ + typedef aux::vector_tag<3> tag; + typedef vector3 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + + + typedef void_ item3; + typedef T2 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,3 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<2> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector3< + T + , + typename Vector::item0, typename Vector::item1 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<3> > +{ + template< typename Vector > struct apply + { + typedef vector2< + typename Vector::item1, typename Vector::item2 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<2> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector3< + typename Vector::item0, typename Vector::item1 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<3> > +{ + template< typename Vector > struct apply + { + typedef vector2< + typename Vector::item0, typename Vector::item1 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<3> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item3 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<3> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<3> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<3> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<3> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<3> > +{ + template< typename Vector > struct apply + : long_<3> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<3> > + : size_impl< aux::vector_tag<3> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<3> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3 + > +struct vector4 +{ + typedef aux::vector_tag<4> tag; + typedef vector4 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + + + typedef void_ item4; + typedef T3 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,4 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<3> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector4< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<4> > +{ + template< typename Vector > struct apply + { + typedef vector3< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<3> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector4< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<4> > +{ + template< typename Vector > struct apply + { + typedef vector3< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<4> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item4 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<4> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<4> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<4> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<4> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<4> > +{ + template< typename Vector > struct apply + : long_<4> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<4> > + : size_impl< aux::vector_tag<4> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<4> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + > +struct vector5 +{ + typedef aux::vector_tag<5> tag; + typedef vector5 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + + + typedef void_ item5; + typedef T4 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,5 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<4> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector5< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<5> > +{ + template< typename Vector > struct apply + { + typedef vector4< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<4> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector5< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<5> > +{ + template< typename Vector > struct apply + { + typedef vector4< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<5> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item5 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<5> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<5> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<5> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<5> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<5> > +{ + template< typename Vector > struct apply + : long_<5> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<5> > + : size_impl< aux::vector_tag<5> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<5> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5 + > +struct vector6 +{ + typedef aux::vector_tag<6> tag; + typedef vector6 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + + + typedef void_ item6; + typedef T5 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,6 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<5> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector6< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<6> > +{ + template< typename Vector > struct apply + { + typedef vector5< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<5> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector6< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<6> > +{ + template< typename Vector > struct apply + { + typedef vector5< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<6> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item6 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<6> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<6> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<6> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<6> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<6> > +{ + template< typename Vector > struct apply + : long_<6> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<6> > + : size_impl< aux::vector_tag<6> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<6> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6 + > +struct vector7 +{ + typedef aux::vector_tag<7> tag; + typedef vector7 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + + + typedef void_ item7; + typedef T6 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,7 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<6> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector7< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<7> > +{ + template< typename Vector > struct apply + { + typedef vector6< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<6> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector7< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<7> > +{ + template< typename Vector > struct apply + { + typedef vector6< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<7> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item7 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<7> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<7> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<7> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<7> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<7> > +{ + template< typename Vector > struct apply + : long_<7> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<7> > + : size_impl< aux::vector_tag<7> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<7> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7 + > +struct vector8 +{ + typedef aux::vector_tag<8> tag; + typedef vector8 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + + + typedef void_ item8; + typedef T7 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,8 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<7> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector8< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<8> > +{ + template< typename Vector > struct apply + { + typedef vector7< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<7> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector8< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<8> > +{ + template< typename Vector > struct apply + { + typedef vector7< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<8> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item8 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<8> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<8> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<8> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<8> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<8> > +{ + template< typename Vector > struct apply + : long_<8> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<8> > + : size_impl< aux::vector_tag<8> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<8> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8 + > +struct vector9 +{ + typedef aux::vector_tag<9> tag; + typedef vector9 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + + + typedef void_ item9; + typedef T8 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,9 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<8> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector9< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<9> > +{ + template< typename Vector > struct apply + { + typedef vector8< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<8> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector9< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<9> > +{ + template< typename Vector > struct apply + { + typedef vector8< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<9> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item9 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<9> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<9> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<9> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<9> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<9> > +{ + template< typename Vector > struct apply + : long_<9> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<9> > + : size_impl< aux::vector_tag<9> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<9> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + > +struct vector10 +{ + typedef aux::vector_tag<10> tag; + typedef vector10 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + + + typedef void_ item10; + typedef T9 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,10 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<9> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector10< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<10> > +{ + template< typename Vector > struct apply + { + typedef vector9< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<9> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector10< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<10> > +{ + template< typename Vector > struct apply + { + typedef vector9< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<10> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item10 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<10> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<10> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<10> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<10> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<10> > +{ + template< typename Vector > struct apply + : long_<10> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<10> > + : size_impl< aux::vector_tag<10> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<10> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/no_ctps/vector10_c.hpp b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector10_c.hpp new file mode 100644 index 00000000..8b36f6a3 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector10_c.hpp @@ -0,0 +1,149 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector10_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0 + > +struct vector1_c + : vector1< integral_c< T,C0 > > +{ + typedef vector1_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1 + > +struct vector2_c + : vector2< integral_c< T,C0 >, integral_c< T,C1 > > +{ + typedef vector2_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2 + > +struct vector3_c + : vector3< integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > > +{ + typedef vector3_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3 + > +struct vector4_c + : vector4< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 >, integral_c + > +{ + typedef vector4_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4 + > +struct vector5_c + : vector5< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 > + > +{ + typedef vector5_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5 + > +struct vector6_c + : vector6< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 > + > +{ + typedef vector6_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6 + > +struct vector7_c + : vector7< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c + > +{ + typedef vector7_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7 + > +struct vector8_c + : vector8< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 > + > +{ + typedef vector8_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8 + > +struct vector9_c + : vector9< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 > + > +{ + typedef vector9_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9 + > +struct vector10_c + : vector10< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + > +{ + typedef vector10_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/no_ctps/vector20.hpp b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector20.hpp new file mode 100644 index 00000000..eb92a781 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector20.hpp @@ -0,0 +1,1804 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector20.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10 + > +struct vector11 +{ + typedef aux::vector_tag<11> tag; + typedef vector11 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + + + typedef void_ item11; + typedef T10 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,11 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<10> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector11< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<11> > +{ + template< typename Vector > struct apply + { + typedef vector10< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<10> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector11< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<11> > +{ + template< typename Vector > struct apply + { + typedef vector10< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<11> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item11 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<11> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<11> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<11> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<11> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<11> > +{ + template< typename Vector > struct apply + : long_<11> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<11> > + : size_impl< aux::vector_tag<11> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<11> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11 + > +struct vector12 +{ + typedef aux::vector_tag<12> tag; + typedef vector12 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + + + typedef void_ item12; + typedef T11 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,12 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<11> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector12< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<12> > +{ + template< typename Vector > struct apply + { + typedef vector11< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<11> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector12< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<12> > +{ + template< typename Vector > struct apply + { + typedef vector11< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<12> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item12 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<12> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<12> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<12> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<12> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<12> > +{ + template< typename Vector > struct apply + : long_<12> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<12> > + : size_impl< aux::vector_tag<12> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<12> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12 + > +struct vector13 +{ + typedef aux::vector_tag<13> tag; + typedef vector13 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + + + typedef void_ item13; + typedef T12 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,13 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<12> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector13< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<13> > +{ + template< typename Vector > struct apply + { + typedef vector12< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<12> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector13< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<13> > +{ + template< typename Vector > struct apply + { + typedef vector12< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<13> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item13 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<13> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<13> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<13> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<13> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<13> > +{ + template< typename Vector > struct apply + : long_<13> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<13> > + : size_impl< aux::vector_tag<13> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<13> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13 + > +struct vector14 +{ + typedef aux::vector_tag<14> tag; + typedef vector14 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + + + typedef void_ item14; + typedef T13 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,14 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<13> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector14< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<14> > +{ + template< typename Vector > struct apply + { + typedef vector13< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<13> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector14< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<14> > +{ + template< typename Vector > struct apply + { + typedef vector13< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<14> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item14 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<14> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<14> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<14> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<14> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<14> > +{ + template< typename Vector > struct apply + : long_<14> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<14> > + : size_impl< aux::vector_tag<14> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<14> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + > +struct vector15 +{ + typedef aux::vector_tag<15> tag; + typedef vector15 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + + + typedef void_ item15; + typedef T14 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,15 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<14> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector15< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<15> > +{ + template< typename Vector > struct apply + { + typedef vector14< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<14> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector15< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<15> > +{ + template< typename Vector > struct apply + { + typedef vector14< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<15> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item15 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<15> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<15> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<15> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<15> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<15> > +{ + template< typename Vector > struct apply + : long_<15> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<15> > + : size_impl< aux::vector_tag<15> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<15> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15 + > +struct vector16 +{ + typedef aux::vector_tag<16> tag; + typedef vector16 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + + + typedef void_ item16; + typedef T15 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,16 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<15> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector16< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<16> > +{ + template< typename Vector > struct apply + { + typedef vector15< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<15> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector16< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<16> > +{ + template< typename Vector > struct apply + { + typedef vector15< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<16> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item16 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<16> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<16> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<16> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<16> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<16> > +{ + template< typename Vector > struct apply + : long_<16> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<16> > + : size_impl< aux::vector_tag<16> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<16> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16 + > +struct vector17 +{ + typedef aux::vector_tag<17> tag; + typedef vector17 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + + + typedef void_ item17; + typedef T16 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,17 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<16> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector17< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<17> > +{ + template< typename Vector > struct apply + { + typedef vector16< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<16> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector17< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<17> > +{ + template< typename Vector > struct apply + { + typedef vector16< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<17> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item17 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<17> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<17> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<17> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<17> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<17> > +{ + template< typename Vector > struct apply + : long_<17> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<17> > + : size_impl< aux::vector_tag<17> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<17> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17 + > +struct vector18 +{ + typedef aux::vector_tag<18> tag; + typedef vector18 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + + + typedef void_ item18; + typedef T17 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,18 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<17> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector18< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<18> > +{ + template< typename Vector > struct apply + { + typedef vector17< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<17> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector18< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<18> > +{ + template< typename Vector > struct apply + { + typedef vector17< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<18> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item18 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<18> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<18> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<18> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<18> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<18> > +{ + template< typename Vector > struct apply + : long_<18> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<18> > + : size_impl< aux::vector_tag<18> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<18> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18 + > +struct vector19 +{ + typedef aux::vector_tag<19> tag; + typedef vector19 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + + + typedef void_ item19; + typedef T18 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,19 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<18> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector19< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<19> > +{ + template< typename Vector > struct apply + { + typedef vector18< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<18> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector19< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<19> > +{ + template< typename Vector > struct apply + { + typedef vector18< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<19> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item19 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<19> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<19> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<19> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<19> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<19> > +{ + template< typename Vector > struct apply + : long_<19> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<19> > + : size_impl< aux::vector_tag<19> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<19> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + > +struct vector20 +{ + typedef aux::vector_tag<20> tag; + typedef vector20 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + + + typedef void_ item20; + typedef T19 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,20 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<19> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector20< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<20> > +{ + template< typename Vector > struct apply + { + typedef vector19< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<19> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector20< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<20> > +{ + template< typename Vector > struct apply + { + typedef vector19< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<20> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item20 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<20> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<20> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<20> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<20> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<20> > +{ + template< typename Vector > struct apply + : long_<20> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<20> > + : size_impl< aux::vector_tag<20> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<20> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/no_ctps/vector20_c.hpp b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector20_c.hpp new file mode 100644 index 00000000..56ca53f4 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector20_c.hpp @@ -0,0 +1,195 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector20_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + > +struct vector11_c + : vector11< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 >, integral_c + > +{ + typedef vector11_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11 + > +struct vector12_c + : vector12< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 > + > +{ + typedef vector12_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12 + > +struct vector13_c + : vector13< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + > +{ + typedef vector13_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13 + > +struct vector14_c + : vector14< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 >, integral_c + > +{ + typedef vector14_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14 + > +struct vector15_c + : vector15< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 > + > +{ + typedef vector15_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15 + > +struct vector16_c + : vector16< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + > +{ + typedef vector16_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16 + > +struct vector17_c + : vector17< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 >, integral_c + > +{ + typedef vector17_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17 + > +struct vector18_c + : vector18< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 > + > +{ + typedef vector18_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18 + > +struct vector19_c + : vector19< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + > +{ + typedef vector19_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19 + > +struct vector20_c + : vector20< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 >, integral_c + > +{ + typedef vector20_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/no_ctps/vector30.hpp b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector30.hpp new file mode 100644 index 00000000..a685019b --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector30.hpp @@ -0,0 +1,2124 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector30.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20 + > +struct vector21 +{ + typedef aux::vector_tag<21> tag; + typedef vector21 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + + + typedef void_ item21; + typedef T20 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,21 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<20> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector21< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<21> > +{ + template< typename Vector > struct apply + { + typedef vector20< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<20> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector21< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<21> > +{ + template< typename Vector > struct apply + { + typedef vector20< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<21> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item21 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<21> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<21> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<21> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<21> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<21> > +{ + template< typename Vector > struct apply + : long_<21> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<21> > + : size_impl< aux::vector_tag<21> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<21> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21 + > +struct vector22 +{ + typedef aux::vector_tag<22> tag; + typedef vector22 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + + + typedef void_ item22; + typedef T21 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,22 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<21> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector22< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<22> > +{ + template< typename Vector > struct apply + { + typedef vector21< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<21> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector22< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<22> > +{ + template< typename Vector > struct apply + { + typedef vector21< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<22> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item22 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<22> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<22> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<22> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<22> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<22> > +{ + template< typename Vector > struct apply + : long_<22> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<22> > + : size_impl< aux::vector_tag<22> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<22> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22 + > +struct vector23 +{ + typedef aux::vector_tag<23> tag; + typedef vector23 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + + + typedef void_ item23; + typedef T22 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,23 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<22> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector23< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<23> > +{ + template< typename Vector > struct apply + { + typedef vector22< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<22> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector23< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<23> > +{ + template< typename Vector > struct apply + { + typedef vector22< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<23> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item23 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<23> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<23> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<23> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<23> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<23> > +{ + template< typename Vector > struct apply + : long_<23> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<23> > + : size_impl< aux::vector_tag<23> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<23> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23 + > +struct vector24 +{ + typedef aux::vector_tag<24> tag; + typedef vector24 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + + + typedef void_ item24; + typedef T23 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,24 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<23> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector24< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<24> > +{ + template< typename Vector > struct apply + { + typedef vector23< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<23> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector24< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<24> > +{ + template< typename Vector > struct apply + { + typedef vector23< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<24> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item24 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<24> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<24> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<24> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<24> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<24> > +{ + template< typename Vector > struct apply + : long_<24> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<24> > + : size_impl< aux::vector_tag<24> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<24> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + > +struct vector25 +{ + typedef aux::vector_tag<25> tag; + typedef vector25 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + + + typedef void_ item25; + typedef T24 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,25 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<24> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector25< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<25> > +{ + template< typename Vector > struct apply + { + typedef vector24< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<24> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector25< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<25> > +{ + template< typename Vector > struct apply + { + typedef vector24< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<25> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item25 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<25> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<25> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<25> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<25> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<25> > +{ + template< typename Vector > struct apply + : long_<25> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<25> > + : size_impl< aux::vector_tag<25> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<25> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25 + > +struct vector26 +{ + typedef aux::vector_tag<26> tag; + typedef vector26 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + + + typedef void_ item26; + typedef T25 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,26 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<25> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector26< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<26> > +{ + template< typename Vector > struct apply + { + typedef vector25< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<25> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector26< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<26> > +{ + template< typename Vector > struct apply + { + typedef vector25< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<26> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item26 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<26> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<26> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<26> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<26> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<26> > +{ + template< typename Vector > struct apply + : long_<26> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<26> > + : size_impl< aux::vector_tag<26> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<26> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26 + > +struct vector27 +{ + typedef aux::vector_tag<27> tag; + typedef vector27 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + + + typedef void_ item27; + typedef T26 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,27 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<26> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector27< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<27> > +{ + template< typename Vector > struct apply + { + typedef vector26< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<26> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector27< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<27> > +{ + template< typename Vector > struct apply + { + typedef vector26< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<27> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item27 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<27> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<27> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<27> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<27> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<27> > +{ + template< typename Vector > struct apply + : long_<27> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<27> > + : size_impl< aux::vector_tag<27> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<27> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27 + > +struct vector28 +{ + typedef aux::vector_tag<28> tag; + typedef vector28 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + + + typedef void_ item28; + typedef T27 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,28 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<27> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector28< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<28> > +{ + template< typename Vector > struct apply + { + typedef vector27< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<27> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector28< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<28> > +{ + template< typename Vector > struct apply + { + typedef vector27< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<28> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item28 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<28> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<28> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<28> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<28> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<28> > +{ + template< typename Vector > struct apply + : long_<28> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<28> > + : size_impl< aux::vector_tag<28> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<28> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28 + > +struct vector29 +{ + typedef aux::vector_tag<29> tag; + typedef vector29 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + + + typedef void_ item29; + typedef T28 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,29 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<28> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector29< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<29> > +{ + template< typename Vector > struct apply + { + typedef vector28< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<28> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector29< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<29> > +{ + template< typename Vector > struct apply + { + typedef vector28< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<29> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item29 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<29> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<29> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<29> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<29> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<29> > +{ + template< typename Vector > struct apply + : long_<29> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<29> > + : size_impl< aux::vector_tag<29> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<29> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + > +struct vector30 +{ + typedef aux::vector_tag<30> tag; + typedef vector30 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + + + typedef void_ item30; + typedef T29 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,30 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<29> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector30< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<30> > +{ + template< typename Vector > struct apply + { + typedef vector29< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<29> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector30< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<30> > +{ + template< typename Vector > struct apply + { + typedef vector29< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<30> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item30 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<30> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<30> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<30> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<30> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<30> > +{ + template< typename Vector > struct apply + : long_<30> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<30> > + : size_impl< aux::vector_tag<30> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<30> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/no_ctps/vector30_c.hpp b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector30_c.hpp new file mode 100644 index 00000000..6251dbc5 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector30_c.hpp @@ -0,0 +1,238 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector30_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + > +struct vector21_c + : vector21< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 > + > +{ + typedef vector21_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21 + > +struct vector22_c + : vector22< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + > +{ + typedef vector22_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22 + > +struct vector23_c + : vector23< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 >, integral_c + > +{ + typedef vector23_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23 + > +struct vector24_c + : vector24< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 > + > +{ + typedef vector24_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24 + > +struct vector25_c + : vector25< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + > +{ + typedef vector25_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25 + > +struct vector26_c + : vector26< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 >, integral_c + > +{ + typedef vector26_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26 + > +struct vector27_c + : vector27< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 > + > +{ + typedef vector27_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27 + > +struct vector28_c + : vector28< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + > +{ + typedef vector28_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28 + > +struct vector29_c + : vector29< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 >, integral_c + > +{ + typedef vector29_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29 + > +struct vector30_c + : vector30< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 > + > +{ + typedef vector30_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/no_ctps/vector40.hpp b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector40.hpp new file mode 100644 index 00000000..1ed648a9 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector40.hpp @@ -0,0 +1,2444 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector40.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30 + > +struct vector31 +{ + typedef aux::vector_tag<31> tag; + typedef vector31 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + + + typedef void_ item31; + typedef T30 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,31 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<30> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector31< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<31> > +{ + template< typename Vector > struct apply + { + typedef vector30< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<30> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector31< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<31> > +{ + template< typename Vector > struct apply + { + typedef vector30< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<31> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item31 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<31> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<31> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<31> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<31> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<31> > +{ + template< typename Vector > struct apply + : long_<31> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<31> > + : size_impl< aux::vector_tag<31> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<31> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31 + > +struct vector32 +{ + typedef aux::vector_tag<32> tag; + typedef vector32 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + + + typedef void_ item32; + typedef T31 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,32 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<31> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector32< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<32> > +{ + template< typename Vector > struct apply + { + typedef vector31< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<31> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector32< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<32> > +{ + template< typename Vector > struct apply + { + typedef vector31< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<32> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item32 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<32> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<32> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<32> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<32> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<32> > +{ + template< typename Vector > struct apply + : long_<32> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<32> > + : size_impl< aux::vector_tag<32> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<32> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32 + > +struct vector33 +{ + typedef aux::vector_tag<33> tag; + typedef vector33 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + + + typedef void_ item33; + typedef T32 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,33 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<32> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector33< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<33> > +{ + template< typename Vector > struct apply + { + typedef vector32< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<32> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector33< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<33> > +{ + template< typename Vector > struct apply + { + typedef vector32< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<33> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item33 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<33> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<33> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<33> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<33> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<33> > +{ + template< typename Vector > struct apply + : long_<33> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<33> > + : size_impl< aux::vector_tag<33> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<33> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33 + > +struct vector34 +{ + typedef aux::vector_tag<34> tag; + typedef vector34 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + + + typedef void_ item34; + typedef T33 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,34 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<33> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector34< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<34> > +{ + template< typename Vector > struct apply + { + typedef vector33< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<33> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector34< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<34> > +{ + template< typename Vector > struct apply + { + typedef vector33< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<34> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item34 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<34> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<34> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<34> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<34> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<34> > +{ + template< typename Vector > struct apply + : long_<34> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<34> > + : size_impl< aux::vector_tag<34> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<34> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + > +struct vector35 +{ + typedef aux::vector_tag<35> tag; + typedef vector35 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + + + typedef void_ item35; + typedef T34 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,35 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<34> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector35< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<35> > +{ + template< typename Vector > struct apply + { + typedef vector34< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<34> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector35< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<35> > +{ + template< typename Vector > struct apply + { + typedef vector34< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<35> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item35 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<35> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<35> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<35> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<35> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<35> > +{ + template< typename Vector > struct apply + : long_<35> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<35> > + : size_impl< aux::vector_tag<35> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<35> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35 + > +struct vector36 +{ + typedef aux::vector_tag<36> tag; + typedef vector36 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + + + typedef void_ item36; + typedef T35 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,36 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<35> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector36< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<36> > +{ + template< typename Vector > struct apply + { + typedef vector35< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<35> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector36< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<36> > +{ + template< typename Vector > struct apply + { + typedef vector35< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<36> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item36 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<36> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<36> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<36> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<36> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<36> > +{ + template< typename Vector > struct apply + : long_<36> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<36> > + : size_impl< aux::vector_tag<36> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<36> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36 + > +struct vector37 +{ + typedef aux::vector_tag<37> tag; + typedef vector37 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + + + typedef void_ item37; + typedef T36 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,37 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<36> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector37< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<37> > +{ + template< typename Vector > struct apply + { + typedef vector36< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<36> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector37< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<37> > +{ + template< typename Vector > struct apply + { + typedef vector36< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<37> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item37 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<37> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<37> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<37> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<37> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<37> > +{ + template< typename Vector > struct apply + : long_<37> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<37> > + : size_impl< aux::vector_tag<37> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<37> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37 + > +struct vector38 +{ + typedef aux::vector_tag<38> tag; + typedef vector38 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + + + typedef void_ item38; + typedef T37 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,38 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<37> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector38< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<38> > +{ + template< typename Vector > struct apply + { + typedef vector37< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<37> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector38< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<38> > +{ + template< typename Vector > struct apply + { + typedef vector37< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<38> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item38 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<38> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<38> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<38> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<38> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<38> > +{ + template< typename Vector > struct apply + : long_<38> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<38> > + : size_impl< aux::vector_tag<38> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<38> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38 + > +struct vector39 +{ + typedef aux::vector_tag<39> tag; + typedef vector39 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + + + typedef void_ item39; + typedef T38 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,39 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<38> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector39< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<39> > +{ + template< typename Vector > struct apply + { + typedef vector38< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<38> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector39< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<39> > +{ + template< typename Vector > struct apply + { + typedef vector38< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<39> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item39 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<39> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<39> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<39> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<39> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<39> > +{ + template< typename Vector > struct apply + : long_<39> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<39> > + : size_impl< aux::vector_tag<39> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<39> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + > +struct vector40 +{ + typedef aux::vector_tag<40> tag; + typedef vector40 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + + + typedef void_ item40; + typedef T39 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,40 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<39> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector40< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<40> > +{ + template< typename Vector > struct apply + { + typedef vector39< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<39> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector40< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<40> > +{ + template< typename Vector > struct apply + { + typedef vector39< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<40> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item40 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<40> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<40> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<40> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<40> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<40> > +{ + template< typename Vector > struct apply + : long_<40> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<40> > + : size_impl< aux::vector_tag<40> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<40> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/no_ctps/vector40_c.hpp b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector40_c.hpp new file mode 100644 index 00000000..ba0ffa88 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector40_c.hpp @@ -0,0 +1,281 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector40_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + > +struct vector31_c + : vector31< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + > +{ + typedef vector31_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31 + > +struct vector32_c + : vector32< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 >, integral_c + > +{ + typedef vector32_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32 + > +struct vector33_c + : vector33< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 > + > +{ + typedef vector33_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33 + > +struct vector34_c + : vector34< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + > +{ + typedef vector34_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34 + > +struct vector35_c + : vector35< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 >, integral_c + > +{ + typedef vector35_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35 + > +struct vector36_c + : vector36< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 > + > +{ + typedef vector36_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36 + > +struct vector37_c + : vector37< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + > +{ + typedef vector37_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37 + > +struct vector38_c + : vector38< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 >, integral_c + > +{ + typedef vector38_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38 + > +struct vector39_c + : vector39< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 > + > +{ + typedef vector39_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39 + > +struct vector40_c + : vector40< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + > +{ + typedef vector40_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/no_ctps/vector50.hpp b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector50.hpp new file mode 100644 index 00000000..3da323a9 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector50.hpp @@ -0,0 +1,2764 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector50.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40 + > +struct vector41 +{ + typedef aux::vector_tag<41> tag; + typedef vector41 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + + + typedef void_ item41; + typedef T40 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,41 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<40> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector41< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<41> > +{ + template< typename Vector > struct apply + { + typedef vector40< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<40> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector41< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<41> > +{ + template< typename Vector > struct apply + { + typedef vector40< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<41> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item41 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<41> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<41> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<41> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<41> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<41> > +{ + template< typename Vector > struct apply + : long_<41> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<41> > + : size_impl< aux::vector_tag<41> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<41> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41 + > +struct vector42 +{ + typedef aux::vector_tag<42> tag; + typedef vector42 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + + + typedef void_ item42; + typedef T41 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,42 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<41> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector42< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<42> > +{ + template< typename Vector > struct apply + { + typedef vector41< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<41> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector42< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<42> > +{ + template< typename Vector > struct apply + { + typedef vector41< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<42> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item42 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<42> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<42> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<42> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<42> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<42> > +{ + template< typename Vector > struct apply + : long_<42> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<42> > + : size_impl< aux::vector_tag<42> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<42> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42 + > +struct vector43 +{ + typedef aux::vector_tag<43> tag; + typedef vector43 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + + + typedef void_ item43; + typedef T42 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,43 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<42> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector43< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<43> > +{ + template< typename Vector > struct apply + { + typedef vector42< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<42> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector43< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<43> > +{ + template< typename Vector > struct apply + { + typedef vector42< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<43> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item43 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<43> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<43> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<43> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<43> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<43> > +{ + template< typename Vector > struct apply + : long_<43> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<43> > + : size_impl< aux::vector_tag<43> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<43> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43 + > +struct vector44 +{ + typedef aux::vector_tag<44> tag; + typedef vector44 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + + + typedef void_ item44; + typedef T43 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,44 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<43> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector44< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<44> > +{ + template< typename Vector > struct apply + { + typedef vector43< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<43> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector44< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<44> > +{ + template< typename Vector > struct apply + { + typedef vector43< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<44> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item44 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<44> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<44> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<44> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<44> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<44> > +{ + template< typename Vector > struct apply + : long_<44> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<44> > + : size_impl< aux::vector_tag<44> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<44> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + > +struct vector45 +{ + typedef aux::vector_tag<45> tag; + typedef vector45 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + typedef T44 item44; + + + typedef void_ item45; + typedef T44 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,45 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<44> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector45< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<45> > +{ + template< typename Vector > struct apply + { + typedef vector44< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43, typename Vector::item44 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<44> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector45< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<45> > +{ + template< typename Vector > struct apply + { + typedef vector44< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<45> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item45 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<45> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<45> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<45> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<45> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<45> > +{ + template< typename Vector > struct apply + : long_<45> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<45> > + : size_impl< aux::vector_tag<45> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<45> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45 + > +struct vector46 +{ + typedef aux::vector_tag<46> tag; + typedef vector46 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + typedef T44 item44; + typedef T45 item45; + + + typedef void_ item46; + typedef T45 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,46 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<45> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector46< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<46> > +{ + template< typename Vector > struct apply + { + typedef vector45< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43, typename Vector::item44 + , typename Vector::item45 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<45> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector46< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<46> > +{ + template< typename Vector > struct apply + { + typedef vector45< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<46> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item46 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<46> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<46> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<46> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<46> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<46> > +{ + template< typename Vector > struct apply + : long_<46> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<46> > + : size_impl< aux::vector_tag<46> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<46> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45, typename T46 + > +struct vector47 +{ + typedef aux::vector_tag<47> tag; + typedef vector47 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + typedef T44 item44; + typedef T45 item45; + typedef T46 item46; + + + typedef void_ item47; + typedef T46 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,47 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<46> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector47< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<47> > +{ + template< typename Vector > struct apply + { + typedef vector46< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43, typename Vector::item44 + , typename Vector::item45, typename Vector::item46 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<46> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector47< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<47> > +{ + template< typename Vector > struct apply + { + typedef vector46< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<47> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item47 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<47> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<47> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<47> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<47> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<47> > +{ + template< typename Vector > struct apply + : long_<47> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<47> > + : size_impl< aux::vector_tag<47> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<47> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45, typename T46, typename T47 + > +struct vector48 +{ + typedef aux::vector_tag<48> tag; + typedef vector48 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + typedef T44 item44; + typedef T45 item45; + typedef T46 item46; + typedef T47 item47; + + + typedef void_ item48; + typedef T47 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,48 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<47> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector48< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<48> > +{ + template< typename Vector > struct apply + { + typedef vector47< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43, typename Vector::item44 + , typename Vector::item45, typename Vector::item46 + , typename Vector::item47 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<47> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector48< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<48> > +{ + template< typename Vector > struct apply + { + typedef vector47< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<48> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item48 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<48> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<48> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<48> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<48> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<48> > +{ + template< typename Vector > struct apply + : long_<48> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<48> > + : size_impl< aux::vector_tag<48> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<48> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45, typename T46, typename T47, typename T48 + > +struct vector49 +{ + typedef aux::vector_tag<49> tag; + typedef vector49 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + typedef T44 item44; + typedef T45 item45; + typedef T46 item46; + typedef T47 item47; + typedef T48 item48; + + + typedef void_ item49; + typedef T48 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,49 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<48> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector49< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46, typename Vector::item47 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<49> > +{ + template< typename Vector > struct apply + { + typedef vector48< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43, typename Vector::item44 + , typename Vector::item45, typename Vector::item46 + , typename Vector::item47, typename Vector::item48 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<48> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector49< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46, typename Vector::item47 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<49> > +{ + template< typename Vector > struct apply + { + typedef vector48< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46, typename Vector::item47 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<49> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item49 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<49> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<49> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<49> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<49> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<49> > +{ + template< typename Vector > struct apply + : long_<49> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<49> > + : size_impl< aux::vector_tag<49> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<49> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45, typename T46, typename T47, typename T48, typename T49 + > +struct vector50 +{ + typedef aux::vector_tag<50> tag; + typedef vector50 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + typedef T44 item44; + typedef T45 item45; + typedef T46 item46; + typedef T47 item47; + typedef T48 item48; + typedef T49 item49; + + + typedef void_ item50; + typedef T49 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,50 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<49> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector50< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46, typename Vector::item47 + , typename Vector::item48 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<50> > +{ + template< typename Vector > struct apply + { + typedef vector49< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43, typename Vector::item44 + , typename Vector::item45, typename Vector::item46 + , typename Vector::item47, typename Vector::item48 + , typename Vector::item49 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<49> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector50< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46, typename Vector::item47 + , typename Vector::item48 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<50> > +{ + template< typename Vector > struct apply + { + typedef vector49< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46, typename Vector::item47 + , typename Vector::item48 + > type; + }; +}; + +namespace aux { +template<> struct v_at_impl<50> +{ + template< typename V_ > struct result_ + { + typedef typename V_::item50 type; + }; +}; + +} + +template<> +struct at_impl< aux::vector_tag<50> > +{ + template< typename V_, typename N > struct apply + { + typedef typename aux::v_at_impl + ::template result_::type type; + }; +}; + +template<> +struct front_impl< aux::vector_tag<50> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::item0 type; + }; +}; + +template<> +struct back_impl< aux::vector_tag<50> > +{ + template< typename Vector > struct apply + { + typedef typename Vector::back type; + }; +}; + +template<> +struct empty_impl< aux::vector_tag<50> > +{ + template< typename Vector > struct apply + : false_ + { + }; +}; + +template<> +struct size_impl< aux::vector_tag<50> > +{ + template< typename Vector > struct apply + : long_<50> + { + }; +}; + +template<> +struct O1_size_impl< aux::vector_tag<50> > + : size_impl< aux::vector_tag<50> > +{ +}; + +template<> +struct clear_impl< aux::vector_tag<50> > +{ + template< typename Vector > struct apply + { + typedef vector0<> type; + }; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/no_ctps/vector50_c.hpp b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector50_c.hpp new file mode 100644 index 00000000..e07f2b3a --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/no_ctps/vector50_c.hpp @@ -0,0 +1,325 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector50_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + > +struct vector41_c + : vector41< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 >, integral_c + > +{ + typedef vector41_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41 + > +struct vector42_c + : vector42< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 > + > +{ + typedef vector42_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42 + > +struct vector43_c + : vector43< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + > +{ + typedef vector43_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43 + > +struct vector44_c + : vector44< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 >, integral_c + > +{ + typedef vector44_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44 + > +struct vector45_c + : vector45< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + , integral_c< T,C43 >, integral_c< T,C44 > + > +{ + typedef vector45_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45 + > +struct vector46_c + : vector46< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + , integral_c< T,C43 >, integral_c< T,C44 >, integral_c< T,C45 > + > +{ + typedef vector46_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45, T C46 + > +struct vector47_c + : vector47< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + , integral_c< T,C43 >, integral_c< T,C44 >, integral_c< T,C45 >, integral_c + > +{ + typedef vector47_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45, T C46, T C47 + > +struct vector48_c + : vector48< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + , integral_c< T,C43 >, integral_c< T,C44 >, integral_c< T,C45 > + , integral_c< T,C46 >, integral_c< T,C47 > + > +{ + typedef vector48_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45, T C46, T C47, T C48 + > +struct vector49_c + : vector49< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + , integral_c< T,C43 >, integral_c< T,C44 >, integral_c< T,C45 > + , integral_c< T,C46 >, integral_c< T,C47 >, integral_c< T,C48 > + > +{ + typedef vector49_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45, T C46, T C47, T C48, T C49 + > +struct vector50_c + : vector50< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + , integral_c< T,C43 >, integral_c< T,C44 >, integral_c< T,C45 > + , integral_c< T,C46 >, integral_c< T,C47 >, integral_c< T,C48 >, integral_c + > +{ + typedef vector50_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/plain/vector10.hpp b/boost/mpl/vector/aux_/preprocessed/plain/vector10.hpp new file mode 100644 index 00000000..88bbd3b3 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/plain/vector10.hpp @@ -0,0 +1,829 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector10.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< typename V > +struct v_at< V,0 > +{ + typedef typename V::item0 type; +}; + +template< + typename T0 + > +struct vector1 +{ + typedef aux::vector_tag<1> tag; + typedef vector1 type; + typedef T0 item0; + typedef void_ item1; + typedef T0 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,1 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<0> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector1< + T + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<1> > +{ + template< typename Vector > struct apply + { + typedef vector0< + + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<0> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector1< + + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<1> > +{ + template< typename Vector > struct apply + { + typedef vector0< + + > type; + }; +}; + +template< typename V > +struct v_at< V,1 > +{ + typedef typename V::item1 type; +}; + +template< + typename T0, typename T1 + > +struct vector2 +{ + typedef aux::vector_tag<2> tag; + typedef vector2 type; + typedef T0 item0; + typedef T1 item1; + + + typedef void_ item2; + typedef T1 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,2 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<1> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector2< + T + , + typename Vector::item0 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<2> > +{ + template< typename Vector > struct apply + { + typedef vector1< + typename Vector::item1 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<1> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector2< + typename Vector::item0 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<2> > +{ + template< typename Vector > struct apply + { + typedef vector1< + typename Vector::item0 + > type; + }; +}; + +template< typename V > +struct v_at< V,2 > +{ + typedef typename V::item2 type; +}; + +template< + typename T0, typename T1, typename T2 + > +struct vector3 +{ + typedef aux::vector_tag<3> tag; + typedef vector3 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + + + typedef void_ item3; + typedef T2 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,3 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<2> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector3< + T + , + typename Vector::item0, typename Vector::item1 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<3> > +{ + template< typename Vector > struct apply + { + typedef vector2< + typename Vector::item1, typename Vector::item2 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<2> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector3< + typename Vector::item0, typename Vector::item1 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<3> > +{ + template< typename Vector > struct apply + { + typedef vector2< + typename Vector::item0, typename Vector::item1 + > type; + }; +}; + +template< typename V > +struct v_at< V,3 > +{ + typedef typename V::item3 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3 + > +struct vector4 +{ + typedef aux::vector_tag<4> tag; + typedef vector4 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + + + typedef void_ item4; + typedef T3 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,4 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<3> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector4< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<4> > +{ + template< typename Vector > struct apply + { + typedef vector3< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<3> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector4< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<4> > +{ + template< typename Vector > struct apply + { + typedef vector3< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2 + > type; + }; +}; + +template< typename V > +struct v_at< V,4 > +{ + typedef typename V::item4 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + > +struct vector5 +{ + typedef aux::vector_tag<5> tag; + typedef vector5 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + + + typedef void_ item5; + typedef T4 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,5 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<4> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector5< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<5> > +{ + template< typename Vector > struct apply + { + typedef vector4< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<4> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector5< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<5> > +{ + template< typename Vector > struct apply + { + typedef vector4< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + > type; + }; +}; + +template< typename V > +struct v_at< V,5 > +{ + typedef typename V::item5 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5 + > +struct vector6 +{ + typedef aux::vector_tag<6> tag; + typedef vector6 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + + + typedef void_ item6; + typedef T5 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,6 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<5> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector6< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<6> > +{ + template< typename Vector > struct apply + { + typedef vector5< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<5> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector6< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<6> > +{ + template< typename Vector > struct apply + { + typedef vector5< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4 + > type; + }; +}; + +template< typename V > +struct v_at< V,6 > +{ + typedef typename V::item6 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6 + > +struct vector7 +{ + typedef aux::vector_tag<7> tag; + typedef vector7 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + + + typedef void_ item7; + typedef T6 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,7 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<6> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector7< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<7> > +{ + template< typename Vector > struct apply + { + typedef vector6< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<6> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector7< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<7> > +{ + template< typename Vector > struct apply + { + typedef vector6< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + > type; + }; +}; + +template< typename V > +struct v_at< V,7 > +{ + typedef typename V::item7 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7 + > +struct vector8 +{ + typedef aux::vector_tag<8> tag; + typedef vector8 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + + + typedef void_ item8; + typedef T7 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,8 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<7> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector8< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<8> > +{ + template< typename Vector > struct apply + { + typedef vector7< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<7> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector8< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<8> > +{ + template< typename Vector > struct apply + { + typedef vector7< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6 + > type; + }; +}; + +template< typename V > +struct v_at< V,8 > +{ + typedef typename V::item8 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8 + > +struct vector9 +{ + typedef aux::vector_tag<9> tag; + typedef vector9 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + + + typedef void_ item9; + typedef T8 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,9 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<8> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector9< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<9> > +{ + template< typename Vector > struct apply + { + typedef vector8< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<8> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector9< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<9> > +{ + template< typename Vector > struct apply + { + typedef vector8< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + > type; + }; +}; + +template< typename V > +struct v_at< V,9 > +{ + typedef typename V::item9 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + > +struct vector10 +{ + typedef aux::vector_tag<10> tag; + typedef vector10 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + + + typedef void_ item10; + typedef T9 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,10 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<9> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector10< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<10> > +{ + template< typename Vector > struct apply + { + typedef vector9< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<9> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector10< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<10> > +{ + template< typename Vector > struct apply + { + typedef vector9< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8 + > type; + }; +}; + +template< typename V > +struct v_at< V,10 > +{ + typedef typename V::item10 type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/plain/vector10_c.hpp b/boost/mpl/vector/aux_/preprocessed/plain/vector10_c.hpp new file mode 100644 index 00000000..8b36f6a3 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/plain/vector10_c.hpp @@ -0,0 +1,149 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector10_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0 + > +struct vector1_c + : vector1< integral_c< T,C0 > > +{ + typedef vector1_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1 + > +struct vector2_c + : vector2< integral_c< T,C0 >, integral_c< T,C1 > > +{ + typedef vector2_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2 + > +struct vector3_c + : vector3< integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > > +{ + typedef vector3_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3 + > +struct vector4_c + : vector4< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 >, integral_c + > +{ + typedef vector4_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4 + > +struct vector5_c + : vector5< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 > + > +{ + typedef vector5_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5 + > +struct vector6_c + : vector6< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 > + > +{ + typedef vector6_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6 + > +struct vector7_c + : vector7< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c + > +{ + typedef vector7_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7 + > +struct vector8_c + : vector8< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 > + > +{ + typedef vector8_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8 + > +struct vector9_c + : vector9< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 > + > +{ + typedef vector9_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9 + > +struct vector10_c + : vector10< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + > +{ + typedef vector10_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/plain/vector20.hpp b/boost/mpl/vector/aux_/preprocessed/plain/vector20.hpp new file mode 100644 index 00000000..8c6c8bbb --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/plain/vector20.hpp @@ -0,0 +1,1144 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector20.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10 + > +struct vector11 +{ + typedef aux::vector_tag<11> tag; + typedef vector11 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + + + typedef void_ item11; + typedef T10 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,11 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<10> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector11< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<11> > +{ + template< typename Vector > struct apply + { + typedef vector10< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<10> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector11< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<11> > +{ + template< typename Vector > struct apply + { + typedef vector10< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + > type; + }; +}; + +template< typename V > +struct v_at< V,11 > +{ + typedef typename V::item11 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11 + > +struct vector12 +{ + typedef aux::vector_tag<12> tag; + typedef vector12 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + + + typedef void_ item12; + typedef T11 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,12 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<11> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector12< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<12> > +{ + template< typename Vector > struct apply + { + typedef vector11< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<11> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector12< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<12> > +{ + template< typename Vector > struct apply + { + typedef vector11< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10 + > type; + }; +}; + +template< typename V > +struct v_at< V,12 > +{ + typedef typename V::item12 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12 + > +struct vector13 +{ + typedef aux::vector_tag<13> tag; + typedef vector13 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + + + typedef void_ item13; + typedef T12 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,13 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<12> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector13< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<13> > +{ + template< typename Vector > struct apply + { + typedef vector12< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<12> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector13< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<13> > +{ + template< typename Vector > struct apply + { + typedef vector12< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + > type; + }; +}; + +template< typename V > +struct v_at< V,13 > +{ + typedef typename V::item13 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13 + > +struct vector14 +{ + typedef aux::vector_tag<14> tag; + typedef vector14 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + + + typedef void_ item14; + typedef T13 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,14 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<13> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector14< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<14> > +{ + template< typename Vector > struct apply + { + typedef vector13< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<13> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector14< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<14> > +{ + template< typename Vector > struct apply + { + typedef vector13< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12 + > type; + }; +}; + +template< typename V > +struct v_at< V,14 > +{ + typedef typename V::item14 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + > +struct vector15 +{ + typedef aux::vector_tag<15> tag; + typedef vector15 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + + + typedef void_ item15; + typedef T14 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,15 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<14> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector15< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<15> > +{ + template< typename Vector > struct apply + { + typedef vector14< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<14> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector15< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<15> > +{ + template< typename Vector > struct apply + { + typedef vector14< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + > type; + }; +}; + +template< typename V > +struct v_at< V,15 > +{ + typedef typename V::item15 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15 + > +struct vector16 +{ + typedef aux::vector_tag<16> tag; + typedef vector16 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + + + typedef void_ item16; + typedef T15 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,16 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<15> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector16< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<16> > +{ + template< typename Vector > struct apply + { + typedef vector15< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<15> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector16< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<16> > +{ + template< typename Vector > struct apply + { + typedef vector15< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14 + > type; + }; +}; + +template< typename V > +struct v_at< V,16 > +{ + typedef typename V::item16 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16 + > +struct vector17 +{ + typedef aux::vector_tag<17> tag; + typedef vector17 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + + + typedef void_ item17; + typedef T16 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,17 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<16> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector17< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<17> > +{ + template< typename Vector > struct apply + { + typedef vector16< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<16> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector17< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<17> > +{ + template< typename Vector > struct apply + { + typedef vector16< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + > type; + }; +}; + +template< typename V > +struct v_at< V,17 > +{ + typedef typename V::item17 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17 + > +struct vector18 +{ + typedef aux::vector_tag<18> tag; + typedef vector18 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + + + typedef void_ item18; + typedef T17 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,18 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<17> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector18< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<18> > +{ + template< typename Vector > struct apply + { + typedef vector17< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<17> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector18< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<18> > +{ + template< typename Vector > struct apply + { + typedef vector17< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16 + > type; + }; +}; + +template< typename V > +struct v_at< V,18 > +{ + typedef typename V::item18 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18 + > +struct vector19 +{ + typedef aux::vector_tag<19> tag; + typedef vector19 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + + + typedef void_ item19; + typedef T18 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,19 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<18> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector19< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<19> > +{ + template< typename Vector > struct apply + { + typedef vector18< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<18> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector19< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<19> > +{ + template< typename Vector > struct apply + { + typedef vector18< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + > type; + }; +}; + +template< typename V > +struct v_at< V,19 > +{ + typedef typename V::item19 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + > +struct vector20 +{ + typedef aux::vector_tag<20> tag; + typedef vector20 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + + + typedef void_ item20; + typedef T19 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,20 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<19> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector20< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<20> > +{ + template< typename Vector > struct apply + { + typedef vector19< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<19> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector20< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<20> > +{ + template< typename Vector > struct apply + { + typedef vector19< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18 + > type; + }; +}; + +template< typename V > +struct v_at< V,20 > +{ + typedef typename V::item20 type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/plain/vector20_c.hpp b/boost/mpl/vector/aux_/preprocessed/plain/vector20_c.hpp new file mode 100644 index 00000000..56ca53f4 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/plain/vector20_c.hpp @@ -0,0 +1,195 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector20_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + > +struct vector11_c + : vector11< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 >, integral_c + > +{ + typedef vector11_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11 + > +struct vector12_c + : vector12< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 > + > +{ + typedef vector12_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12 + > +struct vector13_c + : vector13< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + > +{ + typedef vector13_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13 + > +struct vector14_c + : vector14< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 >, integral_c + > +{ + typedef vector14_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14 + > +struct vector15_c + : vector15< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 > + > +{ + typedef vector15_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15 + > +struct vector16_c + : vector16< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + > +{ + typedef vector16_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16 + > +struct vector17_c + : vector17< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 >, integral_c + > +{ + typedef vector17_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17 + > +struct vector18_c + : vector18< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 > + > +{ + typedef vector18_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18 + > +struct vector19_c + : vector19< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + > +{ + typedef vector19_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19 + > +struct vector20_c + : vector20< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 >, integral_c + > +{ + typedef vector20_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/plain/vector30.hpp b/boost/mpl/vector/aux_/preprocessed/plain/vector30.hpp new file mode 100644 index 00000000..b7da8e76 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/plain/vector30.hpp @@ -0,0 +1,1464 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector30.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20 + > +struct vector21 +{ + typedef aux::vector_tag<21> tag; + typedef vector21 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + + + typedef void_ item21; + typedef T20 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,21 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<20> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector21< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<21> > +{ + template< typename Vector > struct apply + { + typedef vector20< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<20> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector21< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<21> > +{ + template< typename Vector > struct apply + { + typedef vector20< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + > type; + }; +}; + +template< typename V > +struct v_at< V,21 > +{ + typedef typename V::item21 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21 + > +struct vector22 +{ + typedef aux::vector_tag<22> tag; + typedef vector22 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + + + typedef void_ item22; + typedef T21 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,22 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<21> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector22< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<22> > +{ + template< typename Vector > struct apply + { + typedef vector21< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<21> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector22< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<22> > +{ + template< typename Vector > struct apply + { + typedef vector21< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20 + > type; + }; +}; + +template< typename V > +struct v_at< V,22 > +{ + typedef typename V::item22 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22 + > +struct vector23 +{ + typedef aux::vector_tag<23> tag; + typedef vector23 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + + + typedef void_ item23; + typedef T22 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,23 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<22> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector23< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<23> > +{ + template< typename Vector > struct apply + { + typedef vector22< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<22> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector23< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<23> > +{ + template< typename Vector > struct apply + { + typedef vector22< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + > type; + }; +}; + +template< typename V > +struct v_at< V,23 > +{ + typedef typename V::item23 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23 + > +struct vector24 +{ + typedef aux::vector_tag<24> tag; + typedef vector24 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + + + typedef void_ item24; + typedef T23 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,24 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<23> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector24< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<24> > +{ + template< typename Vector > struct apply + { + typedef vector23< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<23> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector24< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<24> > +{ + template< typename Vector > struct apply + { + typedef vector23< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22 + > type; + }; +}; + +template< typename V > +struct v_at< V,24 > +{ + typedef typename V::item24 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + > +struct vector25 +{ + typedef aux::vector_tag<25> tag; + typedef vector25 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + + + typedef void_ item25; + typedef T24 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,25 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<24> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector25< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<25> > +{ + template< typename Vector > struct apply + { + typedef vector24< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<24> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector25< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<25> > +{ + template< typename Vector > struct apply + { + typedef vector24< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + > type; + }; +}; + +template< typename V > +struct v_at< V,25 > +{ + typedef typename V::item25 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25 + > +struct vector26 +{ + typedef aux::vector_tag<26> tag; + typedef vector26 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + + + typedef void_ item26; + typedef T25 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,26 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<25> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector26< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<26> > +{ + template< typename Vector > struct apply + { + typedef vector25< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<25> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector26< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<26> > +{ + template< typename Vector > struct apply + { + typedef vector25< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24 + > type; + }; +}; + +template< typename V > +struct v_at< V,26 > +{ + typedef typename V::item26 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26 + > +struct vector27 +{ + typedef aux::vector_tag<27> tag; + typedef vector27 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + + + typedef void_ item27; + typedef T26 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,27 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<26> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector27< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<27> > +{ + template< typename Vector > struct apply + { + typedef vector26< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<26> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector27< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<27> > +{ + template< typename Vector > struct apply + { + typedef vector26< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + > type; + }; +}; + +template< typename V > +struct v_at< V,27 > +{ + typedef typename V::item27 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27 + > +struct vector28 +{ + typedef aux::vector_tag<28> tag; + typedef vector28 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + + + typedef void_ item28; + typedef T27 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,28 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<27> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector28< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<28> > +{ + template< typename Vector > struct apply + { + typedef vector27< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<27> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector28< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<28> > +{ + template< typename Vector > struct apply + { + typedef vector27< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26 + > type; + }; +}; + +template< typename V > +struct v_at< V,28 > +{ + typedef typename V::item28 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28 + > +struct vector29 +{ + typedef aux::vector_tag<29> tag; + typedef vector29 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + + + typedef void_ item29; + typedef T28 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,29 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<28> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector29< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<29> > +{ + template< typename Vector > struct apply + { + typedef vector28< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<28> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector29< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<29> > +{ + template< typename Vector > struct apply + { + typedef vector28< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + > type; + }; +}; + +template< typename V > +struct v_at< V,29 > +{ + typedef typename V::item29 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + > +struct vector30 +{ + typedef aux::vector_tag<30> tag; + typedef vector30 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + + + typedef void_ item30; + typedef T29 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,30 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<29> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector30< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<30> > +{ + template< typename Vector > struct apply + { + typedef vector29< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<29> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector30< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<30> > +{ + template< typename Vector > struct apply + { + typedef vector29< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28 + > type; + }; +}; + +template< typename V > +struct v_at< V,30 > +{ + typedef typename V::item30 type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/plain/vector30_c.hpp b/boost/mpl/vector/aux_/preprocessed/plain/vector30_c.hpp new file mode 100644 index 00000000..6251dbc5 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/plain/vector30_c.hpp @@ -0,0 +1,238 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector30_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + > +struct vector21_c + : vector21< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 > + > +{ + typedef vector21_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21 + > +struct vector22_c + : vector22< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + > +{ + typedef vector22_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22 + > +struct vector23_c + : vector23< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 >, integral_c + > +{ + typedef vector23_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23 + > +struct vector24_c + : vector24< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 > + > +{ + typedef vector24_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24 + > +struct vector25_c + : vector25< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + > +{ + typedef vector25_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25 + > +struct vector26_c + : vector26< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 >, integral_c + > +{ + typedef vector26_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26 + > +struct vector27_c + : vector27< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 > + > +{ + typedef vector27_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27 + > +struct vector28_c + : vector28< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + > +{ + typedef vector28_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28 + > +struct vector29_c + : vector29< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 >, integral_c + > +{ + typedef vector29_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29 + > +struct vector30_c + : vector30< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 > + > +{ + typedef vector30_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/plain/vector40.hpp b/boost/mpl/vector/aux_/preprocessed/plain/vector40.hpp new file mode 100644 index 00000000..7487be4b --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/plain/vector40.hpp @@ -0,0 +1,1784 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector40.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30 + > +struct vector31 +{ + typedef aux::vector_tag<31> tag; + typedef vector31 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + + + typedef void_ item31; + typedef T30 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,31 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<30> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector31< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<31> > +{ + template< typename Vector > struct apply + { + typedef vector30< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<30> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector31< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<31> > +{ + template< typename Vector > struct apply + { + typedef vector30< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + > type; + }; +}; + +template< typename V > +struct v_at< V,31 > +{ + typedef typename V::item31 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31 + > +struct vector32 +{ + typedef aux::vector_tag<32> tag; + typedef vector32 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + + + typedef void_ item32; + typedef T31 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,32 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<31> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector32< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<32> > +{ + template< typename Vector > struct apply + { + typedef vector31< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<31> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector32< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<32> > +{ + template< typename Vector > struct apply + { + typedef vector31< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30 + > type; + }; +}; + +template< typename V > +struct v_at< V,32 > +{ + typedef typename V::item32 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32 + > +struct vector33 +{ + typedef aux::vector_tag<33> tag; + typedef vector33 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + + + typedef void_ item33; + typedef T32 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,33 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<32> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector33< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<33> > +{ + template< typename Vector > struct apply + { + typedef vector32< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<32> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector33< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<33> > +{ + template< typename Vector > struct apply + { + typedef vector32< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + > type; + }; +}; + +template< typename V > +struct v_at< V,33 > +{ + typedef typename V::item33 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33 + > +struct vector34 +{ + typedef aux::vector_tag<34> tag; + typedef vector34 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + + + typedef void_ item34; + typedef T33 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,34 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<33> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector34< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<34> > +{ + template< typename Vector > struct apply + { + typedef vector33< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<33> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector34< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<34> > +{ + template< typename Vector > struct apply + { + typedef vector33< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32 + > type; + }; +}; + +template< typename V > +struct v_at< V,34 > +{ + typedef typename V::item34 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + > +struct vector35 +{ + typedef aux::vector_tag<35> tag; + typedef vector35 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + + + typedef void_ item35; + typedef T34 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,35 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<34> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector35< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<35> > +{ + template< typename Vector > struct apply + { + typedef vector34< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<34> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector35< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<35> > +{ + template< typename Vector > struct apply + { + typedef vector34< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + > type; + }; +}; + +template< typename V > +struct v_at< V,35 > +{ + typedef typename V::item35 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35 + > +struct vector36 +{ + typedef aux::vector_tag<36> tag; + typedef vector36 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + + + typedef void_ item36; + typedef T35 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,36 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<35> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector36< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<36> > +{ + template< typename Vector > struct apply + { + typedef vector35< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<35> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector36< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<36> > +{ + template< typename Vector > struct apply + { + typedef vector35< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34 + > type; + }; +}; + +template< typename V > +struct v_at< V,36 > +{ + typedef typename V::item36 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36 + > +struct vector37 +{ + typedef aux::vector_tag<37> tag; + typedef vector37 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + + + typedef void_ item37; + typedef T36 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,37 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<36> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector37< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<37> > +{ + template< typename Vector > struct apply + { + typedef vector36< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<36> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector37< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<37> > +{ + template< typename Vector > struct apply + { + typedef vector36< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + > type; + }; +}; + +template< typename V > +struct v_at< V,37 > +{ + typedef typename V::item37 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37 + > +struct vector38 +{ + typedef aux::vector_tag<38> tag; + typedef vector38 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + + + typedef void_ item38; + typedef T37 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,38 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<37> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector38< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<38> > +{ + template< typename Vector > struct apply + { + typedef vector37< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<37> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector38< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<38> > +{ + template< typename Vector > struct apply + { + typedef vector37< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36 + > type; + }; +}; + +template< typename V > +struct v_at< V,38 > +{ + typedef typename V::item38 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38 + > +struct vector39 +{ + typedef aux::vector_tag<39> tag; + typedef vector39 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + + + typedef void_ item39; + typedef T38 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,39 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<38> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector39< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<39> > +{ + template< typename Vector > struct apply + { + typedef vector38< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<38> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector39< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<39> > +{ + template< typename Vector > struct apply + { + typedef vector38< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + > type; + }; +}; + +template< typename V > +struct v_at< V,39 > +{ + typedef typename V::item39 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + > +struct vector40 +{ + typedef aux::vector_tag<40> tag; + typedef vector40 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + + + typedef void_ item40; + typedef T39 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,40 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<39> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector40< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<40> > +{ + template< typename Vector > struct apply + { + typedef vector39< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<39> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector40< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<40> > +{ + template< typename Vector > struct apply + { + typedef vector39< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38 + > type; + }; +}; + +template< typename V > +struct v_at< V,40 > +{ + typedef typename V::item40 type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/plain/vector40_c.hpp b/boost/mpl/vector/aux_/preprocessed/plain/vector40_c.hpp new file mode 100644 index 00000000..ba0ffa88 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/plain/vector40_c.hpp @@ -0,0 +1,281 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector40_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + > +struct vector31_c + : vector31< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + > +{ + typedef vector31_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31 + > +struct vector32_c + : vector32< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 >, integral_c + > +{ + typedef vector32_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32 + > +struct vector33_c + : vector33< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 > + > +{ + typedef vector33_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33 + > +struct vector34_c + : vector34< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + > +{ + typedef vector34_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34 + > +struct vector35_c + : vector35< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 >, integral_c + > +{ + typedef vector35_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35 + > +struct vector36_c + : vector36< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 > + > +{ + typedef vector36_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36 + > +struct vector37_c + : vector37< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + > +{ + typedef vector37_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37 + > +struct vector38_c + : vector38< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 >, integral_c + > +{ + typedef vector38_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38 + > +struct vector39_c + : vector39< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 > + > +{ + typedef vector39_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39 + > +struct vector40_c + : vector40< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + > +{ + typedef vector40_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/plain/vector50.hpp b/boost/mpl/vector/aux_/preprocessed/plain/vector50.hpp new file mode 100644 index 00000000..5a4c6d75 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/plain/vector50.hpp @@ -0,0 +1,2104 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector50.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40 + > +struct vector41 +{ + typedef aux::vector_tag<41> tag; + typedef vector41 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + + + typedef void_ item41; + typedef T40 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,41 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<40> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector41< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<41> > +{ + template< typename Vector > struct apply + { + typedef vector40< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<40> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector41< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<41> > +{ + template< typename Vector > struct apply + { + typedef vector40< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + > type; + }; +}; + +template< typename V > +struct v_at< V,41 > +{ + typedef typename V::item41 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41 + > +struct vector42 +{ + typedef aux::vector_tag<42> tag; + typedef vector42 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + + + typedef void_ item42; + typedef T41 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,42 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<41> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector42< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<42> > +{ + template< typename Vector > struct apply + { + typedef vector41< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<41> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector42< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<42> > +{ + template< typename Vector > struct apply + { + typedef vector41< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40 + > type; + }; +}; + +template< typename V > +struct v_at< V,42 > +{ + typedef typename V::item42 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42 + > +struct vector43 +{ + typedef aux::vector_tag<43> tag; + typedef vector43 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + + + typedef void_ item43; + typedef T42 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,43 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<42> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector43< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<43> > +{ + template< typename Vector > struct apply + { + typedef vector42< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<42> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector43< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<43> > +{ + template< typename Vector > struct apply + { + typedef vector42< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + > type; + }; +}; + +template< typename V > +struct v_at< V,43 > +{ + typedef typename V::item43 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43 + > +struct vector44 +{ + typedef aux::vector_tag<44> tag; + typedef vector44 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + + + typedef void_ item44; + typedef T43 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,44 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<43> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector44< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<44> > +{ + template< typename Vector > struct apply + { + typedef vector43< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<43> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector44< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<44> > +{ + template< typename Vector > struct apply + { + typedef vector43< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42 + > type; + }; +}; + +template< typename V > +struct v_at< V,44 > +{ + typedef typename V::item44 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + > +struct vector45 +{ + typedef aux::vector_tag<45> tag; + typedef vector45 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + typedef T44 item44; + + + typedef void_ item45; + typedef T44 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,45 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<44> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector45< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<45> > +{ + template< typename Vector > struct apply + { + typedef vector44< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43, typename Vector::item44 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<44> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector45< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<45> > +{ + template< typename Vector > struct apply + { + typedef vector44< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + > type; + }; +}; + +template< typename V > +struct v_at< V,45 > +{ + typedef typename V::item45 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45 + > +struct vector46 +{ + typedef aux::vector_tag<46> tag; + typedef vector46 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + typedef T44 item44; + typedef T45 item45; + + + typedef void_ item46; + typedef T45 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,46 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<45> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector46< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<46> > +{ + template< typename Vector > struct apply + { + typedef vector45< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43, typename Vector::item44 + , typename Vector::item45 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<45> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector46< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<46> > +{ + template< typename Vector > struct apply + { + typedef vector45< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44 + > type; + }; +}; + +template< typename V > +struct v_at< V,46 > +{ + typedef typename V::item46 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45, typename T46 + > +struct vector47 +{ + typedef aux::vector_tag<47> tag; + typedef vector47 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + typedef T44 item44; + typedef T45 item45; + typedef T46 item46; + + + typedef void_ item47; + typedef T46 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,47 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<46> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector47< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<47> > +{ + template< typename Vector > struct apply + { + typedef vector46< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43, typename Vector::item44 + , typename Vector::item45, typename Vector::item46 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<46> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector47< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<47> > +{ + template< typename Vector > struct apply + { + typedef vector46< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + > type; + }; +}; + +template< typename V > +struct v_at< V,47 > +{ + typedef typename V::item47 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45, typename T46, typename T47 + > +struct vector48 +{ + typedef aux::vector_tag<48> tag; + typedef vector48 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + typedef T44 item44; + typedef T45 item45; + typedef T46 item46; + typedef T47 item47; + + + typedef void_ item48; + typedef T47 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,48 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<47> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector48< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<48> > +{ + template< typename Vector > struct apply + { + typedef vector47< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43, typename Vector::item44 + , typename Vector::item45, typename Vector::item46 + , typename Vector::item47 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<47> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector48< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<48> > +{ + template< typename Vector > struct apply + { + typedef vector47< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46 + > type; + }; +}; + +template< typename V > +struct v_at< V,48 > +{ + typedef typename V::item48 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45, typename T46, typename T47, typename T48 + > +struct vector49 +{ + typedef aux::vector_tag<49> tag; + typedef vector49 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + typedef T44 item44; + typedef T45 item45; + typedef T46 item46; + typedef T47 item47; + typedef T48 item48; + + + typedef void_ item49; + typedef T48 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,49 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<48> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector49< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46, typename Vector::item47 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<49> > +{ + template< typename Vector > struct apply + { + typedef vector48< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43, typename Vector::item44 + , typename Vector::item45, typename Vector::item46 + , typename Vector::item47, typename Vector::item48 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<48> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector49< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46, typename Vector::item47 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<49> > +{ + template< typename Vector > struct apply + { + typedef vector48< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46, typename Vector::item47 + > type; + }; +}; + +template< typename V > +struct v_at< V,49 > +{ + typedef typename V::item49 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45, typename T46, typename T47, typename T48, typename T49 + > +struct vector50 +{ + typedef aux::vector_tag<50> tag; + typedef vector50 type; + typedef T0 item0; + typedef T1 item1; + typedef T2 item2; + typedef T3 item3; + typedef T4 item4; + typedef T5 item5; + typedef T6 item6; + typedef T7 item7; + typedef T8 item8; + typedef T9 item9; + typedef T10 item10; + typedef T11 item11; + typedef T12 item12; + typedef T13 item13; + typedef T14 item14; + typedef T15 item15; + typedef T16 item16; + typedef T17 item17; + typedef T18 item18; + typedef T19 item19; + typedef T20 item20; + typedef T21 item21; + typedef T22 item22; + typedef T23 item23; + typedef T24 item24; + typedef T25 item25; + typedef T26 item26; + typedef T27 item27; + typedef T28 item28; + typedef T29 item29; + typedef T30 item30; + typedef T31 item31; + typedef T32 item32; + typedef T33 item33; + typedef T34 item34; + typedef T35 item35; + typedef T36 item36; + typedef T37 item37; + typedef T38 item38; + typedef T39 item39; + typedef T40 item40; + typedef T41 item41; + typedef T42 item42; + typedef T43 item43; + typedef T44 item44; + typedef T45 item45; + typedef T46 item46; + typedef T47 item47; + typedef T48 item48; + typedef T49 item49; + + + typedef void_ item50; + typedef T49 back; + typedef v_iter< type,0 > begin; + typedef v_iter< type,50 > end; +}; + +template<> +struct push_front_impl< aux::vector_tag<49> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector50< + T + , + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46, typename Vector::item47 + , typename Vector::item48 + > type; + }; +}; + +template<> +struct pop_front_impl< aux::vector_tag<50> > +{ + template< typename Vector > struct apply + { + typedef vector49< + typename Vector::item1, typename Vector::item2 + , typename Vector::item3, typename Vector::item4 + , typename Vector::item5, typename Vector::item6 + , typename Vector::item7, typename Vector::item8 + , typename Vector::item9, typename Vector::item10 + , typename Vector::item11, typename Vector::item12 + , typename Vector::item13, typename Vector::item14 + , typename Vector::item15, typename Vector::item16 + , typename Vector::item17, typename Vector::item18 + , typename Vector::item19, typename Vector::item20 + , typename Vector::item21, typename Vector::item22 + , typename Vector::item23, typename Vector::item24 + , typename Vector::item25, typename Vector::item26 + , typename Vector::item27, typename Vector::item28 + , typename Vector::item29, typename Vector::item30 + , typename Vector::item31, typename Vector::item32 + , typename Vector::item33, typename Vector::item34 + , typename Vector::item35, typename Vector::item36 + , typename Vector::item37, typename Vector::item38 + , typename Vector::item39, typename Vector::item40 + , typename Vector::item41, typename Vector::item42 + , typename Vector::item43, typename Vector::item44 + , typename Vector::item45, typename Vector::item46 + , typename Vector::item47, typename Vector::item48 + , typename Vector::item49 + > type; + }; +}; + +template<> +struct push_back_impl< aux::vector_tag<49> > +{ + template< typename Vector, typename T > struct apply + { + typedef vector50< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46, typename Vector::item47 + , typename Vector::item48 + , + T + > type; + }; +}; + +template<> +struct pop_back_impl< aux::vector_tag<50> > +{ + template< typename Vector > struct apply + { + typedef vector49< + typename Vector::item0, typename Vector::item1 + , typename Vector::item2, typename Vector::item3 + , typename Vector::item4, typename Vector::item5 + , typename Vector::item6, typename Vector::item7 + , typename Vector::item8, typename Vector::item9 + , typename Vector::item10, typename Vector::item11 + , typename Vector::item12, typename Vector::item13 + , typename Vector::item14, typename Vector::item15 + , typename Vector::item16, typename Vector::item17 + , typename Vector::item18, typename Vector::item19 + , typename Vector::item20, typename Vector::item21 + , typename Vector::item22, typename Vector::item23 + , typename Vector::item24, typename Vector::item25 + , typename Vector::item26, typename Vector::item27 + , typename Vector::item28, typename Vector::item29 + , typename Vector::item30, typename Vector::item31 + , typename Vector::item32, typename Vector::item33 + , typename Vector::item34, typename Vector::item35 + , typename Vector::item36, typename Vector::item37 + , typename Vector::item38, typename Vector::item39 + , typename Vector::item40, typename Vector::item41 + , typename Vector::item42, typename Vector::item43 + , typename Vector::item44, typename Vector::item45 + , typename Vector::item46, typename Vector::item47 + , typename Vector::item48 + > type; + }; +}; + +template< typename V > +struct v_at< V,50 > +{ + typedef typename V::item50 type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/plain/vector50_c.hpp b/boost/mpl/vector/aux_/preprocessed/plain/vector50_c.hpp new file mode 100644 index 00000000..e07f2b3a --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/plain/vector50_c.hpp @@ -0,0 +1,325 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector50_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + > +struct vector41_c + : vector41< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 >, integral_c + > +{ + typedef vector41_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41 + > +struct vector42_c + : vector42< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 > + > +{ + typedef vector42_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42 + > +struct vector43_c + : vector43< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + > +{ + typedef vector43_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43 + > +struct vector44_c + : vector44< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 >, integral_c + > +{ + typedef vector44_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44 + > +struct vector45_c + : vector45< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + , integral_c< T,C43 >, integral_c< T,C44 > + > +{ + typedef vector45_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45 + > +struct vector46_c + : vector46< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + , integral_c< T,C43 >, integral_c< T,C44 >, integral_c< T,C45 > + > +{ + typedef vector46_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45, T C46 + > +struct vector47_c + : vector47< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + , integral_c< T,C43 >, integral_c< T,C44 >, integral_c< T,C45 >, integral_c + > +{ + typedef vector47_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45, T C46, T C47 + > +struct vector48_c + : vector48< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + , integral_c< T,C43 >, integral_c< T,C44 >, integral_c< T,C45 > + , integral_c< T,C46 >, integral_c< T,C47 > + > +{ + typedef vector48_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45, T C46, T C47, T C48 + > +struct vector49_c + : vector49< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + , integral_c< T,C43 >, integral_c< T,C44 >, integral_c< T,C45 > + , integral_c< T,C46 >, integral_c< T,C47 >, integral_c< T,C48 > + > +{ + typedef vector49_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45, T C46, T C47, T C48, T C49 + > +struct vector50_c + : vector50< + integral_c< T,C0 >, integral_c< T,C1 >, integral_c< T,C2 > + , integral_c< T,C3 >, integral_c< T,C4 >, integral_c< T,C5 >, integral_c< T,C6 > + , integral_c< T,C7 >, integral_c< T,C8 >, integral_c< T,C9 > + , integral_c< T,C10 >, integral_c< T,C11 >, integral_c< T,C12 > + , integral_c< T,C13 >, integral_c< T,C14 >, integral_c< T,C15 > + , integral_c< T,C16 >, integral_c< T,C17 >, integral_c< T,C18 > + , integral_c< T,C19 >, integral_c< T,C20 >, integral_c< T,C21 > + , integral_c< T,C22 >, integral_c< T,C23 >, integral_c< T,C24 > + , integral_c< T,C25 >, integral_c< T,C26 >, integral_c< T,C27 > + , integral_c< T,C28 >, integral_c< T,C29 >, integral_c< T,C30 > + , integral_c< T,C31 >, integral_c< T,C32 >, integral_c< T,C33 > + , integral_c< T,C34 >, integral_c< T,C35 >, integral_c< T,C36 > + , integral_c< T,C37 >, integral_c< T,C38 >, integral_c< T,C39 > + , integral_c< T,C40 >, integral_c< T,C41 >, integral_c< T,C42 > + , integral_c< T,C43 >, integral_c< T,C44 >, integral_c< T,C45 > + , integral_c< T,C46 >, integral_c< T,C47 >, integral_c< T,C48 >, integral_c + > +{ + typedef vector50_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/typeof_based/vector10.hpp b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector10.hpp new file mode 100644 index 00000000..e4c64070 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector10.hpp @@ -0,0 +1,139 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector10.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T0 + > +struct vector1 + : v_item< + T0 + , vector0< > + > +{ + typedef vector1 type; +}; + +template< + typename T0, typename T1 + > +struct vector2 + : v_item< + T1 + , vector1 + > +{ + typedef vector2 type; +}; + +template< + typename T0, typename T1, typename T2 + > +struct vector3 + : v_item< + T2 + , vector2< T0,T1 > + > +{ + typedef vector3 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3 + > +struct vector4 + : v_item< + T3 + , vector3< T0,T1,T2 > + > +{ + typedef vector4 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + > +struct vector5 + : v_item< + T4 + , vector4< T0,T1,T2,T3 > + > +{ + typedef vector5 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5 + > +struct vector6 + : v_item< + T5 + , vector5< T0,T1,T2,T3,T4 > + > +{ + typedef vector6 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6 + > +struct vector7 + : v_item< + T6 + , vector6< T0,T1,T2,T3,T4,T5 > + > +{ + typedef vector7 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7 + > +struct vector8 + : v_item< + T7 + , vector7< T0,T1,T2,T3,T4,T5,T6 > + > +{ + typedef vector8 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8 + > +struct vector9 + : v_item< + T8 + , vector8< T0,T1,T2,T3,T4,T5,T6,T7 > + > +{ + typedef vector9 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + > +struct vector10 + : v_item< + T9 + , vector9< T0,T1,T2,T3,T4,T5,T6,T7,T8 > + > +{ + typedef vector10 type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/typeof_based/vector10_c.hpp b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector10_c.hpp new file mode 100644 index 00000000..18eabc64 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector10_c.hpp @@ -0,0 +1,154 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector10_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0 + > +struct vector1_c + : v_item< + integral_c< T,C0 > + , vector0_c + > +{ + typedef vector1_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1 + > +struct vector2_c + : v_item< + integral_c< T,C1 > + , vector1_c< T,C0 > + > +{ + typedef vector2_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2 + > +struct vector3_c + : v_item< + integral_c< T,C2 > + , vector2_c< T,C0,C1 > + > +{ + typedef vector3_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3 + > +struct vector4_c + : v_item< + integral_c< T,C3 > + , vector3_c< T,C0,C1,C2 > + > +{ + typedef vector4_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4 + > +struct vector5_c + : v_item< + integral_c< T,C4 > + , vector4_c< T,C0,C1,C2,C3 > + > +{ + typedef vector5_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5 + > +struct vector6_c + : v_item< + integral_c< T,C5 > + , vector5_c< T,C0,C1,C2,C3,C4 > + > +{ + typedef vector6_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6 + > +struct vector7_c + : v_item< + integral_c< T,C6 > + , vector6_c< T,C0,C1,C2,C3,C4,C5 > + > +{ + typedef vector7_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7 + > +struct vector8_c + : v_item< + integral_c< T,C7 > + , vector7_c< T,C0,C1,C2,C3,C4,C5,C6 > + > +{ + typedef vector8_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8 + > +struct vector9_c + : v_item< + integral_c< T,C8 > + , vector8_c< T,C0,C1,C2,C3,C4,C5,C6,C7 > + > +{ + typedef vector9_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9 + > +struct vector10_c + : v_item< + integral_c< T,C9 > + , vector9_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8 > + > +{ + typedef vector10_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/typeof_based/vector20.hpp b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector20.hpp new file mode 100644 index 00000000..78ccac4e --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector20.hpp @@ -0,0 +1,159 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector20.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10 + > +struct vector11 + : v_item< + T10 + , vector10< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9 > + > +{ + typedef vector11 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11 + > +struct vector12 + : v_item< + T11 + , vector11< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10 > + > +{ + typedef vector12 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12 + > +struct vector13 + : v_item< + T12 + , vector12< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11 > + > +{ + typedef vector13 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13 + > +struct vector14 + : v_item< + T13 + , vector13< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12 > + > +{ + typedef vector14 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + > +struct vector15 + : v_item< + T14 + , vector14< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13 > + > +{ + typedef vector15 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15 + > +struct vector16 + : v_item< + T15 + , vector15< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14 > + > +{ + typedef vector16 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16 + > +struct vector17 + : v_item< + T16 + , vector16< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15 > + > +{ + typedef vector17 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17 + > +struct vector18 + : v_item< + T17 + , vector17< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16 > + > +{ + typedef vector18 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18 + > +struct vector19 + : v_item< + T18 + , vector18< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17 > + > +{ + typedef vector19 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + > +struct vector20 + : v_item< + T19 + , vector19< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18 > + > +{ + typedef vector20 type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/typeof_based/vector20_c.hpp b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector20_c.hpp new file mode 100644 index 00000000..4bf67423 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector20_c.hpp @@ -0,0 +1,163 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector20_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + > +struct vector11_c + : v_item< + integral_c< T,C10 > + , vector10_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9 > + > +{ + typedef vector11_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11 + > +struct vector12_c + : v_item< + integral_c< T,C11 > + , vector11_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10 > + > +{ + typedef vector12_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12 + > +struct vector13_c + : v_item< + integral_c< T,C12 > + , vector12_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11 > + > +{ + typedef vector13_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13 + > +struct vector14_c + : v_item< + integral_c< T,C13 > + , vector13_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12 > + > +{ + typedef vector14_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14 + > +struct vector15_c + : v_item< + integral_c< T,C14 > + , vector14_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13 > + > +{ + typedef vector15_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15 + > +struct vector16_c + : v_item< + integral_c< T,C15 > + , vector15_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14 > + > +{ + typedef vector16_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16 + > +struct vector17_c + : v_item< + integral_c< T,C16 > + , vector16_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15 > + > +{ + typedef vector17_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17 + > +struct vector18_c + : v_item< + integral_c< T,C17 > + , vector17_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16 > + > +{ + typedef vector18_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18 + > +struct vector19_c + : v_item< + integral_c< T,C18 > + , vector18_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17 > + > +{ + typedef vector19_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19 + > +struct vector20_c + : v_item< + integral_c< T,C19 > + , vector19_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18 > + > +{ + typedef vector20_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/typeof_based/vector30.hpp b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector30.hpp new file mode 100644 index 00000000..c4049906 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector30.hpp @@ -0,0 +1,179 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector30.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20 + > +struct vector21 + : v_item< + T20 + , vector20< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19 > + > +{ + typedef vector21 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21 + > +struct vector22 + : v_item< + T21 + , vector21< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20 > + > +{ + typedef vector22 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22 + > +struct vector23 + : v_item< + T22 + , vector22< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21 > + > +{ + typedef vector23 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23 + > +struct vector24 + : v_item< + T23 + , vector23< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22 > + > +{ + typedef vector24 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + > +struct vector25 + : v_item< + T24 + , vector24< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23 > + > +{ + typedef vector25 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25 + > +struct vector26 + : v_item< + T25 + , vector25< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24 > + > +{ + typedef vector26 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26 + > +struct vector27 + : v_item< + T26 + , vector26< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25 > + > +{ + typedef vector27 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27 + > +struct vector28 + : v_item< + T27 + , vector27< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26 > + > +{ + typedef vector28 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28 + > +struct vector29 + : v_item< + T28 + , vector28< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27 > + > +{ + typedef vector29 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + > +struct vector30 + : v_item< + T29 + , vector29< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28 > + > +{ + typedef vector30 type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/typeof_based/vector30_c.hpp b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector30_c.hpp new file mode 100644 index 00000000..5741bb4b --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector30_c.hpp @@ -0,0 +1,173 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector30_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + > +struct vector21_c + : v_item< + integral_c< T,C20 > + , vector20_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19 > + > +{ + typedef vector21_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21 + > +struct vector22_c + : v_item< + integral_c< T,C21 > + , vector21_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20 > + > +{ + typedef vector22_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22 + > +struct vector23_c + : v_item< + integral_c< T,C22 > + , vector22_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21 > + > +{ + typedef vector23_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23 + > +struct vector24_c + : v_item< + integral_c< T,C23 > + , vector23_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22 > + > +{ + typedef vector24_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24 + > +struct vector25_c + : v_item< + integral_c< T,C24 > + , vector24_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23 > + > +{ + typedef vector25_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25 + > +struct vector26_c + : v_item< + integral_c< T,C25 > + , vector25_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24 > + > +{ + typedef vector26_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26 + > +struct vector27_c + : v_item< + integral_c< T,C26 > + , vector26_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25 > + > +{ + typedef vector27_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27 + > +struct vector28_c + : v_item< + integral_c< T,C27 > + , vector27_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26 > + > +{ + typedef vector28_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28 + > +struct vector29_c + : v_item< + integral_c< T,C28 > + , vector28_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27 > + > +{ + typedef vector29_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29 + > +struct vector30_c + : v_item< + integral_c< T,C29 > + , vector29_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28 > + > +{ + typedef vector30_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/typeof_based/vector40.hpp b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector40.hpp new file mode 100644 index 00000000..debcf702 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector40.hpp @@ -0,0 +1,199 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector40.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30 + > +struct vector31 + : v_item< + T30 + , vector30< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29 > + > +{ + typedef vector31 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31 + > +struct vector32 + : v_item< + T31 + , vector31< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30 > + > +{ + typedef vector32 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32 + > +struct vector33 + : v_item< + T32 + , vector32< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31 > + > +{ + typedef vector33 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33 + > +struct vector34 + : v_item< + T33 + , vector33< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32 > + > +{ + typedef vector34 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + > +struct vector35 + : v_item< + T34 + , vector34< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33 > + > +{ + typedef vector35 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35 + > +struct vector36 + : v_item< + T35 + , vector35< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34 > + > +{ + typedef vector36 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36 + > +struct vector37 + : v_item< + T36 + , vector36< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35 > + > +{ + typedef vector37 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37 + > +struct vector38 + : v_item< + T37 + , vector37< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36 > + > +{ + typedef vector38 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38 + > +struct vector39 + : v_item< + T38 + , vector38< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37 > + > +{ + typedef vector39 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + > +struct vector40 + : v_item< + T39 + , vector39< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38 > + > +{ + typedef vector40 type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/typeof_based/vector40_c.hpp b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector40_c.hpp new file mode 100644 index 00000000..88d742e0 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector40_c.hpp @@ -0,0 +1,183 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector40_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + > +struct vector31_c + : v_item< + integral_c< T,C30 > + , vector30_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29 > + > +{ + typedef vector31_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31 + > +struct vector32_c + : v_item< + integral_c< T,C31 > + , vector31_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30 > + > +{ + typedef vector32_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32 + > +struct vector33_c + : v_item< + integral_c< T,C32 > + , vector32_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31 > + > +{ + typedef vector33_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33 + > +struct vector34_c + : v_item< + integral_c< T,C33 > + , vector33_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32 > + > +{ + typedef vector34_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34 + > +struct vector35_c + : v_item< + integral_c< T,C34 > + , vector34_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33 > + > +{ + typedef vector35_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35 + > +struct vector36_c + : v_item< + integral_c< T,C35 > + , vector35_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34 > + > +{ + typedef vector36_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36 + > +struct vector37_c + : v_item< + integral_c< T,C36 > + , vector36_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35 > + > +{ + typedef vector37_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37 + > +struct vector38_c + : v_item< + integral_c< T,C37 > + , vector37_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36 > + > +{ + typedef vector38_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38 + > +struct vector39_c + : v_item< + integral_c< T,C38 > + , vector38_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37 > + > +{ + typedef vector39_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39 + > +struct vector40_c + : v_item< + integral_c< T,C39 > + , vector39_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38 > + > +{ + typedef vector40_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/typeof_based/vector50.hpp b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector50.hpp new file mode 100644 index 00000000..8db06df4 --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector50.hpp @@ -0,0 +1,219 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector50.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40 + > +struct vector41 + : v_item< + T40 + , vector40< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39 > + > +{ + typedef vector41 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41 + > +struct vector42 + : v_item< + T41 + , vector41< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40 > + > +{ + typedef vector42 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42 + > +struct vector43 + : v_item< + T42 + , vector42< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41 > + > +{ + typedef vector43 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43 + > +struct vector44 + : v_item< + T43 + , vector43< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42 > + > +{ + typedef vector44 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + > +struct vector45 + : v_item< + T44 + , vector44< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43 > + > +{ + typedef vector45 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45 + > +struct vector46 + : v_item< + T45 + , vector45< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44 > + > +{ + typedef vector46 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45, typename T46 + > +struct vector47 + : v_item< + T46 + , vector46< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45 > + > +{ + typedef vector47 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45, typename T46, typename T47 + > +struct vector48 + : v_item< + T47 + , vector47< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46 > + > +{ + typedef vector48 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45, typename T46, typename T47, typename T48 + > +struct vector49 + : v_item< + T48 + , vector48< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47 > + > +{ + typedef vector49 type; +}; + +template< + typename T0, typename T1, typename T2, typename T3, typename T4 + , typename T5, typename T6, typename T7, typename T8, typename T9 + , typename T10, typename T11, typename T12, typename T13, typename T14 + , typename T15, typename T16, typename T17, typename T18, typename T19 + , typename T20, typename T21, typename T22, typename T23, typename T24 + , typename T25, typename T26, typename T27, typename T28, typename T29 + , typename T30, typename T31, typename T32, typename T33, typename T34 + , typename T35, typename T36, typename T37, typename T38, typename T39 + , typename T40, typename T41, typename T42, typename T43, typename T44 + , typename T45, typename T46, typename T47, typename T48, typename T49 + > +struct vector50 + : v_item< + T49 + , vector49< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,T32,T33,T34,T35,T36,T37,T38,T39,T40,T41,T42,T43,T44,T45,T46,T47,T48 > + > +{ + typedef vector50 type; +}; + +}} diff --git a/boost/mpl/vector/aux_/preprocessed/typeof_based/vector50_c.hpp b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector50_c.hpp new file mode 100644 index 00000000..f56d6aff --- /dev/null +++ b/boost/mpl/vector/aux_/preprocessed/typeof_based/vector50_c.hpp @@ -0,0 +1,193 @@ + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// + +// Preprocessed version of "boost/mpl/vector/vector50_c.hpp" header +// -- DO NOT modify by hand! + +namespace boost { namespace mpl { + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + > +struct vector41_c + : v_item< + integral_c< T,C40 > + , vector40_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39 > + > +{ + typedef vector41_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41 + > +struct vector42_c + : v_item< + integral_c< T,C41 > + , vector41_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40 > + > +{ + typedef vector42_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42 + > +struct vector43_c + : v_item< + integral_c< T,C42 > + , vector42_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41 > + > +{ + typedef vector43_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43 + > +struct vector44_c + : v_item< + integral_c< T,C43 > + , vector43_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42 > + > +{ + typedef vector44_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44 + > +struct vector45_c + : v_item< + integral_c< T,C44 > + , vector44_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42,C43 > + > +{ + typedef vector45_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45 + > +struct vector46_c + : v_item< + integral_c< T,C45 > + , vector45_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42,C43,C44 > + > +{ + typedef vector46_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45, T C46 + > +struct vector47_c + : v_item< + integral_c< T,C46 > + , vector46_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42,C43,C44,C45 > + > +{ + typedef vector47_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45, T C46, T C47 + > +struct vector48_c + : v_item< + integral_c< T,C47 > + , vector47_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42,C43,C44,C45,C46 > + > +{ + typedef vector48_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45, T C46, T C47, T C48 + > +struct vector49_c + : v_item< + integral_c< T,C48 > + , vector48_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42,C43,C44,C45,C46,C47 > + > +{ + typedef vector49_c type; + typedef T value_type; +}; + +template< + typename T + , T C0, T C1, T C2, T C3, T C4, T C5, T C6, T C7, T C8, T C9, T C10 + , T C11, T C12, T C13, T C14, T C15, T C16, T C17, T C18, T C19, T C20 + , T C21, T C22, T C23, T C24, T C25, T C26, T C27, T C28, T C29, T C30 + , T C31, T C32, T C33, T C34, T C35, T C36, T C37, T C38, T C39, T C40 + , T C41, T C42, T C43, T C44, T C45, T C46, T C47, T C48, T C49 + > +struct vector50_c + : v_item< + integral_c< T,C49 > + , vector49_c< T,C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,C23,C24,C25,C26,C27,C28,C29,C30,C31,C32,C33,C34,C35,C36,C37,C38,C39,C40,C41,C42,C43,C44,C45,C46,C47,C48 > + > +{ + typedef vector50_c type; + typedef T value_type; +}; + +}} diff --git a/boost/mpl/vector/aux_/push_back.hpp b/boost/mpl/vector/aux_/push_back.hpp new file mode 100644 index 00000000..527828c9 --- /dev/null +++ b/boost/mpl/vector/aux_/push_back.hpp @@ -0,0 +1,40 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_PUSH_BACK_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_PUSH_BACK_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +# include +# include + +namespace boost { namespace mpl { + +template<> +struct push_back_impl< aux::vector_tag > +{ + template< typename Vector, typename T > struct apply + { + typedef v_item type; + }; +}; + +}} + +#endif + +#endif // BOOST_MPL_VECTOR_AUX_PUSH_BACK_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/push_front.hpp b/boost/mpl/vector/aux_/push_front.hpp new file mode 100644 index 00000000..f315de58 --- /dev/null +++ b/boost/mpl/vector/aux_/push_front.hpp @@ -0,0 +1,40 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_PUSH_FRONT_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_PUSH_FRONT_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +# include +# include + +namespace boost { namespace mpl { + +template<> +struct push_front_impl< aux::vector_tag > +{ + template< typename Vector, typename T > struct apply + { + typedef v_item type; + }; +}; + +}} + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +#endif // BOOST_MPL_VECTOR_AUX_PUSH_FRONT_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/size.hpp b/boost/mpl/vector/aux_/size.hpp new file mode 100644 index 00000000..c131e886 --- /dev/null +++ b/boost/mpl/vector/aux_/size.hpp @@ -0,0 +1,49 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_SIZE_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_SIZE_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include + +namespace boost { namespace mpl { + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + +template<> +struct size_impl< aux::vector_tag > + : O1_size_impl< aux::vector_tag > +{ +}; + +#else + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + +template< long N > +struct size_impl< aux::vector_tag > + : O1_size_impl< aux::vector_tag > +{ +}; + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES + +}} + +#endif // BOOST_MPL_VECTOR_AUX_SIZE_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/tag.hpp b/boost/mpl/vector/aux_/tag.hpp new file mode 100644 index 00000000..90d16e38 --- /dev/null +++ b/boost/mpl/vector/aux_/tag.hpp @@ -0,0 +1,32 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_TAG_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_TAG_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include + +namespace boost { namespace mpl { namespace aux { + +struct v_iter_tag; + +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) +struct vector_tag; +#else +template< BOOST_MPL_AUX_NTTP_DECL(long, N) > struct vector_tag; +#endif + +}}} + +#endif // BOOST_MPL_VECTOR_AUX_TAG_HPP_INCLUDED diff --git a/boost/mpl/vector/aux_/vector0.hpp b/boost/mpl/vector/aux_/vector0.hpp new file mode 100644 index 00000000..40266736 --- /dev/null +++ b/boost/mpl/vector/aux_/vector0.hpp @@ -0,0 +1,52 @@ + +#ifndef BOOST_MPL_VECTOR_AUX_VECTOR0_HPP_INCLUDED +#define BOOST_MPL_VECTOR_AUX_VECTOR0_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include + +#include +#include +#include + +namespace boost { namespace mpl { + +template< typename Dummy = na > struct vector0; + +template<> struct vector0 +{ +#if defined(BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES) + typedef aux::vector_tag tag; + typedef vector0 type; + typedef long_<32768> lower_bound_; + typedef lower_bound_ upper_bound_; + typedef long_<0> size; + + static aux::type_wrapper item_(...); +#else + typedef aux::vector_tag<0> tag; + typedef vector0 type; + typedef void_ item0; + + typedef v_iter,0> begin; + typedef v_iter,0> end; +#endif +}; + +}} + +#endif // BOOST_MPL_VECTOR_AUX_VECTOR0_HPP_INCLUDED diff --git a/boost/mpl/vector/vector0.hpp b/boost/mpl/vector/vector0.hpp new file mode 100644 index 00000000..39759ddc --- /dev/null +++ b/boost/mpl/vector/vector0.hpp @@ -0,0 +1,34 @@ + +#ifndef BOOST_MPL_VECTOR_VECTOR0_HPP_INCLUDED +#define BOOST_MPL_VECTOR_VECTOR0_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // BOOST_MPL_VECTOR_VECTOR0_HPP_INCLUDED diff --git a/boost/mpl/vector/vector0_c.hpp b/boost/mpl/vector/vector0_c.hpp new file mode 100644 index 00000000..0e60215d --- /dev/null +++ b/boost/mpl/vector/vector0_c.hpp @@ -0,0 +1,31 @@ + +#ifndef BOOST_MPL_VECTOR_VECTOR0_C_HPP_INCLUDED +#define BOOST_MPL_VECTOR_VECTOR0_C_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#include +#include + +namespace boost { namespace mpl { + +template< typename T > struct vector0_c + : vector0<> +{ + typedef vector0_c type; + typedef T value_type; +}; + +}} + +#endif // BOOST_MPL_VECTOR_VECTOR0_C_HPP_INCLUDED diff --git a/boost/mpl/vector/vector10.hpp b/boost/mpl/vector/vector10.hpp new file mode 100644 index 00000000..53a2a163 --- /dev/null +++ b/boost/mpl/vector/vector10.hpp @@ -0,0 +1,45 @@ + +#ifndef BOOST_MPL_VECTOR_VECTOR10_HPP_INCLUDED +#define BOOST_MPL_VECTOR_VECTOR10_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER vector10.hpp +# include + +#else + +# include +# include +# include + +namespace boost { namespace mpl { + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(0, 10, )) +# include BOOST_PP_ITERATE() + +}} + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS + +#endif // BOOST_MPL_VECTOR_VECTOR10_HPP_INCLUDED diff --git a/boost/mpl/vector/vector10_c.hpp b/boost/mpl/vector/vector10_c.hpp new file mode 100644 index 00000000..be52d2f7 --- /dev/null +++ b/boost/mpl/vector/vector10_c.hpp @@ -0,0 +1,46 @@ + +#ifndef BOOST_MPL_VECTOR_VECTOR10_C_HPP_INCLUDED +#define BOOST_MPL_VECTOR_VECTOR10_C_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +# include +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER vector10_c.hpp +# include + +#else + +# include +# include +# include + +namespace boost { namespace mpl { + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(1, 10, )) +# include BOOST_PP_ITERATE() + +}} + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS + +#endif // BOOST_MPL_VECTOR_VECTOR10_C_HPP_INCLUDED diff --git a/boost/mpl/vector/vector20.hpp b/boost/mpl/vector/vector20.hpp new file mode 100644 index 00000000..96d1b9f4 --- /dev/null +++ b/boost/mpl/vector/vector20.hpp @@ -0,0 +1,45 @@ + +#ifndef BOOST_MPL_VECTOR_VECTOR20_HPP_INCLUDED +#define BOOST_MPL_VECTOR_VECTOR20_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER vector20.hpp +# include + +#else + +# include +# include +# include + +namespace boost { namespace mpl { + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(11, 20, )) +# include BOOST_PP_ITERATE() + +}} + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS + +#endif // BOOST_MPL_VECTOR_VECTOR20_HPP_INCLUDED diff --git a/boost/mpl/vector/vector20_c.hpp b/boost/mpl/vector/vector20_c.hpp new file mode 100644 index 00000000..3913f260 --- /dev/null +++ b/boost/mpl/vector/vector20_c.hpp @@ -0,0 +1,46 @@ + +#ifndef BOOST_MPL_VECTOR_VECTOR20_C_HPP_INCLUDED +#define BOOST_MPL_VECTOR_VECTOR20_C_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +# include +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER vector20_c.hpp +# include + +#else + +# include +# include +# include + +namespace boost { namespace mpl { + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(11, 20, )) +# include BOOST_PP_ITERATE() + +}} + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS + +#endif // BOOST_MPL_VECTOR_VECTOR20_C_HPP_INCLUDED diff --git a/boost/mpl/vector/vector30.hpp b/boost/mpl/vector/vector30.hpp new file mode 100644 index 00000000..b2f0a5eb --- /dev/null +++ b/boost/mpl/vector/vector30.hpp @@ -0,0 +1,45 @@ + +#ifndef BOOST_MPL_VECTOR_VECTOR30_HPP_INCLUDED +#define BOOST_MPL_VECTOR_VECTOR30_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER vector30.hpp +# include + +#else + +# include +# include +# include + +namespace boost { namespace mpl { + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(21, 30, )) +# include BOOST_PP_ITERATE() + +}} + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS + +#endif // BOOST_MPL_VECTOR_VECTOR30_HPP_INCLUDED diff --git a/boost/mpl/vector/vector30_c.hpp b/boost/mpl/vector/vector30_c.hpp new file mode 100644 index 00000000..94cdab46 --- /dev/null +++ b/boost/mpl/vector/vector30_c.hpp @@ -0,0 +1,47 @@ + +#ifndef BOOST_MPL_VECTOR_VECTOR30_C_HPP_INCLUDED +#define BOOST_MPL_VECTOR_VECTOR30_C_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +# include +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER vector30_c.hpp +# include + +#else + +# include +# include +# include +# include + +namespace boost { namespace mpl { + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(21, 30, )) +# include BOOST_PP_ITERATE() + +}} + +#endif // BOOST_MPL_CFG_USE_PREPROCESSED_HEADERS + +#endif // BOOST_MPL_VECTOR_VECTOR30_C_HPP_INCLUDED diff --git a/boost/mpl/vector/vector40.hpp b/boost/mpl/vector/vector40.hpp new file mode 100644 index 00000000..2d2ef819 --- /dev/null +++ b/boost/mpl/vector/vector40.hpp @@ -0,0 +1,45 @@ + +#ifndef BOOST_MPL_VECTOR_VECTOR40_HPP_INCLUDED +#define BOOST_MPL_VECTOR_VECTOR40_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER vector40.hpp +# include + +#else + +# include +# include +# include + +namespace boost { namespace mpl { + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(31, 40, )) +# include BOOST_PP_ITERATE() + +}} + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS + +#endif // BOOST_MPL_VECTOR_VECTOR40_HPP_INCLUDED diff --git a/boost/mpl/vector/vector40_c.hpp b/boost/mpl/vector/vector40_c.hpp new file mode 100644 index 00000000..25e2ebf3 --- /dev/null +++ b/boost/mpl/vector/vector40_c.hpp @@ -0,0 +1,46 @@ + +#ifndef BOOST_MPL_VECTOR_VECTOR40_C_HPP_INCLUDED +#define BOOST_MPL_VECTOR_VECTOR40_C_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +# include +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER vector40_c.hpp +# include + +#else + +# include +# include +# include + +namespace boost { namespace mpl { + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(31, 40, )) +# include BOOST_PP_ITERATE() + +}} + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS + +#endif // BOOST_MPL_VECTOR_VECTOR40_C_HPP_INCLUDED diff --git a/boost/mpl/vector/vector50.hpp b/boost/mpl/vector/vector50.hpp new file mode 100644 index 00000000..dc2d5c20 --- /dev/null +++ b/boost/mpl/vector/vector50.hpp @@ -0,0 +1,45 @@ + +#ifndef BOOST_MPL_VECTOR_VECTOR50_HPP_INCLUDED +#define BOOST_MPL_VECTOR_VECTOR50_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER vector50.hpp +# include + +#else + +# include +# include +# include + +namespace boost { namespace mpl { + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(41, 50, )) +# include BOOST_PP_ITERATE() + +}} + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS + +#endif // BOOST_MPL_VECTOR_VECTOR50_HPP_INCLUDED diff --git a/boost/mpl/vector/vector50_c.hpp b/boost/mpl/vector/vector50_c.hpp new file mode 100644 index 00000000..7388bf40 --- /dev/null +++ b/boost/mpl/vector/vector50_c.hpp @@ -0,0 +1,46 @@ + +#ifndef BOOST_MPL_VECTOR_VECTOR50_C_HPP_INCLUDED +#define BOOST_MPL_VECTOR_VECTOR50_C_HPP_INCLUDED + +// Copyright Aleksey Gurtovoy 2000-2004 +// +// 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) +// +// See http://www.boost.org/libs/mpl for documentation. + +// $Id$ +// $Date$ +// $Revision$ + +#if !defined(BOOST_MPL_PREPROCESSING_MODE) +# include +# include +#endif + +#include + +#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \ + && !defined(BOOST_MPL_PREPROCESSING_MODE) + +# define BOOST_MPL_PREPROCESSED_HEADER vector50_c.hpp +# include + +#else + +# include +# include +# include + +namespace boost { namespace mpl { + +# define BOOST_PP_ITERATION_PARAMS_1 \ + (3,(41, 50, )) +# include BOOST_PP_ITERATE() + +}} + +#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS + +#endif // BOOST_MPL_VECTOR_VECTOR50_C_HPP_INCLUDED diff --git a/boost/predef.h b/boost/predef.h new file mode 100644 index 00000000..49653378 --- /dev/null +++ b/boost/predef.h @@ -0,0 +1,24 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#if !defined(BOOST_PREDEF_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS) +#ifndef BOOST_PREDEF_H +#define BOOST_PREDEF_H +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#endif diff --git a/boost/predef/architecture.h b/boost/predef/architecture.h new file mode 100644 index 00000000..b131a892 --- /dev/null +++ b/boost/predef/architecture.h @@ -0,0 +1,35 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#if !defined(BOOST_PREDEF_ARCHITECTURE_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS) +#ifndef BOOST_PREDEF_ARCHITECTURE_H +#define BOOST_PREDEF_ARCHITECTURE_H +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/boost/predef/architecture/alpha.h b/boost/predef/architecture/alpha.h new file mode 100644 index 00000000..64d3dad3 --- /dev/null +++ b/boost/predef/architecture/alpha.h @@ -0,0 +1,65 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_ALPHA_H +#define BOOST_PREDEF_ARCHITECTURE_ALPHA_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_ALPHA` + +http://en.wikipedia.org/wiki/DEC_Alpha[DEC Alpha] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} +| `+__alpha__+` | {predef_detection} +| `+__alpha+` | {predef_detection} +| `+_M_ALPHA+` | {predef_detection} + +| `+__alpha_ev4__+` | 4.0.0 +| `+__alpha_ev5__+` | 5.0.0 +| `+__alpha_ev6__+` | 6.0.0 +|=== +*/ // end::reference[] + +#define BOOST_ARCH_ALPHA BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__alpha__) || defined(__alpha) || \ + defined(_M_ALPHA) +# undef BOOST_ARCH_ALPHA +# if !defined(BOOST_ARCH_ALPHA) && defined(__alpha_ev4__) +# define BOOST_ARCH_ALPHA BOOST_VERSION_NUMBER(4,0,0) +# endif +# if !defined(BOOST_ARCH_ALPHA) && defined(__alpha_ev5__) +# define BOOST_ARCH_ALPHA BOOST_VERSION_NUMBER(5,0,0) +# endif +# if !defined(BOOST_ARCH_ALPHA) && defined(__alpha_ev6__) +# define BOOST_ARCH_ALPHA BOOST_VERSION_NUMBER(6,0,0) +# endif +# if !defined(BOOST_ARCH_ALPHA) +# define BOOST_ARCH_ALPHA BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_ARCH_ALPHA +# define BOOST_ARCH_ALPHA_AVAILABLE +#endif + +#if BOOST_ARCH_ALPHA +# undef BOOST_ARCH_WORD_BITS_64 +# define BOOST_ARCH_WORD_BITS_64 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_ALPHA_NAME "DEC Alpha" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_ALPHA,BOOST_ARCH_ALPHA_NAME) diff --git a/boost/predef/architecture/arm.h b/boost/predef/architecture/arm.h new file mode 100644 index 00000000..8ab20b2d --- /dev/null +++ b/boost/predef/architecture/arm.h @@ -0,0 +1,144 @@ +/* +Copyright Rene Rivera 2008-2019 +Copyright Franz Detro 2014 +Copyright (c) Microsoft Corporation 2014 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_ARM_H +#define BOOST_PREDEF_ARCHITECTURE_ARM_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_ARM` + +http://en.wikipedia.org/wiki/ARM_architecture[ARM] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__ARM_ARCH+` | {predef_detection} +| `+__TARGET_ARCH_ARM+` | {predef_detection} +| `+__TARGET_ARCH_THUMB+` | {predef_detection} +| `+_M_ARM+` | {predef_detection} +| `+__arm__+` | {predef_detection} +| `+__arm64+` | {predef_detection} +| `+__thumb__+` | {predef_detection} +| `+_M_ARM64+` | {predef_detection} +| `+__aarch64__+` | {predef_detection} +| `+__AARCH64EL__+` | {predef_detection} +| `+__ARM_ARCH_7__+` | {predef_detection} +| `+__ARM_ARCH_7A__+` | {predef_detection} +| `+__ARM_ARCH_7R__+` | {predef_detection} +| `+__ARM_ARCH_7M__+` | {predef_detection} +| `+__ARM_ARCH_6K__+` | {predef_detection} +| `+__ARM_ARCH_6Z__+` | {predef_detection} +| `+__ARM_ARCH_6KZ__+` | {predef_detection} +| `+__ARM_ARCH_6T2__+` | {predef_detection} +| `+__ARM_ARCH_5TE__+` | {predef_detection} +| `+__ARM_ARCH_5TEJ__+` | {predef_detection} +| `+__ARM_ARCH_4T__+` | {predef_detection} +| `+__ARM_ARCH_4__+` | {predef_detection} + +| `+__ARM_ARCH+` | V.0.0 +| `+__TARGET_ARCH_ARM+` | V.0.0 +| `+__TARGET_ARCH_THUMB+` | V.0.0 +| `+_M_ARM+` | V.0.0 +| `+__arm64+` | 8.0.0 +| `+_M_ARM64+` | 8.0.0 +| `+__aarch64__+` | 8.0.0 +| `+__AARCH64EL__+` | 8.0.0 +| `+__ARM_ARCH_7__+` | 7.0.0 +| `+__ARM_ARCH_7A__+` | 7.0.0 +| `+__ARM_ARCH_7R__+` | 7.0.0 +| `+__ARM_ARCH_7M__+` | 7.0.0 +| `+__ARM_ARCH_6K__+` | 6.0.0 +| `+__ARM_ARCH_6Z__+` | 6.0.0 +| `+__ARM_ARCH_6KZ__+` | 6.0.0 +| `+__ARM_ARCH_6T2__+` | 6.0.0 +| `+__ARM_ARCH_5TE__+` | 5.0.0 +| `+__ARM_ARCH_5TEJ__+` | 5.0.0 +| `+__ARM_ARCH_4T__+` | 4.0.0 +| `+__ARM_ARCH_4__+` | 4.0.0 +|=== +*/ // end::reference[] + +#define BOOST_ARCH_ARM BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if \ + defined(__ARM_ARCH) || defined(__TARGET_ARCH_ARM) || \ + defined(__TARGET_ARCH_THUMB) || defined(_M_ARM) || \ + defined(__arm__) || defined(__arm64) || defined(__thumb__) || \ + defined(_M_ARM64) || defined(__aarch64__) || defined(__AARCH64EL__) || \ + defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \ + defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || \ + defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \ + defined(__ARM_ARCH_6KZ__) || defined(__ARM_ARCH_6T2__) || \ + defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__) || \ + defined(__ARM_ARCH_4T__) || defined(__ARM_ARCH_4__) +# undef BOOST_ARCH_ARM +# if !defined(BOOST_ARCH_ARM) && defined(__ARM_ARCH) +# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(__ARM_ARCH,0,0) +# endif +# if !defined(BOOST_ARCH_ARM) && defined(__TARGET_ARCH_ARM) +# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(__TARGET_ARCH_ARM,0,0) +# endif +# if !defined(BOOST_ARCH_ARM) && defined(__TARGET_ARCH_THUMB) +# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(__TARGET_ARCH_THUMB,0,0) +# endif +# if !defined(BOOST_ARCH_ARM) && defined(_M_ARM) +# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(_M_ARM,0,0) +# endif +# if !defined(BOOST_ARCH_ARM) && ( \ + defined(__arm64) || defined(_M_ARM64) || defined(__aarch64__) || \ + defined(__AARCH64EL__) ) +# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(8,0,0) +# endif +# if !defined(BOOST_ARCH_ARM) && ( \ + defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \ + defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) ) +# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(7,0,0) +# endif +# if !defined(BOOST_ARCH_ARM) && ( \ + defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \ + defined(__ARM_ARCH_6KZ__) || defined(__ARM_ARCH_6T2__) ) +# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(6,0,0) +# endif +# if !defined(BOOST_ARCH_ARM) && ( \ + defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__) ) +# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(5,0,0) +# endif +# if !defined(BOOST_ARCH_ARM) && ( \ + defined(__ARM_ARCH_4T__) || defined(__ARM_ARCH_4__) ) +# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(4,0,0) +# endif +# if !defined(BOOST_ARCH_ARM) +# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_ARCH_ARM +# define BOOST_ARCH_ARM_AVAILABLE +#endif + +#if BOOST_ARCH_ARM +# if BOOST_ARCH_ARM >= BOOST_VERSION_NUMBER(8,0,0) +# undef BOOST_ARCH_WORD_BITS_64 +# define BOOST_ARCH_WORD_BITS_64 BOOST_VERSION_NUMBER_AVAILABLE +# else +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#define BOOST_ARCH_ARM_NAME "ARM" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_ARM,BOOST_ARCH_ARM_NAME) diff --git a/boost/predef/architecture/blackfin.h b/boost/predef/architecture/blackfin.h new file mode 100644 index 00000000..5c94b448 --- /dev/null +++ b/boost/predef/architecture/blackfin.h @@ -0,0 +1,52 @@ +/* +Copyright Rene Rivera 2013-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_BLACKFIN_H +#define BOOST_PREDEF_ARCHITECTURE_BLACKFIN_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_BLACKFIN` + +Blackfin Processors from Analog Devices. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__bfin__+` | {predef_detection} +| `+__BFIN__+` | {predef_detection} +| `bfin` | {predef_detection} +| `BFIN` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_ARCH_BLACKFIN BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__bfin__) || defined(__BFIN__) || \ + defined(bfin) || defined(BFIN) +# undef BOOST_ARCH_BLACKFIN +# define BOOST_ARCH_BLACKFIN BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_ARCH_BLACKFIN +# define BOOST_ARCH_BLACKFIN_AVAILABLE +#endif + +#if BOOST_ARCH_BLACKFIN +# undef BOOST_ARCH_WORD_BITS_16 +# define BOOST_ARCH_WORD_BITS_16 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_BLACKFIN_NAME "Blackfin" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_BLACKFIN,BOOST_ARCH_BLACKFIN_NAME) diff --git a/boost/predef/architecture/convex.h b/boost/predef/architecture/convex.h new file mode 100644 index 00000000..eb73d083 --- /dev/null +++ b/boost/predef/architecture/convex.h @@ -0,0 +1,71 @@ +/* +Copyright Rene Rivera 2011-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_CONVEX_H +#define BOOST_PREDEF_ARCHITECTURE_CONVEX_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_CONVEX` + +http://en.wikipedia.org/wiki/Convex_Computer[Convex Computer] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__convex__+` | {predef_detection} + +| `+__convex_c1__+` | 1.0.0 +| `+__convex_c2__+` | 2.0.0 +| `+__convex_c32__+` | 3.2.0 +| `+__convex_c34__+` | 3.4.0 +| `+__convex_c38__+` | 3.8.0 +|=== +*/ // end::reference[] + +#define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__convex__) +# undef BOOST_ARCH_CONVEX +# if !defined(BOOST_ARCH_CONVEX) && defined(__convex_c1__) +# define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER(1,0,0) +# endif +# if !defined(BOOST_ARCH_CONVEX) && defined(__convex_c2__) +# define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER(2,0,0) +# endif +# if !defined(BOOST_ARCH_CONVEX) && defined(__convex_c32__) +# define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER(3,2,0) +# endif +# if !defined(BOOST_ARCH_CONVEX) && defined(__convex_c34__) +# define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER(3,4,0) +# endif +# if !defined(BOOST_ARCH_CONVEX) && defined(__convex_c38__) +# define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER(3,8,0) +# endif +# if !defined(BOOST_ARCH_CONVEX) +# define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_ARCH_CONVEX +# define BOOST_ARCH_CONVEX_AVAILABLE +#endif + +#if BOOST_ARCH_CONVEX +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_CONVEX_NAME "Convex Computer" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_CONVEX,BOOST_ARCH_CONVEX_NAME) diff --git a/boost/predef/architecture/e2k.h b/boost/predef/architecture/e2k.h new file mode 100644 index 00000000..92edc9e2 --- /dev/null +++ b/boost/predef/architecture/e2k.h @@ -0,0 +1,54 @@ +/* +Copyright Konstantin Ivlev 2021 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_E2K_H +#define BOOST_PREDEF_ARCHITECTURE_E2K_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_E2K` + +https://en.wikipedia.org/wiki/Elbrus_2000[E2K] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__e2k__+` | {predef_detection} + +| `+__e2k__+` | V.0.0 +|=== +*/ // end::reference[] + +#define BOOST_ARCH_E2K BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__e2k__) +# undef BOOST_ARCH_E2K +# if !defined(BOOST_ARCH_E2K) && defined(__iset__) +# define BOOST_ARCH_E2K BOOST_VERSION_NUMBER(__iset__,0,0) +# endif +# if !defined(BOOST_ARCH_E2K) +# define BOOST_ARCH_E2K BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_ARCH_E2K +# define BOOST_ARCH_E2K_AVAILABLE +#endif + +#if BOOST_ARCH_E2K +# define BOOST_ARCH_WORD_BITS_64 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_E2K_NAME "E2K" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_E2K,BOOST_ARCH_E2K_NAME) diff --git a/boost/predef/architecture/ia64.h b/boost/predef/architecture/ia64.h new file mode 100644 index 00000000..1f4b58a0 --- /dev/null +++ b/boost/predef/architecture/ia64.h @@ -0,0 +1,55 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_IA64_H +#define BOOST_PREDEF_ARCHITECTURE_IA64_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_IA64` + +http://en.wikipedia.org/wiki/Ia64[Intel Itanium 64] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__ia64__+` | {predef_detection} +| `+_IA64+` | {predef_detection} +| `+__IA64__+` | {predef_detection} +| `+__ia64+` | {predef_detection} +| `+_M_IA64+` | {predef_detection} +| `+__itanium__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_ARCH_IA64 BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__ia64__) || defined(_IA64) || \ + defined(__IA64__) || defined(__ia64) || \ + defined(_M_IA64) || defined(__itanium__) +# undef BOOST_ARCH_IA64 +# define BOOST_ARCH_IA64 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_ARCH_IA64 +# define BOOST_ARCH_IA64_AVAILABLE +#endif + +#if BOOST_ARCH_IA64 +# undef BOOST_ARCH_WORD_BITS_64 +# define BOOST_ARCH_WORD_BITS_64 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_IA64_NAME "Intel Itanium 64" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_IA64,BOOST_ARCH_IA64_NAME) diff --git a/boost/predef/architecture/loongarch.h b/boost/predef/architecture/loongarch.h new file mode 100644 index 00000000..e3e163bd --- /dev/null +++ b/boost/predef/architecture/loongarch.h @@ -0,0 +1,41 @@ +/* +Copyright Zhang Na 2022 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_LOONGARCH_H +#define BOOST_PREDEF_ARCHITECTURE_LOONGARCH_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_LOONGARCH` + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__loongarch__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_ARCH_LOONGARCH BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__loongarch__) +# undef BOOST_ARCH_LOONGARCH +# define BOOST_ARCH_LOONGARCH BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_ARCH_LOONGARCH +# define BOOST_ARCH_LOONGARCH_AVAILABLE +#endif + +#define BOOST_ARCH_LOONGARCH_NAME "LoongArch" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_LOONGARCH,BOOST_ARCH_LOONGARCH_NAME) diff --git a/boost/predef/architecture/m68k.h b/boost/predef/architecture/m68k.h new file mode 100644 index 00000000..a5945378 --- /dev/null +++ b/boost/predef/architecture/m68k.h @@ -0,0 +1,88 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_M68K_H +#define BOOST_PREDEF_ARCHITECTURE_M68K_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_M68K` + +http://en.wikipedia.org/wiki/M68k[Motorola 68k] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__m68k__+` | {predef_detection} +| `M68000` | {predef_detection} + +| `+__mc68060__+` | 6.0.0 +| `mc68060` | 6.0.0 +| `+__mc68060+` | 6.0.0 +| `+__mc68040__+` | 4.0.0 +| `mc68040` | 4.0.0 +| `+__mc68040+` | 4.0.0 +| `+__mc68030__+` | 3.0.0 +| `mc68030` | 3.0.0 +| `+__mc68030+` | 3.0.0 +| `+__mc68020__+` | 2.0.0 +| `mc68020` | 2.0.0 +| `+__mc68020+` | 2.0.0 +| `+__mc68010__+` | 1.0.0 +| `mc68010` | 1.0.0 +| `+__mc68010+` | 1.0.0 +| `+__mc68000__+` | 0.0.1 +| `mc68000` | 0.0.1 +| `+__mc68000+` | 0.0.1 +|=== +*/ // end::reference[] + +#define BOOST_ARCH_M68K BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__m68k__) || defined(M68000) +# undef BOOST_ARCH_M68K +# if !defined(BOOST_ARCH_M68K) && (defined(__mc68060__) || defined(mc68060) || defined(__mc68060)) +# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER(6,0,0) +# endif +# if !defined(BOOST_ARCH_M68K) && (defined(__mc68040__) || defined(mc68040) || defined(__mc68040)) +# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER(4,0,0) +# endif +# if !defined(BOOST_ARCH_M68K) && (defined(__mc68030__) || defined(mc68030) || defined(__mc68030)) +# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER(3,0,0) +# endif +# if !defined(BOOST_ARCH_M68K) && (defined(__mc68020__) || defined(mc68020) || defined(__mc68020)) +# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER(2,0,0) +# endif +# if !defined(BOOST_ARCH_M68K) && (defined(__mc68010__) || defined(mc68010) || defined(__mc68010)) +# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER(1,0,0) +# endif +# if !defined(BOOST_ARCH_M68K) && (defined(__mc68000__) || defined(mc68000) || defined(__mc68000)) +# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER_AVAILABLE +# endif +# if !defined(BOOST_ARCH_M68K) +# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_ARCH_M68K +# define BOOST_ARCH_M68K_AVAILABLE +#endif + +#if BOOST_ARCH_M68K +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_M68K_NAME "Motorola 68k" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_M68K,BOOST_ARCH_M68K_NAME) diff --git a/boost/predef/architecture/mips.h b/boost/predef/architecture/mips.h new file mode 100644 index 00000000..e35d23ab --- /dev/null +++ b/boost/predef/architecture/mips.h @@ -0,0 +1,84 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_MIPS_H +#define BOOST_PREDEF_ARCHITECTURE_MIPS_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_MIPS` + +http://en.wikipedia.org/wiki/MIPS_architecture[MIPS] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__mips__+` | {predef_detection} +| `+__mips+` | {predef_detection} +| `+__MIPS__+` | {predef_detection} + +| `+__mips+` | V.0.0 +| `+_MIPS_ISA_MIPS1+` | 1.0.0 +| `+_R3000+` | 1.0.0 +| `+_MIPS_ISA_MIPS2+` | 2.0.0 +| `+__MIPS_ISA2__+` | 2.0.0 +| `+_R4000+` | 2.0.0 +| `+_MIPS_ISA_MIPS3+` | 3.0.0 +| `+__MIPS_ISA3__+` | 3.0.0 +| `+_MIPS_ISA_MIPS4+` | 4.0.0 +| `+__MIPS_ISA4__+` | 4.0.0 +|=== +*/ // end::reference[] + +#define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__mips__) || defined(__mips) || \ + defined(__MIPS__) +# undef BOOST_ARCH_MIPS +# if !defined(BOOST_ARCH_MIPS) && (defined(__mips)) +# define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER(__mips,0,0) +# endif +# if !defined(BOOST_ARCH_MIPS) && (defined(_MIPS_ISA_MIPS1) || defined(_R3000)) +# define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER(1,0,0) +# endif +# if !defined(BOOST_ARCH_MIPS) && (defined(_MIPS_ISA_MIPS2) || defined(__MIPS_ISA2__) || defined(_R4000)) +# define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER(2,0,0) +# endif +# if !defined(BOOST_ARCH_MIPS) && (defined(_MIPS_ISA_MIPS3) || defined(__MIPS_ISA3__)) +# define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER(3,0,0) +# endif +# if !defined(BOOST_ARCH_MIPS) && (defined(_MIPS_ISA_MIPS4) || defined(__MIPS_ISA4__)) +# define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER(4,0,0) +# endif +# if !defined(BOOST_ARCH_MIPS) +# define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_ARCH_MIPS +# define BOOST_ARCH_MIPS_AVAILABLE +#endif + +#if BOOST_ARCH_MIPS +# if BOOST_ARCH_MIPS >= BOOST_VERSION_NUMBER(3,0,0) +# undef BOOST_ARCH_WORD_BITS_64 +# define BOOST_ARCH_WORD_BITS_64 BOOST_VERSION_NUMBER_AVAILABLE +# else +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#define BOOST_ARCH_MIPS_NAME "MIPS" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_MIPS,BOOST_ARCH_MIPS_NAME) diff --git a/boost/predef/architecture/parisc.h b/boost/predef/architecture/parisc.h new file mode 100644 index 00000000..b93bfd9e --- /dev/null +++ b/boost/predef/architecture/parisc.h @@ -0,0 +1,70 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_PARISC_H +#define BOOST_PREDEF_ARCHITECTURE_PARISC_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_PARISC` + +http://en.wikipedia.org/wiki/PA-RISC_family[HP/PA RISC] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__hppa__+` | {predef_detection} +| `+__hppa+` | {predef_detection} +| `+__HPPA__+` | {predef_detection} + +| `+_PA_RISC1_0+` | 1.0.0 +| `+_PA_RISC1_1+` | 1.1.0 +| `+__HPPA11__+` | 1.1.0 +| `+__PA7100__+` | 1.1.0 +| `+_PA_RISC2_0+` | 2.0.0 +| `+__RISC2_0__+` | 2.0.0 +| `+__HPPA20__+` | 2.0.0 +| `+__PA8000__+` | 2.0.0 +|=== +*/ // end::reference[] + +#define BOOST_ARCH_PARISC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__hppa__) || defined(__hppa) || defined(__HPPA__) +# undef BOOST_ARCH_PARISC +# if !defined(BOOST_ARCH_PARISC) && (defined(_PA_RISC1_0)) +# define BOOST_ARCH_PARISC BOOST_VERSION_NUMBER(1,0,0) +# endif +# if !defined(BOOST_ARCH_PARISC) && (defined(_PA_RISC1_1) || defined(__HPPA11__) || defined(__PA7100__)) +# define BOOST_ARCH_PARISC BOOST_VERSION_NUMBER(1,1,0) +# endif +# if !defined(BOOST_ARCH_PARISC) && (defined(_PA_RISC2_0) || defined(__RISC2_0__) || defined(__HPPA20__) || defined(__PA8000__)) +# define BOOST_ARCH_PARISC BOOST_VERSION_NUMBER(2,0,0) +# endif +# if !defined(BOOST_ARCH_PARISC) +# define BOOST_ARCH_PARISC BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_ARCH_PARISC +# define BOOST_ARCH_PARISC_AVAILABLE +#endif + +#if BOOST_ARCH_PARISC +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_PARISC_NAME "HP/PA RISC" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_PARISC,BOOST_ARCH_PARISC_NAME) diff --git a/boost/predef/architecture/ppc.h b/boost/predef/architecture/ppc.h new file mode 100644 index 00000000..73d99f33 --- /dev/null +++ b/boost/predef/architecture/ppc.h @@ -0,0 +1,124 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_PPC_H +#define BOOST_PREDEF_ARCHITECTURE_PPC_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_PPC` + +http://en.wikipedia.org/wiki/PowerPC[PowerPC] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__powerpc+` | {predef_detection} +| `+__powerpc__+` | {predef_detection} +| `+__powerpc64__+` | {predef_detection} +| `+__POWERPC__+` | {predef_detection} +| `+__ppc__+` | {predef_detection} +| `+__ppc64__+` | {predef_detection} +| `+__PPC__+` | {predef_detection} +| `+__PPC64__+` | {predef_detection} +| `+_M_PPC+` | {predef_detection} +| `+_ARCH_PPC+` | {predef_detection} +| `+_ARCH_PPC64+` | {predef_detection} +| `+__PPCGECKO__+` | {predef_detection} +| `+__PPCBROADWAY__+` | {predef_detection} +| `+_XENON+` | {predef_detection} +| `+__ppc+` | {predef_detection} + +| `+__ppc601__+` | 6.1.0 +| `+_ARCH_601+` | 6.1.0 +| `+__ppc603__+` | 6.3.0 +| `+_ARCH_603+` | 6.3.0 +| `+__ppc604__+` | 6.4.0 +| `+__ppc604__+` | 6.4.0 +|=== +*/ // end::reference[] + +#define BOOST_ARCH_PPC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__) || \ + defined(__POWERPC__) || defined(__ppc__) || defined(__ppc64__) || \ + defined(__PPC__) || defined(__PPC64__) || \ + defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \ + defined(__PPCGECKO__) || defined(__PPCBROADWAY__) || \ + defined(_XENON) || \ + defined(__ppc) +# undef BOOST_ARCH_PPC +# if !defined (BOOST_ARCH_PPC) && (defined(__ppc601__) || defined(_ARCH_601)) +# define BOOST_ARCH_PPC BOOST_VERSION_NUMBER(6,1,0) +# endif +# if !defined (BOOST_ARCH_PPC) && (defined(__ppc603__) || defined(_ARCH_603)) +# define BOOST_ARCH_PPC BOOST_VERSION_NUMBER(6,3,0) +# endif +# if !defined (BOOST_ARCH_PPC) && (defined(__ppc604__) || defined(__ppc604__)) +# define BOOST_ARCH_PPC BOOST_VERSION_NUMBER(6,4,0) +# endif +# if !defined (BOOST_ARCH_PPC) +# define BOOST_ARCH_PPC BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_ARCH_PPC +# define BOOST_ARCH_PPC_AVAILABLE +#endif + +#define BOOST_ARCH_PPC_NAME "PowerPC" + + +/* tag::reference[] += `BOOST_ARCH_PPC_64` + +http://en.wikipedia.org/wiki/PowerPC[PowerPC] 64 bit architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__powerpc64__+` | {predef_detection} +| `+__ppc64__+` | {predef_detection} +| `+__PPC64__+` | {predef_detection} +| `+_ARCH_PPC64+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_ARCH_PPC_64 BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \ + defined(_ARCH_PPC64) +# undef BOOST_ARCH_PPC_64 +# define BOOST_ARCH_PPC_64 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_ARCH_PPC_64 +# define BOOST_ARCH_PPC_64_AVAILABLE +#endif + +#define BOOST_ARCH_PPC_64_NAME "PowerPC64" + + +#if BOOST_ARCH_PPC_64 +# undef BOOST_ARCH_WORD_BITS_64 +# define BOOST_ARCH_WORD_BITS_64 BOOST_VERSION_NUMBER_AVAILABLE +#else +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_PPC,BOOST_ARCH_PPC_NAME) + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_PPC_64,BOOST_ARCH_PPC_64_NAME) diff --git a/boost/predef/architecture/ptx.h b/boost/predef/architecture/ptx.h new file mode 100644 index 00000000..77372136 --- /dev/null +++ b/boost/predef/architecture/ptx.h @@ -0,0 +1,50 @@ +/* +Copyright Benjamin Worpitz 2018 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_PTX_H +#define BOOST_PREDEF_ARCHITECTURE_PTX_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_PTX` + +https://en.wikipedia.org/wiki/Parallel_Thread_Execution[PTX] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__CUDA_ARCH__+` | {predef_detection} + +| `+__CUDA_ARCH__+` | V.R.0 +|=== +*/ // end::reference[] + +#define BOOST_ARCH_PTX BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__CUDA_ARCH__) +# undef BOOST_ARCH_PTX +# define BOOST_ARCH_PTX BOOST_PREDEF_MAKE_10_VR0(__CUDA_ARCH__) +#endif + +#if BOOST_ARCH_PTX +# define BOOST_ARCH_PTX_AVAILABLE +#endif + +#if BOOST_ARCH_PTX +# undef BOOST_ARCH_WORD_BITS_64 +# define BOOST_ARCH_WORD_BITS_64 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_PTX_NAME "PTX" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_PTX,BOOST_ARCH_PTX_NAME) diff --git a/boost/predef/architecture/pyramid.h b/boost/predef/architecture/pyramid.h new file mode 100644 index 00000000..40c5359b --- /dev/null +++ b/boost/predef/architecture/pyramid.h @@ -0,0 +1,48 @@ +/* +Copyright Rene Rivera 2011-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_PYRAMID_H +#define BOOST_PREDEF_ARCHITECTURE_PYRAMID_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_PYRAMID` + +Pyramid 9810 architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `pyr` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_ARCH_PYRAMID BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(pyr) +# undef BOOST_ARCH_PYRAMID +# define BOOST_ARCH_PYRAMID BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_ARCH_PYRAMID +# define BOOST_ARCH_PYRAMID_AVAILABLE +#endif + +#if BOOST_ARCH_PYRAMID +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_PYRAMID_NAME "Pyramid 9810" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_PYRAMID,BOOST_ARCH_PYRAMID_NAME) diff --git a/boost/predef/architecture/riscv.h b/boost/predef/architecture/riscv.h new file mode 100644 index 00000000..8b819d77 --- /dev/null +++ b/boost/predef/architecture/riscv.h @@ -0,0 +1,48 @@ +/* +Copyright Andreas Schwab 2019 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_RISCV_H +#define BOOST_PREDEF_ARCHITECTURE_RISCV_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_RISCV` + +http://en.wikipedia.org/wiki/RISC-V[RISC-V] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__riscv+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_ARCH_RISCV BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__riscv) +# undef BOOST_ARCH_RISCV +# define BOOST_ARCH_RISCV BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_ARCH_RISCV +# define BOOST_ARCH_RISCV_AVAILABLE +#endif + +#if BOOST_ARCH_RISCV +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_RISCV_NAME "RISC-V" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_RISCV,BOOST_ARCH_RISCV_NAME) diff --git a/boost/predef/architecture/rs6k.h b/boost/predef/architecture/rs6k.h new file mode 100644 index 00000000..1c6d987d --- /dev/null +++ b/boost/predef/architecture/rs6k.h @@ -0,0 +1,67 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_RS6K_H +#define BOOST_PREDEF_ARCHITECTURE_RS6K_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_RS6000` + +http://en.wikipedia.org/wiki/RS/6000[RS/6000] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__THW_RS6000+` | {predef_detection} +| `+_IBMR2+` | {predef_detection} +| `+_POWER+` | {predef_detection} +| `+_ARCH_PWR+` | {predef_detection} +| `+_ARCH_PWR2+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_ARCH_RS6000 BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__THW_RS6000) || defined(_IBMR2) || \ + defined(_POWER) || defined(_ARCH_PWR) || \ + defined(_ARCH_PWR2) +# undef BOOST_ARCH_RS6000 +# define BOOST_ARCH_RS6000 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_ARCH_RS6000 +# define BOOST_ARCH_RS6000_AVAILABLE +#endif + +#if BOOST_ARCH_RS6000 +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_RS6000_NAME "RS/6000" + +#define BOOST_ARCH_PWR BOOST_ARCH_RS6000 + +#if BOOST_ARCH_PWR +# define BOOST_ARCH_PWR_AVAILABLE +#endif + +#if BOOST_ARCH_PWR +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_PWR_NAME BOOST_ARCH_RS6000_NAME + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_RS6000,BOOST_ARCH_RS6000_NAME) diff --git a/boost/predef/architecture/sparc.h b/boost/predef/architecture/sparc.h new file mode 100644 index 00000000..d01605e8 --- /dev/null +++ b/boost/predef/architecture/sparc.h @@ -0,0 +1,67 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_SPARC_H +#define BOOST_PREDEF_ARCHITECTURE_SPARC_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_SPARC` + +http://en.wikipedia.org/wiki/SPARC[SPARC] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__sparc__+` | {predef_detection} +| `+__sparc+` | {predef_detection} + +| `+__sparcv9+` | 9.0.0 +| `+__sparc_v9__+` | 9.0.0 +| `+__sparcv8+` | 8.0.0 +| `+__sparc_v8__+` | 8.0.0 +|=== +*/ // end::reference[] + +#define BOOST_ARCH_SPARC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__sparc__) || defined(__sparc) +# undef BOOST_ARCH_SPARC +# if !defined(BOOST_ARCH_SPARC) && (defined(__sparcv9) || defined(__sparc_v9__)) +# define BOOST_ARCH_SPARC BOOST_VERSION_NUMBER(9,0,0) +# endif +# if !defined(BOOST_ARCH_SPARC) && (defined(__sparcv8) || defined(__sparc_v8__)) +# define BOOST_ARCH_SPARC BOOST_VERSION_NUMBER(8,0,0) +# endif +# if !defined(BOOST_ARCH_SPARC) +# define BOOST_ARCH_SPARC BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_ARCH_SPARC +# define BOOST_ARCH_SPARC_AVAILABLE +#endif + +#if BOOST_ARCH_SPARC +# if BOOST_ARCH_SPARC >= BOOST_VERSION_NUMBER(9,0,0) +# undef BOOST_ARCH_WORD_BITS_64 +# define BOOST_ARCH_WORD_BITS_64 BOOST_VERSION_NUMBER_AVAILABLE +# else +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#define BOOST_ARCH_SPARC_NAME "SPARC" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_SPARC,BOOST_ARCH_SPARC_NAME) diff --git a/boost/predef/architecture/superh.h b/boost/predef/architecture/superh.h new file mode 100644 index 00000000..f72dc8b1 --- /dev/null +++ b/boost/predef/architecture/superh.h @@ -0,0 +1,81 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_SUPERH_H +#define BOOST_PREDEF_ARCHITECTURE_SUPERH_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_SH` + +http://en.wikipedia.org/wiki/SuperH[SuperH] architecture: +If available versions [1-5] are specifically detected. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__sh__+` | {predef_detection} + +| `+__SH5__+` | 5.0.0 +| `+__SH4__+` | 4.0.0 +| `+__sh3__+` | 3.0.0 +| `+__SH3__+` | 3.0.0 +| `+__sh2__+` | 2.0.0 +| `+__sh1__+` | 1.0.0 +|=== +*/ // end::reference[] + +#define BOOST_ARCH_SH BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__sh__) +# undef BOOST_ARCH_SH +# if !defined(BOOST_ARCH_SH) && (defined(__SH5__)) +# define BOOST_ARCH_SH BOOST_VERSION_NUMBER(5,0,0) +# endif +# if !defined(BOOST_ARCH_SH) && (defined(__SH4__)) +# define BOOST_ARCH_SH BOOST_VERSION_NUMBER(4,0,0) +# endif +# if !defined(BOOST_ARCH_SH) && (defined(__sh3__) || defined(__SH3__)) +# define BOOST_ARCH_SH BOOST_VERSION_NUMBER(3,0,0) +# endif +# if !defined(BOOST_ARCH_SH) && (defined(__sh2__)) +# define BOOST_ARCH_SH BOOST_VERSION_NUMBER(2,0,0) +# endif +# if !defined(BOOST_ARCH_SH) && (defined(__sh1__)) +# define BOOST_ARCH_SH BOOST_VERSION_NUMBER(1,0,0) +# endif +# if !defined(BOOST_ARCH_SH) +# define BOOST_ARCH_SH BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_ARCH_SH +# define BOOST_ARCH_SH_AVAILABLE +#endif + +#if BOOST_ARCH_SH +# if BOOST_ARCH_SH >= BOOST_VERSION_NUMBER(5,0,0) +# undef BOOST_ARCH_WORD_BITS_64 +# define BOOST_ARCH_WORD_BITS_64 BOOST_VERSION_NUMBER_AVAILABLE +# elif BOOST_ARCH_SH >= BOOST_VERSION_NUMBER(3,0,0) +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +# else +# undef BOOST_ARCH_WORD_BITS_16 +# define BOOST_ARCH_WORD_BITS_16 BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#define BOOST_ARCH_SH_NAME "SuperH" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_SH,BOOST_ARCH_SH_NAME) diff --git a/boost/predef/architecture/sys370.h b/boost/predef/architecture/sys370.h new file mode 100644 index 00000000..5500d253 --- /dev/null +++ b/boost/predef/architecture/sys370.h @@ -0,0 +1,49 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_SYS370_H +#define BOOST_PREDEF_ARCHITECTURE_SYS370_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_SYS370` + +http://en.wikipedia.org/wiki/System/370[System/370] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__370__+` | {predef_detection} +| `+__THW_370__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_ARCH_SYS370 BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__370__) || defined(__THW_370__) +# undef BOOST_ARCH_SYS370 +# define BOOST_ARCH_SYS370 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_ARCH_SYS370 +# define BOOST_ARCH_SYS370_AVAILABLE +#endif + +#if BOOST_ARCH_SYS370 +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_SYS370_NAME "System/370" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_SYS370,BOOST_ARCH_SYS370_NAME) diff --git a/boost/predef/architecture/sys390.h b/boost/predef/architecture/sys390.h new file mode 100644 index 00000000..9aba5685 --- /dev/null +++ b/boost/predef/architecture/sys390.h @@ -0,0 +1,49 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_SYS390_H +#define BOOST_PREDEF_ARCHITECTURE_SYS390_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_SYS390` + +http://en.wikipedia.org/wiki/System/390[System/390] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__s390__+` | {predef_detection} +| `+__s390x__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_ARCH_SYS390 BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__s390__) || defined(__s390x__) +# undef BOOST_ARCH_SYS390 +# define BOOST_ARCH_SYS390 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_ARCH_SYS390 +# define BOOST_ARCH_SYS390_AVAILABLE +#endif + +#if BOOST_ARCH_SYS390 +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_SYS390_NAME "System/390" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_SYS390,BOOST_ARCH_SYS390_NAME) diff --git a/boost/predef/architecture/x86.h b/boost/predef/architecture/x86.h new file mode 100644 index 00000000..9827ef3a --- /dev/null +++ b/boost/predef/architecture/x86.h @@ -0,0 +1,38 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#include +#include + +#ifndef BOOST_PREDEF_ARCHITECTURE_X86_H +#define BOOST_PREDEF_ARCHITECTURE_X86_H + +/* tag::reference[] += `BOOST_ARCH_X86` + +http://en.wikipedia.org/wiki/X86[Intel x86] architecture. This is +a category to indicate that either `BOOST_ARCH_X86_32` or +`BOOST_ARCH_X86_64` is detected. +*/ // end::reference[] + +#define BOOST_ARCH_X86 BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if BOOST_ARCH_X86_32 || BOOST_ARCH_X86_64 +# undef BOOST_ARCH_X86 +# define BOOST_ARCH_X86 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_ARCH_X86 +# define BOOST_ARCH_X86_AVAILABLE +#endif + +#define BOOST_ARCH_X86_NAME "Intel x86" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_X86,BOOST_ARCH_X86_NAME) diff --git a/boost/predef/architecture/x86/32.h b/boost/predef/architecture/x86/32.h new file mode 100644 index 00000000..b20fed9d --- /dev/null +++ b/boost/predef/architecture/x86/32.h @@ -0,0 +1,93 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_X86_32_H +#define BOOST_PREDEF_ARCHITECTURE_X86_32_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_X86_32` + +http://en.wikipedia.org/wiki/X86[Intel x86] architecture: +If available versions [3-6] are specifically detected. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `i386` | {predef_detection} +| `+__i386__+` | {predef_detection} +| `+__i486__+` | {predef_detection} +| `+__i586__+` | {predef_detection} +| `+__i686__+` | {predef_detection} +| `+__i386+` | {predef_detection} +| `+_M_IX86+` | {predef_detection} +| `+_X86_+` | {predef_detection} +| `+__THW_INTEL__+` | {predef_detection} +| `+__I86__+` | {predef_detection} +| `+__INTEL__+` | {predef_detection} + +| `+__I86__+` | V.0.0 +| `+_M_IX86+` | V.0.0 +| `+__i686__+` | 6.0.0 +| `+__i586__+` | 5.0.0 +| `+__i486__+` | 4.0.0 +| `+__i386__+` | 3.0.0 +|=== +*/ // end::reference[] + +#define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(i386) || defined(__i386__) || \ + defined(__i486__) || defined(__i586__) || \ + defined(__i686__) || defined(__i386) || \ + defined(_M_IX86) || defined(_X86_) || \ + defined(__THW_INTEL__) || defined(__I86__) || \ + defined(__INTEL__) +# undef BOOST_ARCH_X86_32 +# if !defined(BOOST_ARCH_X86_32) && defined(__I86__) +# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(__I86__,0,0) +# endif +# if !defined(BOOST_ARCH_X86_32) && defined(_M_IX86) +# define BOOST_ARCH_X86_32 BOOST_PREDEF_MAKE_10_VV00(_M_IX86) +# endif +# if !defined(BOOST_ARCH_X86_32) && defined(__i686__) +# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(6,0,0) +# endif +# if !defined(BOOST_ARCH_X86_32) && defined(__i586__) +# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(5,0,0) +# endif +# if !defined(BOOST_ARCH_X86_32) && defined(__i486__) +# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(4,0,0) +# endif +# if !defined(BOOST_ARCH_X86_32) && defined(__i386__) +# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(3,0,0) +# endif +# if !defined(BOOST_ARCH_X86_32) +# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_ARCH_X86_32 +# define BOOST_ARCH_X86_32_AVAILABLE +#endif + +#if BOOST_ARCH_X86_32 +# undef BOOST_ARCH_WORD_BITS_32 +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_X86_32_NAME "Intel x86-32" + +#include + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_X86_32,BOOST_ARCH_X86_32_NAME) diff --git a/boost/predef/architecture/x86/64.h b/boost/predef/architecture/x86/64.h new file mode 100644 index 00000000..6f59722b --- /dev/null +++ b/boost/predef/architecture/x86/64.h @@ -0,0 +1,56 @@ +/* +Copyright Rene Rivera 2008-2021 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_X86_64_H +#define BOOST_PREDEF_ARCHITECTURE_X86_64_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_X86_64` + +https://en.wikipedia.org/wiki/X86-64[X86-64] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__x86_64+` | {predef_detection} +| `+__x86_64__+` | {predef_detection} +| `+__amd64__+` | {predef_detection} +| `+__amd64+` | {predef_detection} +| `+_M_X64+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_ARCH_X86_64 BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__x86_64) || defined(__x86_64__) || \ + defined(__amd64__) || defined(__amd64) || \ + defined(_M_X64) +# undef BOOST_ARCH_X86_64 +# define BOOST_ARCH_X86_64 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_ARCH_X86_64 +# define BOOST_ARCH_X86_64_AVAILABLE +#endif + +#if BOOST_ARCH_X86_64 +# undef BOOST_ARCH_WORD_BITS_64 +# define BOOST_ARCH_WORD_BITS_64 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_X86_64_NAME "Intel x86-64" + +#include + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_X86_64,BOOST_ARCH_X86_64_NAME) diff --git a/boost/predef/architecture/z.h b/boost/predef/architecture/z.h new file mode 100644 index 00000000..a5f79796 --- /dev/null +++ b/boost/predef/architecture/z.h @@ -0,0 +1,48 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ARCHITECTURE_Z_H +#define BOOST_PREDEF_ARCHITECTURE_Z_H + +#include +#include + +/* tag::reference[] += `BOOST_ARCH_Z` + +http://en.wikipedia.org/wiki/Z/Architecture[z/Architecture] architecture. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__SYSC_ZARCH__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_ARCH_Z BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__SYSC_ZARCH__) +# undef BOOST_ARCH_Z +# define BOOST_ARCH_Z BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_ARCH_Z +# define BOOST_ARCH_Z_AVAILABLE +#endif + +#if BOOST_ARCH_Z +# undef BOOST_ARCH_WORD_BITS_64 +# define BOOST_ARCH_WORD_BITS_64 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#define BOOST_ARCH_Z_NAME "z/Architecture" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_Z,BOOST_ARCH_Z_NAME) diff --git a/boost/predef/compiler.h b/boost/predef/compiler.h new file mode 100644 index 00000000..de1b4ab5 --- /dev/null +++ b/boost/predef/compiler.h @@ -0,0 +1,44 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#if !defined(BOOST_PREDEF_COMPILER_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS) +#ifndef BOOST_PREDEF_COMPILER_H +#define BOOST_PREDEF_COMPILER_H +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/boost/predef/compiler/borland.h b/boost/predef/compiler/borland.h new file mode 100644 index 00000000..64daf909 --- /dev/null +++ b/boost/predef/compiler/borland.h @@ -0,0 +1,64 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_BORLAND_H +#define BOOST_PREDEF_COMPILER_BORLAND_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_BORLAND` + +http://en.wikipedia.org/wiki/C_plus_plus_builder[Borland {CPP}] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__BORLANDC__+` | {predef_detection} +| `+__CODEGEARC__+` | {predef_detection} + +| `+__BORLANDC__+` | V.R.P +| `+__CODEGEARC__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_BORLAND BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__BORLANDC__) || defined(__CODEGEARC__) +# if !defined(BOOST_COMP_BORLAND_DETECTION) && (defined(__CODEGEARC__)) +# define BOOST_COMP_BORLAND_DETECTION BOOST_PREDEF_MAKE_0X_VVRP(__CODEGEARC__) +# endif +# if !defined(BOOST_COMP_BORLAND_DETECTION) +# define BOOST_COMP_BORLAND_DETECTION BOOST_PREDEF_MAKE_0X_VVRP(__BORLANDC__) +# endif +#endif + +#ifdef BOOST_COMP_BORLAND_DETECTION +# define BOOST_COMP_BORLAND_AVAILABLE +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_BORLAND_EMULATED BOOST_COMP_BORLAND_DETECTION +# else +# undef BOOST_COMP_BORLAND +# define BOOST_COMP_BORLAND BOOST_COMP_BORLAND_DETECTION +# endif +# include +#endif + +#define BOOST_COMP_BORLAND_NAME "Borland C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_BORLAND,BOOST_COMP_BORLAND_NAME) + +#ifdef BOOST_COMP_BORLAND_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_BORLAND_EMULATED,BOOST_COMP_BORLAND_NAME) +#endif diff --git a/boost/predef/compiler/clang.h b/boost/predef/compiler/clang.h new file mode 100644 index 00000000..5e62da25 --- /dev/null +++ b/boost/predef/compiler/clang.h @@ -0,0 +1,57 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_CLANG_H +#define BOOST_PREDEF_COMPILER_CLANG_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_CLANG` + +http://en.wikipedia.org/wiki/Clang[Clang] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__clang__+` | {predef_detection} + +| `+__clang_major__+`, `+__clang_minor__+`, `+__clang_patchlevel__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_CLANG BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__clang__) +# define BOOST_COMP_CLANG_DETECTION BOOST_VERSION_NUMBER(__clang_major__,__clang_minor__,__clang_patchlevel__) +#endif + +#ifdef BOOST_COMP_CLANG_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_CLANG_EMULATED BOOST_COMP_CLANG_DETECTION +# else +# undef BOOST_COMP_CLANG +# define BOOST_COMP_CLANG BOOST_COMP_CLANG_DETECTION +# endif +# define BOOST_COMP_CLANG_AVAILABLE +# include +#endif + +#define BOOST_COMP_CLANG_NAME "Clang" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_CLANG,BOOST_COMP_CLANG_NAME) + +#ifdef BOOST_COMP_CLANG_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_CLANG_EMULATED,BOOST_COMP_CLANG_NAME) +#endif diff --git a/boost/predef/compiler/comeau.h b/boost/predef/compiler/comeau.h new file mode 100644 index 00000000..749694d0 --- /dev/null +++ b/boost/predef/compiler/comeau.h @@ -0,0 +1,62 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_COMEAU_H +#define BOOST_PREDEF_COMPILER_COMEAU_H + +#include +#include + +#define BOOST_COMP_COMO BOOST_VERSION_NUMBER_NOT_AVAILABLE + +/* tag::reference[] += `BOOST_COMP_COMO` + +http://en.wikipedia.org/wiki/Comeau_C/C%2B%2B[Comeau {CPP}] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__COMO__+` | {predef_detection} + +| `+__COMO_VERSION__+` | V.R.P +|=== +*/ // end::reference[] + +#if defined(__COMO__) +# if !defined(BOOST_COMP_COMO_DETECTION) && defined(__COMO_VERSION__) +# define BOOST_COMP_COMO_DETECTION BOOST_PREDEF_MAKE_0X_VRP(__COMO_VERSION__) +# endif +# if !defined(BOOST_COMP_COMO_DETECTION) +# define BOOST_COMP_COMO_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#ifdef BOOST_COMP_COMO_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_COMO_EMULATED BOOST_COMP_COMO_DETECTION +# else +# undef BOOST_COMP_COMO +# define BOOST_COMP_COMO BOOST_COMP_COMO_DETECTION +# endif +# define BOOST_COMP_COMO_AVAILABLE +# include +#endif + +#define BOOST_COMP_COMO_NAME "Comeau C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_COMO,BOOST_COMP_COMO_NAME) + +#ifdef BOOST_COMP_COMO_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_COMO_EMULATED,BOOST_COMP_COMO_NAME) +#endif diff --git a/boost/predef/compiler/compaq.h b/boost/predef/compiler/compaq.h new file mode 100644 index 00000000..a2a403ff --- /dev/null +++ b/boost/predef/compiler/compaq.h @@ -0,0 +1,67 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_COMPAQ_H +#define BOOST_PREDEF_COMPILER_COMPAQ_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_DEC` + +http://www.openvms.compaq.com/openvms/brochures/deccplus/[Compaq C/{CPP}] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__DECCXX+` | {predef_detection} +| `+__DECC+` | {predef_detection} + +| `+__DECCXX_VER+` | V.R.P +| `+__DECC_VER+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_DEC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__DECC) || defined(__DECCXX) +# if !defined(BOOST_COMP_DEC_DETECTION) && defined(__DECCXX_VER) +# define BOOST_COMP_DEC_DETECTION BOOST_PREDEF_MAKE_10_VVRR0PP00(__DECCXX_VER) +# endif +# if !defined(BOOST_COMP_DEC_DETECTION) && defined(__DECC_VER) +# define BOOST_COMP_DEC_DETECTION BOOST_PREDEF_MAKE_10_VVRR0PP00(__DECC_VER) +# endif +# if !defined(BOOST_COMP_DEC_DETECTION) +# define BOOST_COMP_DEC_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#ifdef BOOST_COMP_DEC_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_DEC_EMULATED BOOST_COMP_DEC_DETECTION +# else +# undef BOOST_COMP_DEC +# define BOOST_COMP_DEC BOOST_COMP_DEC_DETECTION +# endif +# define BOOST_COMP_DEC_AVAILABLE +# include +#endif + +#define BOOST_COMP_DEC_NAME "Compaq C/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_DEC,BOOST_COMP_DEC_NAME) + +#ifdef BOOST_COMP_DEC_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_DEC_EMULATED,BOOST_COMP_DEC_NAME) +#endif diff --git a/boost/predef/compiler/diab.h b/boost/predef/compiler/diab.h new file mode 100644 index 00000000..9be1d1ae --- /dev/null +++ b/boost/predef/compiler/diab.h @@ -0,0 +1,57 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_DIAB_H +#define BOOST_PREDEF_COMPILER_DIAB_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_DIAB` + +http://www.windriver.com/products/development_suite/wind_river_compiler/[Diab C/{CPP}] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__DCC__+` | {predef_detection} + +| `+__VERSION_NUMBER__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_DIAB BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__DCC__) +# define BOOST_COMP_DIAB_DETECTION BOOST_PREDEF_MAKE_10_VRPP(__VERSION_NUMBER__) +#endif + +#ifdef BOOST_COMP_DIAB_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_DIAB_EMULATED BOOST_COMP_DIAB_DETECTION +# else +# undef BOOST_COMP_DIAB +# define BOOST_COMP_DIAB BOOST_COMP_DIAB_DETECTION +# endif +# define BOOST_COMP_DIAB_AVAILABLE +# include +#endif + +#define BOOST_COMP_DIAB_NAME "Diab C/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_DIAB,BOOST_COMP_DIAB_NAME) + +#ifdef BOOST_COMP_DIAB_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_DIAB_EMULATED,BOOST_COMP_DIAB_NAME) +#endif diff --git a/boost/predef/compiler/digitalmars.h b/boost/predef/compiler/digitalmars.h new file mode 100644 index 00000000..3b2d53f7 --- /dev/null +++ b/boost/predef/compiler/digitalmars.h @@ -0,0 +1,57 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_DIGITALMARS_H +#define BOOST_PREDEF_COMPILER_DIGITALMARS_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_DMC` + +http://en.wikipedia.org/wiki/Digital_Mars[Digital Mars] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__DMC__+` | {predef_detection} + +| `+__DMC__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_DMC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__DMC__) +# define BOOST_COMP_DMC_DETECTION BOOST_PREDEF_MAKE_0X_VRP(__DMC__) +#endif + +#ifdef BOOST_COMP_DMC_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_DMC_EMULATED BOOST_COMP_DMC_DETECTION +# else +# undef BOOST_COMP_DMC +# define BOOST_COMP_DMC BOOST_COMP_DMC_DETECTION +# endif +# define BOOST_COMP_DMC_AVAILABLE +# include +#endif + +#define BOOST_COMP_DMC_NAME "Digital Mars" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_DMC,BOOST_COMP_DMC_NAME) + +#ifdef BOOST_COMP_DMC_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_DMC_EMULATED,BOOST_COMP_DMC_NAME) +#endif diff --git a/boost/predef/compiler/dignus.h b/boost/predef/compiler/dignus.h new file mode 100644 index 00000000..8177cc76 --- /dev/null +++ b/boost/predef/compiler/dignus.h @@ -0,0 +1,57 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_DIGNUS_H +#define BOOST_PREDEF_COMPILER_DIGNUS_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_SYSC` + +http://www.dignus.com/dcxx/[Dignus Systems/{CPP}] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__SYSC__+` | {predef_detection} + +| `+__SYSC_VER__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_SYSC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__SYSC__) +# define BOOST_COMP_SYSC_DETECTION BOOST_PREDEF_MAKE_10_VRRPP(__SYSC_VER__) +#endif + +#ifdef BOOST_COMP_SYSC_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_SYSC_EMULATED BOOST_COMP_SYSC_DETECTION +# else +# undef BOOST_COMP_SYSC +# define BOOST_COMP_SYSC BOOST_COMP_SYSC_DETECTION +# endif +# define BOOST_COMP_SYSC_AVAILABLE +# include +#endif + +#define BOOST_COMP_SYSC_NAME "Dignus Systems/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_SYSC,BOOST_COMP_SYSC_NAME) + +#ifdef BOOST_COMP_SYSC_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_SYSC_EMULATED,BOOST_COMP_SYSC_NAME) +#endif diff --git a/boost/predef/compiler/edg.h b/boost/predef/compiler/edg.h new file mode 100644 index 00000000..6e0f97a2 --- /dev/null +++ b/boost/predef/compiler/edg.h @@ -0,0 +1,57 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_EDG_H +#define BOOST_PREDEF_COMPILER_EDG_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_EDG` + +http://en.wikipedia.org/wiki/Edison_Design_Group[EDG {CPP} Frontend] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__EDG__+` | {predef_detection} + +| `+__EDG_VERSION__+` | V.R.0 +|=== +*/ // end::reference[] + +#define BOOST_COMP_EDG BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__EDG__) +# define BOOST_COMP_EDG_DETECTION BOOST_PREDEF_MAKE_10_VRR(__EDG_VERSION__) +#endif + +#ifdef BOOST_COMP_EDG_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_EDG_EMULATED BOOST_COMP_EDG_DETECTION +# else +# undef BOOST_COMP_EDG +# define BOOST_COMP_EDG BOOST_COMP_EDG_DETECTION +# endif +# define BOOST_COMP_EDG_AVAILABLE +# include +#endif + +#define BOOST_COMP_EDG_NAME "EDG C++ Frontend" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_EDG,BOOST_COMP_EDG_NAME) + +#ifdef BOOST_COMP_EDG_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_EDG_EMULATED,BOOST_COMP_EDG_NAME) +#endif diff --git a/boost/predef/compiler/ekopath.h b/boost/predef/compiler/ekopath.h new file mode 100644 index 00000000..f91c9dce --- /dev/null +++ b/boost/predef/compiler/ekopath.h @@ -0,0 +1,58 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_EKOPATH_H +#define BOOST_PREDEF_COMPILER_EKOPATH_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_PATH` + +http://en.wikipedia.org/wiki/PathScale[EKOpath] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__PATHCC__+` | {predef_detection} + +| `+__PATHCC__+`, `+__PATHCC_MINOR__+`, `+__PATHCC_PATCHLEVEL__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_PATH BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__PATHCC__) +# define BOOST_COMP_PATH_DETECTION \ + BOOST_VERSION_NUMBER(__PATHCC__,__PATHCC_MINOR__,__PATHCC_PATCHLEVEL__) +#endif + +#ifdef BOOST_COMP_PATH_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_PATH_EMULATED BOOST_COMP_PATH_DETECTION +# else +# undef BOOST_COMP_PATH +# define BOOST_COMP_PATH BOOST_COMP_PATH_DETECTION +# endif +# define BOOST_COMP_PATH_AVAILABLE +# include +#endif + +#define BOOST_COMP_PATH_NAME "EKOpath" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_PATH,BOOST_COMP_PATH_NAME) + +#ifdef BOOST_COMP_PATH_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_PATH_EMULATED,BOOST_COMP_PATH_NAME) +#endif diff --git a/boost/predef/compiler/gcc.h b/boost/predef/compiler/gcc.h new file mode 100644 index 00000000..88698d21 --- /dev/null +++ b/boost/predef/compiler/gcc.h @@ -0,0 +1,69 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_GCC_H +#define BOOST_PREDEF_COMPILER_GCC_H + +/* Other compilers that emulate this one need to be detected first. */ + +#include + +#include +#include + +/* tag::reference[] += `BOOST_COMP_GNUC` + +http://en.wikipedia.org/wiki/GNU_Compiler_Collection[Gnu GCC C/{CPP}] compiler. +Version number available as major, minor, and patch (if available). + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__GNUC__+` | {predef_detection} + +| `+__GNUC__+`, `+__GNUC_MINOR__+`, `+__GNUC_PATCHLEVEL__+` | V.R.P +| `+__GNUC__+`, `+__GNUC_MINOR__+` | V.R.0 +|=== +*/ // end::reference[] + +#define BOOST_COMP_GNUC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__GNUC__) +# if !defined(BOOST_COMP_GNUC_DETECTION) && defined(__GNUC_PATCHLEVEL__) +# define BOOST_COMP_GNUC_DETECTION \ + BOOST_VERSION_NUMBER(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) +# endif +# if !defined(BOOST_COMP_GNUC_DETECTION) +# define BOOST_COMP_GNUC_DETECTION \ + BOOST_VERSION_NUMBER(__GNUC__,__GNUC_MINOR__,0) +# endif +#endif + +#ifdef BOOST_COMP_GNUC_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_GNUC_EMULATED BOOST_COMP_GNUC_DETECTION +# else +# undef BOOST_COMP_GNUC +# define BOOST_COMP_GNUC BOOST_COMP_GNUC_DETECTION +# endif +# define BOOST_COMP_GNUC_AVAILABLE +# include +#endif + +#define BOOST_COMP_GNUC_NAME "Gnu GCC C/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_GNUC,BOOST_COMP_GNUC_NAME) + +#ifdef BOOST_COMP_GNUC_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_GNUC_EMULATED,BOOST_COMP_GNUC_NAME) +#endif diff --git a/boost/predef/compiler/gcc_xml.h b/boost/predef/compiler/gcc_xml.h new file mode 100644 index 00000000..a9253370 --- /dev/null +++ b/boost/predef/compiler/gcc_xml.h @@ -0,0 +1,54 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_GCC_XML_H +#define BOOST_PREDEF_COMPILER_GCC_XML_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_GCCXML` + +http://www.gccxml.org/[GCC XML] compiler. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__GCCXML__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_COMP_GCCXML BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__GCCXML__) +# define BOOST_COMP_GCCXML_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#ifdef BOOST_COMP_GCCXML_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_GCCXML_EMULATED BOOST_COMP_GCCXML_DETECTION +# else +# undef BOOST_COMP_GCCXML +# define BOOST_COMP_GCCXML BOOST_COMP_GCCXML_DETECTION +# endif +# define BOOST_COMP_GCCXML_AVAILABLE +# include +#endif + +#define BOOST_COMP_GCCXML_NAME "GCC XML" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_GCCXML,BOOST_COMP_GCCXML_NAME) + +#ifdef BOOST_COMP_GCCXML_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_GCCXML_EMULATED,BOOST_COMP_GCCXML_NAME) +#endif diff --git a/boost/predef/compiler/greenhills.h b/boost/predef/compiler/greenhills.h new file mode 100644 index 00000000..9bf5bf17 --- /dev/null +++ b/boost/predef/compiler/greenhills.h @@ -0,0 +1,67 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_GREENHILLS_H +#define BOOST_PREDEF_COMPILER_GREENHILLS_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_GHS` + +http://en.wikipedia.org/wiki/Green_Hills_Software[Green Hills C/{CPP}] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__ghs+` | {predef_detection} +| `+__ghs__+` | {predef_detection} + +| `+__GHS_VERSION_NUMBER__+` | V.R.P +| `+__ghs+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_GHS BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__ghs) || defined(__ghs__) +# if !defined(BOOST_COMP_GHS_DETECTION) && defined(__GHS_VERSION_NUMBER__) +# define BOOST_COMP_GHS_DETECTION BOOST_PREDEF_MAKE_10_VRP(__GHS_VERSION_NUMBER__) +# endif +# if !defined(BOOST_COMP_GHS_DETECTION) && defined(__ghs) +# define BOOST_COMP_GHS_DETECTION BOOST_PREDEF_MAKE_10_VRP(__ghs) +# endif +# if !defined(BOOST_COMP_GHS_DETECTION) +# define BOOST_COMP_GHS_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#ifdef BOOST_COMP_GHS_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_GHS_EMULATED BOOST_COMP_GHS_DETECTION +# else +# undef BOOST_COMP_GHS +# define BOOST_COMP_GHS BOOST_COMP_GHS_DETECTION +# endif +# define BOOST_COMP_GHS_AVAILABLE +# include +#endif + +#define BOOST_COMP_GHS_NAME "Green Hills C/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_GHS,BOOST_COMP_GHS_NAME) + +#ifdef BOOST_COMP_GHS_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_GHS_EMULATED,BOOST_COMP_GHS_NAME) +#endif diff --git a/boost/predef/compiler/hp_acc.h b/boost/predef/compiler/hp_acc.h new file mode 100644 index 00000000..7a825cd5 --- /dev/null +++ b/boost/predef/compiler/hp_acc.h @@ -0,0 +1,62 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_HP_ACC_H +#define BOOST_PREDEF_COMPILER_HP_ACC_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_HPACC` + +HP a{CPP} compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__HP_aCC+` | {predef_detection} + +| `+__HP_aCC+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_HPACC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__HP_aCC) +# if !defined(BOOST_COMP_HPACC_DETECTION) && (__HP_aCC > 1) +# define BOOST_COMP_HPACC_DETECTION BOOST_PREDEF_MAKE_10_VVRRPP(__HP_aCC) +# endif +# if !defined(BOOST_COMP_HPACC_DETECTION) +# define BOOST_COMP_HPACC_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#ifdef BOOST_COMP_HPACC_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_HPACC_EMULATED BOOST_COMP_HPACC_DETECTION +# else +# undef BOOST_COMP_HPACC +# define BOOST_COMP_HPACC BOOST_COMP_HPACC_DETECTION +# endif +# define BOOST_COMP_HPACC_AVAILABLE +# include +#endif + +#define BOOST_COMP_HPACC_NAME "HP aC++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_HPACC,BOOST_COMP_HPACC_NAME) + +#ifdef BOOST_COMP_HPACC_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_HPACC_EMULATED,BOOST_COMP_HPACC_NAME) +#endif diff --git a/boost/predef/compiler/iar.h b/boost/predef/compiler/iar.h new file mode 100644 index 00000000..1140b0b4 --- /dev/null +++ b/boost/predef/compiler/iar.h @@ -0,0 +1,57 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_IAR_H +#define BOOST_PREDEF_COMPILER_IAR_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_IAR` + +IAR C/{CPP} compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__IAR_SYSTEMS_ICC__+` | {predef_detection} + +| `+__VER__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_IAR BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__IAR_SYSTEMS_ICC__) +# define BOOST_COMP_IAR_DETECTION BOOST_PREDEF_MAKE_10_VVRR(__VER__) +#endif + +#ifdef BOOST_COMP_IAR_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_IAR_EMULATED BOOST_COMP_IAR_DETECTION +# else +# undef BOOST_COMP_IAR +# define BOOST_COMP_IAR BOOST_COMP_IAR_DETECTION +# endif +# define BOOST_COMP_IAR_AVAILABLE +# include +#endif + +#define BOOST_COMP_IAR_NAME "IAR C/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_IAR,BOOST_COMP_IAR_NAME) + +#ifdef BOOST_COMP_IAR_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_IAR_EMULATED,BOOST_COMP_IAR_NAME) +#endif diff --git a/boost/predef/compiler/ibm.h b/boost/predef/compiler/ibm.h new file mode 100644 index 00000000..6820677f --- /dev/null +++ b/boost/predef/compiler/ibm.h @@ -0,0 +1,73 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_IBM_H +#define BOOST_PREDEF_COMPILER_IBM_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_IBM` + +http://en.wikipedia.org/wiki/VisualAge[IBM XL C/{CPP}] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__IBMCPP__+` | {predef_detection} +| `+__xlC__+` | {predef_detection} +| `+__xlc__+` | {predef_detection} + +| `+__COMPILER_VER__+` | V.R.P +| `+__xlC__+` | V.R.P +| `+__xlc__+` | V.R.P +| `+__IBMCPP__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_IBM BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__IBMCPP__) || defined(__xlC__) || defined(__xlc__) +# if !defined(BOOST_COMP_IBM_DETECTION) && defined(__COMPILER_VER__) +# define BOOST_COMP_IBM_DETECTION BOOST_PREDEF_MAKE_0X_VRRPPPP(__COMPILER_VER__) +# endif +# if !defined(BOOST_COMP_IBM_DETECTION) && defined(__xlC__) +# define BOOST_COMP_IBM_DETECTION BOOST_PREDEF_MAKE_0X_VVRR(__xlC__) +# endif +# if !defined(BOOST_COMP_IBM_DETECTION) && defined(__xlc__) +# define BOOST_COMP_IBM_DETECTION BOOST_PREDEF_MAKE_0X_VVRR(__xlc__) +# endif +# if !defined(BOOST_COMP_IBM_DETECTION) +# define BOOST_COMP_IBM_DETECTION BOOST_PREDEF_MAKE_10_VRP(__IBMCPP__) +# endif +#endif + +#ifdef BOOST_COMP_IBM_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_IBM_EMULATED BOOST_COMP_IBM_DETECTION +# else +# undef BOOST_COMP_IBM +# define BOOST_COMP_IBM BOOST_COMP_IBM_DETECTION +# endif +# define BOOST_COMP_IBM_AVAILABLE +# include +#endif + +#define BOOST_COMP_IBM_NAME "IBM XL C/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_IBM,BOOST_COMP_IBM_NAME) + +#ifdef BOOST_COMP_IBM_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_IBM_EMULATED,BOOST_COMP_IBM_NAME) +#endif diff --git a/boost/predef/compiler/intel.h b/boost/predef/compiler/intel.h new file mode 100644 index 00000000..62d510ab --- /dev/null +++ b/boost/predef/compiler/intel.h @@ -0,0 +1,80 @@ +/* +Copyright Rene Rivera 2008-2017 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_INTEL_H +#define BOOST_PREDEF_COMPILER_INTEL_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_INTEL` + +http://en.wikipedia.org/wiki/Intel_C%2B%2B[Intel C/{CPP}] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__INTEL_COMPILER+` | {predef_detection} +| `+__ICL+` | {predef_detection} +| `+__ICC+` | {predef_detection} +| `+__ECC+` | {predef_detection} + +| `+__INTEL_COMPILER+` | V.R +| `+__INTEL_COMPILER+` and `+__INTEL_COMPILER_UPDATE+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_INTEL BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || \ + defined(__ECC) +/* tag::reference[] +NOTE: Because of an Intel mistake in the release version numbering when +`__INTEL_COMPILER` is `9999` it is detected as version 12.1.0. +*/ // end::reference[] +# if !defined(BOOST_COMP_INTEL_DETECTION) && defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 9999) +# define BOOST_COMP_INTEL_DETECTION BOOST_VERSION_NUMBER(12,1,0) +# endif +# if !defined(BOOST_COMP_INTEL_DETECTION) && defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) +# define BOOST_COMP_INTEL_DETECTION BOOST_VERSION_NUMBER( \ + BOOST_VERSION_NUMBER_MAJOR(BOOST_PREDEF_MAKE_10_VVRR(__INTEL_COMPILER)), \ + BOOST_VERSION_NUMBER_MINOR(BOOST_PREDEF_MAKE_10_VVRR(__INTEL_COMPILER)), \ + __INTEL_COMPILER_UPDATE) +# endif +# if !defined(BOOST_COMP_INTEL_DETECTION) && defined(__INTEL_COMPILER) +# define BOOST_COMP_INTEL_DETECTION BOOST_PREDEF_MAKE_10_VVRR(__INTEL_COMPILER) +# endif +# if !defined(BOOST_COMP_INTEL_DETECTION) +# define BOOST_COMP_INTEL_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#ifdef BOOST_COMP_INTEL_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_INTEL_EMULATED BOOST_COMP_INTEL_DETECTION +# else +# undef BOOST_COMP_INTEL +# define BOOST_COMP_INTEL BOOST_COMP_INTEL_DETECTION +# endif +# define BOOST_COMP_INTEL_AVAILABLE +# include +#endif + +#define BOOST_COMP_INTEL_NAME "Intel C/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_INTEL,BOOST_COMP_INTEL_NAME) + +#ifdef BOOST_COMP_INTEL_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_INTEL_EMULATED,BOOST_COMP_INTEL_NAME) +#endif diff --git a/boost/predef/compiler/kai.h b/boost/predef/compiler/kai.h new file mode 100644 index 00000000..1980cc84 --- /dev/null +++ b/boost/predef/compiler/kai.h @@ -0,0 +1,57 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_KAI_H +#define BOOST_PREDEF_COMPILER_KAI_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_KCC` + +Kai {CPP} compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__KCC+` | {predef_detection} + +| `+__KCC_VERSION+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_KCC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__KCC) +# define BOOST_COMP_KCC_DETECTION BOOST_PREDEF_MAKE_0X_VRPP(__KCC_VERSION) +#endif + +#ifdef BOOST_COMP_KCC_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_KCC_EMULATED BOOST_COMP_KCC_DETECTION +# else +# undef BOOST_COMP_KCC +# define BOOST_COMP_KCC BOOST_COMP_KCC_DETECTION +# endif +# define BOOST_COMP_KCC_AVAILABLE +# include +#endif + +#define BOOST_COMP_KCC_NAME "Kai C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_KCC,BOOST_COMP_KCC_NAME) + +#ifdef BOOST_COMP_KCC_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_KCC_EMULATED,BOOST_COMP_KCC_NAME) +#endif diff --git a/boost/predef/compiler/llvm.h b/boost/predef/compiler/llvm.h new file mode 100644 index 00000000..09f2b804 --- /dev/null +++ b/boost/predef/compiler/llvm.h @@ -0,0 +1,58 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_LLVM_H +#define BOOST_PREDEF_COMPILER_LLVM_H + +/* Other compilers that emulate this one need to be detected first. */ + +#include + +#include +#include + +/* tag::reference[] += `BOOST_COMP_LLVM` + +http://en.wikipedia.org/wiki/LLVM[LLVM] compiler. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__llvm__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_COMP_LLVM BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__llvm__) +# define BOOST_COMP_LLVM_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#ifdef BOOST_COMP_LLVM_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_LLVM_EMULATED BOOST_COMP_LLVM_DETECTION +# else +# undef BOOST_COMP_LLVM +# define BOOST_COMP_LLVM BOOST_COMP_LLVM_DETECTION +# endif +# define BOOST_COMP_LLVM_AVAILABLE +# include +#endif + +#define BOOST_COMP_LLVM_NAME "LLVM" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_LLVM,BOOST_COMP_LLVM_NAME) + +#ifdef BOOST_COMP_LLVM_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_LLVM_EMULATED,BOOST_COMP_LLVM_NAME) +#endif diff --git a/boost/predef/compiler/metaware.h b/boost/predef/compiler/metaware.h new file mode 100644 index 00000000..e210943d --- /dev/null +++ b/boost/predef/compiler/metaware.h @@ -0,0 +1,54 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_METAWARE_H +#define BOOST_PREDEF_COMPILER_METAWARE_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_HIGHC` + +MetaWare High C/{CPP} compiler. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__HIGHC__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_COMP_HIGHC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__HIGHC__) +# define BOOST_COMP_HIGHC_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#ifdef BOOST_COMP_HIGHC_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_HIGHC_EMULATED BOOST_COMP_HIGHC_DETECTION +# else +# undef BOOST_COMP_HIGHC +# define BOOST_COMP_HIGHC BOOST_COMP_HIGHC_DETECTION +# endif +# define BOOST_COMP_HIGHC_AVAILABLE +# include +#endif + +#define BOOST_COMP_HIGHC_NAME "MetaWare High C/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_HIGHC,BOOST_COMP_HIGHC_NAME) + +#ifdef BOOST_COMP_HIGHC_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_HIGHC_EMULATED,BOOST_COMP_HIGHC_NAME) +#endif diff --git a/boost/predef/compiler/metrowerks.h b/boost/predef/compiler/metrowerks.h new file mode 100644 index 00000000..98cb751d --- /dev/null +++ b/boost/predef/compiler/metrowerks.h @@ -0,0 +1,78 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_METROWERKS_H +#define BOOST_PREDEF_COMPILER_METROWERKS_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_MWERKS` + +http://en.wikipedia.org/wiki/CodeWarrior[Metrowerks CodeWarrior] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__MWERKS__+` | {predef_detection} +| `+__CWCC__+` | {predef_detection} + +| `+__CWCC__+` | V.R.P +| `+__MWERKS__+` | V.R.P >= 4.2.0 +| `+__MWERKS__+` | 9.R.0 +| `+__MWERKS__+` | 8.R.0 +|=== +*/ // end::reference[] + +#define BOOST_COMP_MWERKS BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__MWERKS__) || defined(__CWCC__) +# if !defined(BOOST_COMP_MWERKS_DETECTION) && defined(__CWCC__) +# define BOOST_COMP_MWERKS_DETECTION BOOST_PREDEF_MAKE_0X_VRPP(__CWCC__) +# endif +# if !defined(BOOST_COMP_MWERKS_DETECTION) && (__MWERKS__ >= 0x4200) +# define BOOST_COMP_MWERKS_DETECTION BOOST_PREDEF_MAKE_0X_VRPP(__MWERKS__) +# endif +# if !defined(BOOST_COMP_MWERKS_DETECTION) && (__MWERKS__ >= 0x3204) // note the "skip": 04->9.3 +# define BOOST_COMP_MWERKS_DETECTION BOOST_VERSION_NUMBER(9,(__MWERKS__)%100-1,0) +# endif +# if !defined(BOOST_COMP_MWERKS_DETECTION) && (__MWERKS__ >= 0x3200) +# define BOOST_COMP_MWERKS_DETECTION BOOST_VERSION_NUMBER(9,(__MWERKS__)%100,0) +# endif +# if !defined(BOOST_COMP_MWERKS_DETECTION) && (__MWERKS__ >= 0x3000) +# define BOOST_COMP_MWERKS_DETECTION BOOST_VERSION_NUMBER(8,(__MWERKS__)%100,0) +# endif +# if !defined(BOOST_COMP_MWERKS_DETECTION) +# define BOOST_COMP_MWERKS_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#ifdef BOOST_COMP_MWERKS_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_MWERKS_EMULATED BOOST_COMP_MWERKS_DETECTION +# else +# undef BOOST_COMP_MWERKS +# define BOOST_COMP_MWERKS BOOST_COMP_MWERKS_DETECTION +# endif +# define BOOST_COMP_MWERKS_AVAILABLE +# include +#endif + +#define BOOST_COMP_MWERKS_NAME "Metrowerks CodeWarrior" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MWERKS,BOOST_COMP_MWERKS_NAME) + +#ifdef BOOST_COMP_MWERKS_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MWERKS_EMULATED,BOOST_COMP_MWERKS_NAME) +#endif diff --git a/boost/predef/compiler/microtec.h b/boost/predef/compiler/microtec.h new file mode 100644 index 00000000..93c7e910 --- /dev/null +++ b/boost/predef/compiler/microtec.h @@ -0,0 +1,54 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_MICROTEC_H +#define BOOST_PREDEF_COMPILER_MICROTEC_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_MRI` + +http://www.mentor.com/microtec/[Microtec C/{CPP}] compiler. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+_MRI+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_COMP_MRI BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(_MRI) +# define BOOST_COMP_MRI_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#ifdef BOOST_COMP_MRI_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_MRI_EMULATED BOOST_COMP_MRI_DETECTION +# else +# undef BOOST_COMP_MRI +# define BOOST_COMP_MRI BOOST_COMP_MRI_DETECTION +# endif +# define BOOST_COMP_MRI_AVAILABLE +# include +#endif + +#define BOOST_COMP_MRI_NAME "Microtec C/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MRI,BOOST_COMP_MRI_NAME) + +#ifdef BOOST_COMP_MRI_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MRI_EMULATED,BOOST_COMP_MRI_NAME) +#endif diff --git a/boost/predef/compiler/mpw.h b/boost/predef/compiler/mpw.h new file mode 100644 index 00000000..963f7567 --- /dev/null +++ b/boost/predef/compiler/mpw.h @@ -0,0 +1,64 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_MPW_H +#define BOOST_PREDEF_COMPILER_MPW_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_MPW` + +http://en.wikipedia.org/wiki/Macintosh_Programmer%27s_Workshop[MPW {CPP}] compiler. +Version number available as major, and minor. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__MRC__+` | {predef_detection} +| `MPW_C` | {predef_detection} +| `MPW_CPLUS` | {predef_detection} + +| `+__MRC__+` | V.R.0 +|=== +*/ // end::reference[] + +#define BOOST_COMP_MPW BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__MRC__) || defined(MPW_C) || defined(MPW_CPLUS) +# if !defined(BOOST_COMP_MPW_DETECTION) && defined(__MRC__) +# define BOOST_COMP_MPW_DETECTION BOOST_PREDEF_MAKE_0X_VVRR(__MRC__) +# endif +# if !defined(BOOST_COMP_MPW_DETECTION) +# define BOOST_COMP_MPW_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#ifdef BOOST_COMP_MPW_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_MPW_EMULATED BOOST_COMP_MPW_DETECTION +# else +# undef BOOST_COMP_MPW +# define BOOST_COMP_MPW BOOST_COMP_MPW_DETECTION +# endif +# define BOOST_COMP_MPW_AVAILABLE +# include +#endif + +#define BOOST_COMP_MPW_NAME "MPW C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MPW,BOOST_COMP_MPW_NAME) + +#ifdef BOOST_COMP_MPW_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MPW_EMULATED,BOOST_COMP_MPW_NAME) +#endif diff --git a/boost/predef/compiler/nvcc.h b/boost/predef/compiler/nvcc.h new file mode 100644 index 00000000..3690c535 --- /dev/null +++ b/boost/predef/compiler/nvcc.h @@ -0,0 +1,74 @@ +/* +Copyright Benjamin Worpitz 2018 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_NVCC_H +#define BOOST_PREDEF_COMPILER_NVCC_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_NVCC` + +https://en.wikipedia.org/wiki/NVIDIA_CUDA_Compiler[NVCC] compiler. +Version number available as major, minor, and patch beginning with version 7.5. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__NVCC__+` | {predef_detection} + +| `+__CUDACC_VER_MAJOR__+`, `+__CUDACC_VER_MINOR__+`, `+__CUDACC_VER_BUILD__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_NVCC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__NVCC__) +# if !defined(__CUDACC_VER_MAJOR__) || !defined(__CUDACC_VER_MINOR__) || !defined(__CUDACC_VER_BUILD__) +# define BOOST_COMP_NVCC_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +# else +# define BOOST_COMP_NVCC_DETECTION BOOST_VERSION_NUMBER(__CUDACC_VER_MAJOR__, __CUDACC_VER_MINOR__, __CUDACC_VER_BUILD__) +# endif +#endif + +#ifdef BOOST_COMP_NVCC_DETECTION +/* +Always define BOOST_COMP_NVCC instead of BOOST_COMP_NVCC_EMULATED +The nvcc compilation process is somewhat special as can be read here: +https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#cuda-compilation-trajectory +The nvcc compiler precompiles the input two times. Once for the device code +being compiled by the cicc device compiler and once for the host code +compiled by the real host compiler. NVCC uses gcc/clang/msvc/... +depending on the host compiler being set on the command line. + +Predef (as a preprocessor only lib) detects the one doing the preprocessing +as compiler and expects it to be the one doing the real compilation. +This is not true for NVCC which is only doing the preprocessing and which +is using another compiler for parts of its work. So for NVCC it should be +allowed to set BOOST_COMP_NVCC additionally to the already detected host +compiler because both is true: It is gcc/clang/... compiling the code, but it +is also NVCC doing the preprocessing and adding some other quirks you may +want to detect. + +This behavior is similar to what boost config is doing in `select_compiler_config.hpp`. +There the NVCC detection is not handled as a real compiler (part of the +#if-#elif) but as additional option before the real compiler. +*/ +# undef BOOST_COMP_NVCC +# define BOOST_COMP_NVCC BOOST_COMP_NVCC_DETECTION +# define BOOST_COMP_NVCC_AVAILABLE +# include +#endif + +#define BOOST_COMP_NVCC_NAME "NVCC" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_NVCC,BOOST_COMP_NVCC_NAME) diff --git a/boost/predef/compiler/palm.h b/boost/predef/compiler/palm.h new file mode 100644 index 00000000..7f182151 --- /dev/null +++ b/boost/predef/compiler/palm.h @@ -0,0 +1,57 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_PALM_H +#define BOOST_PREDEF_COMPILER_PALM_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_PALM` + +Palm C/{CPP} compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+_PACC_VER+` | {predef_detection} + +| `+_PACC_VER+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_PALM BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(_PACC_VER) +# define BOOST_COMP_PALM_DETECTION BOOST_PREDEF_MAKE_0X_VRRPP000(_PACC_VER) +#endif + +#ifdef BOOST_COMP_PALM_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_PALM_EMULATED BOOST_COMP_PALM_DETECTION +# else +# undef BOOST_COMP_PALM +# define BOOST_COMP_PALM BOOST_COMP_PALM_DETECTION +# endif +# define BOOST_COMP_PALM_AVAILABLE +# include +#endif + +#define BOOST_COMP_PALM_NAME "Palm C/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_PALM,BOOST_COMP_PALM_NAME) + +#ifdef BOOST_COMP_PALM_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_PALM_EMULATED,BOOST_COMP_PALM_NAME) +#endif diff --git a/boost/predef/compiler/pgi.h b/boost/predef/compiler/pgi.h new file mode 100644 index 00000000..649e87ad --- /dev/null +++ b/boost/predef/compiler/pgi.h @@ -0,0 +1,61 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_PGI_H +#define BOOST_PREDEF_COMPILER_PGI_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_PGI` + +http://en.wikipedia.org/wiki/The_Portland_Group[Portland Group C/{CPP}] compiler. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__PGI+` | {predef_detection} + +| `+__PGIC__+`, `+__PGIC_MINOR__+`, `+__PGIC_PATCHLEVEL__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_PGI BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__PGI) +# if !defined(BOOST_COMP_PGI_DETECTION) && (defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)) +# define BOOST_COMP_PGI_DETECTION BOOST_VERSION_NUMBER(__PGIC__,__PGIC_MINOR__,__PGIC_PATCHLEVEL__) +# endif +# if !defined(BOOST_COMP_PGI_DETECTION) +# define BOOST_COMP_PGI_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#ifdef BOOST_COMP_PGI_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_PGI_EMULATED BOOST_COMP_PGI_DETECTION +# else +# undef BOOST_COMP_PGI +# define BOOST_COMP_PGI BOOST_COMP_PGI_DETECTION +# endif +# define BOOST_COMP_PGI_AVAILABLE +# include +#endif + +#define BOOST_COMP_PGI_NAME "Portland Group C/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_PGI,BOOST_COMP_PGI_NAME) + +#ifdef BOOST_COMP_PGI_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_PGI_EMULATED,BOOST_COMP_PGI_NAME) +#endif diff --git a/boost/predef/compiler/sgi_mipspro.h b/boost/predef/compiler/sgi_mipspro.h new file mode 100644 index 00000000..7bfdc9c6 --- /dev/null +++ b/boost/predef/compiler/sgi_mipspro.h @@ -0,0 +1,67 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_SGI_MIPSPRO_H +#define BOOST_PREDEF_COMPILER_SGI_MIPSPRO_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_SGI` + +http://en.wikipedia.org/wiki/MIPSpro[SGI MIPSpro] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__sgi+` | {predef_detection} +| `sgi` | {predef_detection} + +| `+_SGI_COMPILER_VERSION+` | V.R.P +| `+_COMPILER_VERSION+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_SGI BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__sgi) || defined(sgi) +# if !defined(BOOST_COMP_SGI_DETECTION) && defined(_SGI_COMPILER_VERSION) +# define BOOST_COMP_SGI_DETECTION BOOST_PREDEF_MAKE_10_VRP(_SGI_COMPILER_VERSION) +# endif +# if !defined(BOOST_COMP_SGI_DETECTION) && defined(_COMPILER_VERSION) +# define BOOST_COMP_SGI_DETECTION BOOST_PREDEF_MAKE_10_VRP(_COMPILER_VERSION) +# endif +# if !defined(BOOST_COMP_SGI_DETECTION) +# define BOOST_COMP_SGI_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#ifdef BOOST_COMP_SGI_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_SGI_EMULATED BOOST_COMP_SGI_DETECTION +# else +# undef BOOST_COMP_SGI +# define BOOST_COMP_SGI BOOST_COMP_SGI_DETECTION +# endif +# define BOOST_COMP_SGI_AVAILABLE +# include +#endif + +#define BOOST_COMP_SGI_NAME "SGI MIPSpro" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_SGI,BOOST_COMP_SGI_NAME) + +#ifdef BOOST_COMP_SGI_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_SGI_EMULATED,BOOST_COMP_SGI_NAME) +#endif diff --git a/boost/predef/compiler/sunpro.h b/boost/predef/compiler/sunpro.h new file mode 100644 index 00000000..b44d0bb3 --- /dev/null +++ b/boost/predef/compiler/sunpro.h @@ -0,0 +1,77 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_SUNPRO_H +#define BOOST_PREDEF_COMPILER_SUNPRO_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_SUNPRO` + +http://en.wikipedia.org/wiki/Oracle_Solaris_Studio[Oracle Solaris Studio] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__SUNPRO_CC+` | {predef_detection} +| `+__SUNPRO_C+` | {predef_detection} + +| `+__SUNPRO_CC+` | V.R.P +| `+__SUNPRO_C+` | V.R.P +| `+__SUNPRO_CC+` | VV.RR.P +| `+__SUNPRO_C+` | VV.RR.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_SUNPRO BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__SUNPRO_CC) || defined(__SUNPRO_C) +# if !defined(BOOST_COMP_SUNPRO_DETECTION) && defined(__SUNPRO_CC) +# if (__SUNPRO_CC < 0x5100) +# define BOOST_COMP_SUNPRO_DETECTION BOOST_PREDEF_MAKE_0X_VRP(__SUNPRO_CC) +# else +# define BOOST_COMP_SUNPRO_DETECTION BOOST_PREDEF_MAKE_0X_VVRRP(__SUNPRO_CC) +# endif +# endif +# if !defined(BOOST_COMP_SUNPRO_DETECTION) && defined(__SUNPRO_C) +# if (__SUNPRO_C < 0x5100) +# define BOOST_COMP_SUNPRO_DETECTION BOOST_PREDEF_MAKE_0X_VRP(__SUNPRO_C) +# else +# define BOOST_COMP_SUNPRO_DETECTION BOOST_PREDEF_MAKE_0X_VVRRP(__SUNPRO_C) +# endif +# endif +# if !defined(BOOST_COMP_SUNPRO_DETECTION) +# define BOOST_COMP_SUNPRO_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#ifdef BOOST_COMP_SUNPRO_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_SUNPRO_EMULATED BOOST_COMP_SUNPRO_DETECTION +# else +# undef BOOST_COMP_SUNPRO +# define BOOST_COMP_SUNPRO BOOST_COMP_SUNPRO_DETECTION +# endif +# define BOOST_COMP_SUNPRO_AVAILABLE +# include +#endif + +#define BOOST_COMP_SUNPRO_NAME "Oracle Solaris Studio" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_SUNPRO,BOOST_COMP_SUNPRO_NAME) + +#ifdef BOOST_COMP_SUNPRO_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_SUNPRO_EMULATED,BOOST_COMP_SUNPRO_NAME) +#endif diff --git a/boost/predef/compiler/tendra.h b/boost/predef/compiler/tendra.h new file mode 100644 index 00000000..bb896c07 --- /dev/null +++ b/boost/predef/compiler/tendra.h @@ -0,0 +1,54 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_TENDRA_H +#define BOOST_PREDEF_COMPILER_TENDRA_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_TENDRA` + +http://en.wikipedia.org/wiki/TenDRA_Compiler[TenDRA C/{CPP}] compiler. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__TenDRA__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_COMP_TENDRA BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__TenDRA__) +# define BOOST_COMP_TENDRA_DETECTION BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#ifdef BOOST_COMP_TENDRA_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_TENDRA_EMULATED BOOST_COMP_TENDRA_DETECTION +# else +# undef BOOST_COMP_TENDRA +# define BOOST_COMP_TENDRA BOOST_COMP_TENDRA_DETECTION +# endif +# define BOOST_COMP_TENDRA_AVAILABLE +# include +#endif + +#define BOOST_COMP_TENDRA_NAME "TenDRA C/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_TENDRA,BOOST_COMP_TENDRA_NAME) + +#ifdef BOOST_COMP_TENDRA_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_TENDRA_EMULATED,BOOST_COMP_TENDRA_NAME) +#endif diff --git a/boost/predef/compiler/visualc.h b/boost/predef/compiler/visualc.h new file mode 100644 index 00000000..5b0f2b83 --- /dev/null +++ b/boost/predef/compiler/visualc.h @@ -0,0 +1,106 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_VISUALC_H +#define BOOST_PREDEF_COMPILER_VISUALC_H + +/* Other compilers that emulate this one need to be detected first. */ + +#include + +#include +#include + +/* tag::reference[] += `BOOST_COMP_MSVC` + +http://en.wikipedia.org/wiki/Visual_studio[Microsoft Visual C/{CPP}] compiler. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+_MSC_VER+` | {predef_detection} + +| `+_MSC_FULL_VER+` | V.R.P +| `+_MSC_VER+` | V.R.0 +|=== + +NOTE: Release of Visual Studio after 2015 will no longer be identified +by Boost Predef as the marketing version number. Instead we use the +compiler version number directly, i.e. the _MSC_VER number. +*/ // end::reference[] + +#define BOOST_COMP_MSVC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(_MSC_VER) +# if !defined (_MSC_FULL_VER) +# define BOOST_COMP_MSVC_BUILD 0 +# else + /* how many digits does the build number have? */ +# if _MSC_FULL_VER / 10000 == _MSC_VER + /* four digits */ +# define BOOST_COMP_MSVC_BUILD (_MSC_FULL_VER % 10000) +# elif _MSC_FULL_VER / 100000 == _MSC_VER + /* five digits */ +# define BOOST_COMP_MSVC_BUILD (_MSC_FULL_VER % 100000) +# else +# error "Cannot determine build number from _MSC_FULL_VER" +# endif +# endif + /* + VS2014 was skipped in the release sequence for MS. Which + means that the compiler and VS product versions are no longer + in sync. Hence we need to use different formulas for + mapping from MSC version to VS product version. + + VS2017 is a total nightmare when it comes to version numbers. + Hence to avoid arguments relating to that both present and + future.. Any version after VS2015 will use solely the compiler + version, i.e. cl.exe, as the version number here. + */ +# if (_MSC_VER > 1900) +# define BOOST_COMP_MSVC_DETECTION BOOST_VERSION_NUMBER(\ + _MSC_VER/100,\ + _MSC_VER%100,\ + BOOST_COMP_MSVC_BUILD) +# elif (_MSC_VER >= 1900) +# define BOOST_COMP_MSVC_DETECTION BOOST_VERSION_NUMBER(\ + _MSC_VER/100-5,\ + _MSC_VER%100,\ + BOOST_COMP_MSVC_BUILD) +# else +# define BOOST_COMP_MSVC_DETECTION BOOST_VERSION_NUMBER(\ + _MSC_VER/100-6,\ + _MSC_VER%100,\ + BOOST_COMP_MSVC_BUILD) +# endif +#endif + +#ifdef BOOST_COMP_MSVC_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_MSVC_EMULATED BOOST_COMP_MSVC_DETECTION +# else +# undef BOOST_COMP_MSVC +# define BOOST_COMP_MSVC BOOST_COMP_MSVC_DETECTION +# endif +# define BOOST_COMP_MSVC_AVAILABLE +# include +#endif + +#define BOOST_COMP_MSVC_NAME "Microsoft Visual C/C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MSVC,BOOST_COMP_MSVC_NAME) + +#ifdef BOOST_COMP_MSVC_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MSVC_EMULATED,BOOST_COMP_MSVC_NAME) +#endif diff --git a/boost/predef/compiler/watcom.h b/boost/predef/compiler/watcom.h new file mode 100644 index 00000000..1f8c069d --- /dev/null +++ b/boost/predef/compiler/watcom.h @@ -0,0 +1,57 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_COMPILER_WATCOM_H +#define BOOST_PREDEF_COMPILER_WATCOM_H + +#include +#include + +/* tag::reference[] += `BOOST_COMP_WATCOM` + +http://en.wikipedia.org/wiki/Watcom[Watcom {CPP}] compiler. +Version number available as major, and minor. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__WATCOMC__+` | {predef_detection} + +| `+__WATCOMC__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_COMP_WATCOM BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__WATCOMC__) +# define BOOST_COMP_WATCOM_DETECTION BOOST_PREDEF_MAKE_10_VVRR(__WATCOMC__) +#endif + +#ifdef BOOST_COMP_WATCOM_DETECTION +# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED) +# define BOOST_COMP_WATCOM_EMULATED BOOST_COMP_WATCOM_DETECTION +# else +# undef BOOST_COMP_WATCOM +# define BOOST_COMP_WATCOM BOOST_COMP_WATCOM_DETECTION +# endif +# define BOOST_COMP_WATCOM_AVAILABLE +# include +#endif + +#define BOOST_COMP_WATCOM_NAME "Watcom C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_WATCOM,BOOST_COMP_WATCOM_NAME) + +#ifdef BOOST_COMP_WATCOM_EMULATED +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_WATCOM_EMULATED,BOOST_COMP_WATCOM_NAME) +#endif diff --git a/boost/predef/detail/_cassert.h b/boost/predef/detail/_cassert.h new file mode 100644 index 00000000..940e944e --- /dev/null +++ b/boost/predef/detail/_cassert.h @@ -0,0 +1,17 @@ +/* +Copyright Rene Rivera 2011-2012 +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) +*/ + +#ifndef BOOST_PREDEF_DETAIL__CASSERT_H +#define BOOST_PREDEF_DETAIL__CASSERT_H + +#if defined(__cplusplus) +#include +#else +#include +#endif + +#endif diff --git a/boost/predef/detail/_exception.h b/boost/predef/detail/_exception.h new file mode 100644 index 00000000..f5a6687a --- /dev/null +++ b/boost/predef/detail/_exception.h @@ -0,0 +1,15 @@ +/* +Copyright Rene Rivera 2011-2012 +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) +*/ + +#ifndef BOOST_PREDEF_DETAIL__EXCEPTION_H +#define BOOST_PREDEF_DETAIL__EXCEPTION_H + +#if defined(__cplusplus) +#include +#endif + +#endif diff --git a/boost/predef/detail/comp_detected.h b/boost/predef/detail/comp_detected.h new file mode 100644 index 00000000..fda1801b --- /dev/null +++ b/boost/predef/detail/comp_detected.h @@ -0,0 +1,10 @@ +/* +Copyright Rene Rivera 2014 +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) +*/ + +#ifndef BOOST_PREDEF_DETAIL_COMP_DETECTED +#define BOOST_PREDEF_DETAIL_COMP_DETECTED 1 +#endif diff --git a/boost/predef/hardware.h b/boost/predef/hardware.h new file mode 100644 index 00000000..972b73af --- /dev/null +++ b/boost/predef/hardware.h @@ -0,0 +1,16 @@ +/* +Copyright Charly Chevalier 2015 +Copyright Joel Falcou 2015 +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) +*/ + +#if !defined(BOOST_PREDEF_HARDWARE_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS) +#ifndef BOOST_PREDEF_HARDWARE_H +#define BOOST_PREDEF_HARDWARE_H +#endif + +#include + +#endif diff --git a/boost/predef/hardware/simd.h b/boost/predef/hardware/simd.h new file mode 100644 index 00000000..b671fa3b --- /dev/null +++ b/boost/predef/hardware/simd.h @@ -0,0 +1,168 @@ +/* +Copyright Charly Chevalier 2015 +Copyright Joel Falcou 2015 +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) +*/ + +#include +#include +#include +#include + +#ifndef BOOST_PREDEF_HARDWARE_SIMD_H +#define BOOST_PREDEF_HARDWARE_SIMD_H + +#include + +/* tag::reference[] += Using the `BOOST_HW_SIMD_*` predefs + +SIMD predefs depend on compiler options. For example, you will have to add the +option `-msse3` to clang or gcc to enable SSE3. SIMD predefs are also inclusive. +This means that if SSE3 is enabled, then every other extensions with a lower +version number will implicitly be enabled and detected. However, some extensions +are CPU specific, they may not be detected nor enabled when an upper version is +enabled. + +NOTE: SSE(1) and SSE2 are automatically enabled by default when using x86-64 +architecture. + +To check if any SIMD extension has been enabled, you can use: + +[source] +---- +#include +#include + +int main() +{ +#if defined(BOOST_HW_SIMD_AVAILABLE) + std::cout << "SIMD detected!" << std::endl; +#endif + return 0; +} +---- + +When writing SIMD specific code, you may want to check if a particular extension +has been detected. To do so you have to use the right architecture predef and +compare it. Those predef are of the form `BOOST_HW_SIMD_"ARCH"` (where `"ARCH"` +is either `ARM`, `PPC`, or `X86`). For example, if you compile code for x86 +architecture, you will have to use `BOOST_HW_SIMD_X86`. Its value will be the +version number of the most recent SIMD extension detected for the architecture. + +To check if an extension has been enabled: + +[source] +---- +#include +#include + +int main() +{ +#if BOOST_HW_SIMD_X86 >= BOOST_HW_SIMD_X86_SSE3_VERSION + std::cout << "This is SSE3!" << std::endl; +#endif + return 0; +} +---- + +NOTE: The *_VERSION* defines that map version number to actual real +identifiers. This way it is easier to write comparisons without messing up with +version numbers. + +To *"strictly"* check the most recent detected extension: + +[source] +---- +#include +#include + +int main() +{ +#if BOOST_HW_SIMD_X86 == BOOST_HW_SIMD_X86_SSE3_VERSION + std::cout << "This is SSE3 and this is the most recent enabled extension!" + << std::endl; +#endif + return 0; +} +---- + +Because of the version systems of predefs and of the inclusive property of SIMD +extensions macros, you can easily check for ranges of supported extensions: + +[source] +---- +#include +#include + +int main() +{ +#if BOOST_HW_SIMD_X86 >= BOOST_HW_SIMD_X86_SSE2_VERSION &&\ + BOOST_HW_SIMD_X86 <= BOOST_HW_SIMD_X86_SSSE3_VERSION + std::cout << "This is SSE2, SSE3 and SSSE3!" << std::endl; +#endif + return 0; +} +---- + +NOTE: Unlike gcc and clang, Visual Studio does not allow you to specify precisely +the SSE variants you want to use, the only detections that will take place are +SSE, SSE2, AVX and AVX2. For more informations, + see [@https://msdn.microsoft.com/en-us/library/b0084kay.aspx here]. + + +*/ // end::reference[] + +// We check if SIMD extension of multiples architectures have been detected, +// if yes, then this is an error! +// +// NOTE: _X86_AMD implies _X86, so there is no need to check for it here! +// +#if defined(BOOST_HW_SIMD_ARM_AVAILABLE) && defined(BOOST_HW_SIMD_PPC_AVAILABLE) ||\ + defined(BOOST_HW_SIMD_ARM_AVAILABLE) && defined(BOOST_HW_SIMD_X86_AVAILABLE) ||\ + defined(BOOST_HW_SIMD_PPC_AVAILABLE) && defined(BOOST_HW_SIMD_X86_AVAILABLE) +# error "Multiple SIMD architectures detected, this cannot happen!" +#endif + +#if defined(BOOST_HW_SIMD_X86_AVAILABLE) && defined(BOOST_HW_SIMD_X86_AMD_AVAILABLE) + // If both standard _X86 and _X86_AMD are available, + // then take the biggest version of the two! +# if BOOST_HW_SIMD_X86 >= BOOST_HW_SIMD_X86_AMD +# define BOOST_HW_SIMD BOOST_HW_SIMD_X86 +# else +# define BOOST_HW_SIMD BOOST_HW_SIMD_X86_AMD +# endif +#endif + +#if !defined(BOOST_HW_SIMD) + // At this point, only one of these two is defined +# if defined(BOOST_HW_SIMD_X86_AVAILABLE) +# define BOOST_HW_SIMD BOOST_HW_SIMD_X86 +# endif +# if defined(BOOST_HW_SIMD_X86_AMD_AVAILABLE) +# define BOOST_HW_SIMD BOOST_HW_SIMD_X86_AMD +# endif +#endif + +#if defined(BOOST_HW_SIMD_ARM_AVAILABLE) +# define BOOST_HW_SIMD BOOST_HW_SIMD_ARM +#endif + +#if defined(BOOST_HW_SIMD_PPC_AVAILABLE) +# define BOOST_HW_SIMD BOOST_HW_SIMD_PPC +#endif + +#if defined(BOOST_HW_SIMD) +# define BOOST_HW_SIMD_AVAILABLE +#else +# define BOOST_HW_SIMD BOOST_VERSION_NUMBER_NOT_AVAILABLE +#endif + +#define BOOST_HW_SIMD_NAME "Hardware SIMD" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_HW_SIMD, BOOST_HW_SIMD_NAME) diff --git a/boost/predef/hardware/simd/arm.h b/boost/predef/hardware/simd/arm.h new file mode 100644 index 00000000..24e4c1b0 --- /dev/null +++ b/boost/predef/hardware/simd/arm.h @@ -0,0 +1,61 @@ +/* +Copyright Charly Chevalier 2015 +Copyright Joel Falcou 2015 +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) +*/ + +#ifndef BOOST_PREDEF_HARDWARE_SIMD_ARM_H +#define BOOST_PREDEF_HARDWARE_SIMD_ARM_H + +#include +#include + +/* tag::reference[] += `BOOST_HW_SIMD_ARM` + +The SIMD extension for ARM (*if detected*). +Version number depends on the most recent detected extension. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__ARM_NEON__+` | {predef_detection} +| `+__aarch64__+` | {predef_detection} +| `+_M_ARM+` | {predef_detection} +| `+_M_ARM64+` | {predef_detection} +|=== + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__ARM_NEON__+` | BOOST_HW_SIMD_ARM_NEON_VERSION +| `+__aarch64__+` | BOOST_HW_SIMD_ARM_NEON_VERSION +| `+_M_ARM+` | BOOST_HW_SIMD_ARM_NEON_VERSION +| `+_M_ARM64+` | BOOST_HW_SIMD_ARM_NEON_VERSION +|=== + +*/ // end::reference[] + +#define BOOST_HW_SIMD_ARM BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#undef BOOST_HW_SIMD_ARM +#if !defined(BOOST_HW_SIMD_ARM) && (defined(__ARM_NEON__) || defined(__aarch64__) || defined (_M_ARM) || defined (_M_ARM64)) +# define BOOST_HW_SIMD_ARM BOOST_HW_SIMD_ARM_NEON_VERSION +#endif + +#if !defined(BOOST_HW_SIMD_ARM) +# define BOOST_HW_SIMD_ARM BOOST_VERSION_NUMBER_NOT_AVAILABLE +#else +# define BOOST_HW_SIMD_ARM_AVAILABLE +#endif + +#define BOOST_HW_SIMD_ARM_NAME "ARM SIMD" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_HW_SIMD_ARM, BOOST_HW_SIMD_ARM_NAME) diff --git a/boost/predef/hardware/simd/arm/versions.h b/boost/predef/hardware/simd/arm/versions.h new file mode 100644 index 00000000..92071a6b --- /dev/null +++ b/boost/predef/hardware/simd/arm/versions.h @@ -0,0 +1,38 @@ +/* +Copyright Charly Chevalier 2015 +Copyright Joel Falcou 2015 +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) +*/ + +#ifndef BOOST_PREDEF_HARDWARE_SIMD_ARM_VERSIONS_H +#define BOOST_PREDEF_HARDWARE_SIMD_ARM_VERSIONS_H + +#include + +/* tag::reference[] += `BOOST_HW_SIMD_ARM_*_VERSION` + +Those defines represent ARM SIMD extensions versions. + +NOTE: You *MUST* compare them with the predef `BOOST_HW_SIMD_ARM`. +*/ // end::reference[] + +// --------------------------------- + +/* tag::reference[] += `BOOST_HW_SIMD_ARM_NEON_VERSION` + +The https://en.wikipedia.org/wiki/ARM_architecture#Advanced_SIMD_.28NEON.29[NEON] +ARM extension version number. + +Version number is: *1.0.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_ARM_NEON_VERSION BOOST_VERSION_NUMBER(1, 0, 0) + +/* tag::reference[] + +*/ // end::reference[] + +#endif diff --git a/boost/predef/hardware/simd/ppc.h b/boost/predef/hardware/simd/ppc.h new file mode 100644 index 00000000..bf30cc1e --- /dev/null +++ b/boost/predef/hardware/simd/ppc.h @@ -0,0 +1,71 @@ +/* +Copyright Charly Chevalier 2015 +Copyright Joel Falcou 2015 +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) +*/ + +#ifndef BOOST_PREDEF_HARDWARE_SIMD_PPC_H +#define BOOST_PREDEF_HARDWARE_SIMD_PPC_H + +#include +#include + +/* tag::reference[] += `BOOST_HW_SIMD_PPC` + +The SIMD extension for PowerPC (*if detected*). +Version number depends on the most recent detected extension. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__VECTOR4DOUBLE__+` | {predef_detection} + +| `+__ALTIVEC__+` | {predef_detection} +| `+__VEC__+` | {predef_detection} + +| `+__VSX__+` | {predef_detection} +|=== + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__VECTOR4DOUBLE__+` | BOOST_HW_SIMD_PPC_QPX_VERSION + +| `+__ALTIVEC__+` | BOOST_HW_SIMD_PPC_VMX_VERSION +| `+__VEC__+` | BOOST_HW_SIMD_PPC_VMX_VERSION + +| `+__VSX__+` | BOOST_HW_SIMD_PPC_VSX_VERSION +|=== + +*/ // end::reference[] + +#define BOOST_HW_SIMD_PPC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#undef BOOST_HW_SIMD_PPC +#if !defined(BOOST_HW_SIMD_PPC) && defined(__VECTOR4DOUBLE__) +# define BOOST_HW_SIMD_PPC BOOST_HW_SIMD_PPC_QPX_VERSION +#endif +#if !defined(BOOST_HW_SIMD_PPC) && defined(__VSX__) +# define BOOST_HW_SIMD_PPC BOOST_HW_SIMD_PPC_VSX_VERSION +#endif +#if !defined(BOOST_HW_SIMD_PPC) && (defined(__ALTIVEC__) || defined(__VEC__)) +# define BOOST_HW_SIMD_PPC BOOST_HW_SIMD_PPC_VMX_VERSION +#endif + +#if !defined(BOOST_HW_SIMD_PPC) +# define BOOST_HW_SIMD_PPC BOOST_VERSION_NUMBER_NOT_AVAILABLE +#else +# define BOOST_HW_SIMD_PPC_AVAILABLE +#endif + +#define BOOST_HW_SIMD_PPC_NAME "PPC SIMD" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_HW_SIMD_PPC, BOOST_HW_SIMD_PPC_NAME) diff --git a/boost/predef/hardware/simd/ppc/versions.h b/boost/predef/hardware/simd/ppc/versions.h new file mode 100644 index 00000000..3cf8319c --- /dev/null +++ b/boost/predef/hardware/simd/ppc/versions.h @@ -0,0 +1,57 @@ +/* +Copyright Charly Chevalier 2015 +Copyright Joel Falcou 2015 +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) +*/ + +#ifndef BOOST_PREDEF_HARDWARE_SIMD_PPC_VERSIONS_H +#define BOOST_PREDEF_HARDWARE_SIMD_PPC_VERSIONS_H + +#include + +/* tag::reference[] += `BOOST_HW_SIMD_PPC_*_VERSION` + +Those defines represent Power PC SIMD extensions versions. + +NOTE: You *MUST* compare them with the predef `BOOST_HW_SIMD_PPC`. +*/ // end::reference[] + +// --------------------------------- + +/* tag::reference[] += `BOOST_HW_SIMD_PPC_VMX_VERSION` + +The https://en.wikipedia.org/wiki/AltiVec#VMX128[VMX] powerpc extension +version number. + +Version number is: *1.0.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_PPC_VMX_VERSION BOOST_VERSION_NUMBER(1, 0, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_PPC_VSX_VERSION` + +The https://en.wikipedia.org/wiki/AltiVec#VSX[VSX] powerpc extension version +number. + +Version number is: *1.1.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_PPC_VSX_VERSION BOOST_VERSION_NUMBER(1, 1, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_PPC_QPX_VERSION` + +The QPX powerpc extension version number. + +Version number is: *2.0.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_PPC_QPX_VERSION BOOST_VERSION_NUMBER(2, 0, 0) + +/* tag::reference[] + +*/ // end::reference[] + +#endif diff --git a/boost/predef/hardware/simd/x86.h b/boost/predef/hardware/simd/x86.h new file mode 100644 index 00000000..6c9a0fb8 --- /dev/null +++ b/boost/predef/hardware/simd/x86.h @@ -0,0 +1,125 @@ +/* +Copyright Charly Chevalier 2015 +Copyright Joel Falcou 2015 +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) +*/ + +#ifndef BOOST_PREDEF_HARDWARE_SIMD_X86_H +#define BOOST_PREDEF_HARDWARE_SIMD_X86_H + +#include +#include + +/* tag::reference[] += `BOOST_HW_SIMD_X86` + +The SIMD extension for x86 (*if detected*). +Version number depends on the most recent detected extension. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__SSE__+` | {predef_detection} +| `+_M_X64+` | {predef_detection} +| `_M_IX86_FP >= 1` | {predef_detection} + +| `+__SSE2__+` | {predef_detection} +| `+_M_X64+` | {predef_detection} +| `_M_IX86_FP >= 2` | {predef_detection} + +| `+__SSE3__+` | {predef_detection} + +| `+__SSSE3__+` | {predef_detection} + +| `+__SSE4_1__+` | {predef_detection} + +| `+__SSE4_2__+` | {predef_detection} + +| `+__AVX__+` | {predef_detection} + +| `+__FMA__+` | {predef_detection} + +| `+__AVX2__+` | {predef_detection} +|=== + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__SSE__+` | BOOST_HW_SIMD_X86_SSE_VERSION +| `+_M_X64+` | BOOST_HW_SIMD_X86_SSE_VERSION +| `_M_IX86_FP >= 1` | BOOST_HW_SIMD_X86_SSE_VERSION + +| `+__SSE2__+` | BOOST_HW_SIMD_X86_SSE2_VERSION +| `+_M_X64+` | BOOST_HW_SIMD_X86_SSE2_VERSION +| `_M_IX86_FP >= 2` | BOOST_HW_SIMD_X86_SSE2_VERSION + +| `+__SSE3__+` | BOOST_HW_SIMD_X86_SSE3_VERSION + +| `+__SSSE3__+` | BOOST_HW_SIMD_X86_SSSE3_VERSION + +| `+__SSE4_1__+` | BOOST_HW_SIMD_X86_SSE4_1_VERSION + +| `+__SSE4_2__+` | BOOST_HW_SIMD_X86_SSE4_2_VERSION + +| `+__AVX__+` | BOOST_HW_SIMD_X86_AVX_VERSION + +| `+__FMA__+` | BOOST_HW_SIMD_X86_FMA3_VERSION + +| `+__AVX2__+` | BOOST_HW_SIMD_X86_AVX2_VERSION +|=== + +*/ // end::reference[] + +#define BOOST_HW_SIMD_X86 BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#undef BOOST_HW_SIMD_X86 +#if !defined(BOOST_HW_SIMD_X86) && defined(__MIC__) +# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_MIC_VERSION +#endif +#if !defined(BOOST_HW_SIMD_X86) && defined(__AVX2__) +# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_AVX2_VERSION +#endif +#if !defined(BOOST_HW_SIMD_X86) && defined(__AVX__) +# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_AVX_VERSION +#endif +#if !defined(BOOST_HW_SIMD_X86) && defined(__FMA__) +# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_FMA_VERSION +#endif +#if !defined(BOOST_HW_SIMD_X86) && defined(__SSE4_2__) +# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSE4_2_VERSION +#endif +#if !defined(BOOST_HW_SIMD_X86) && defined(__SSE4_1__) +# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSE4_1_VERSION +#endif +#if !defined(BOOST_HW_SIMD_X86) && defined(__SSSE3__) +# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSSE3_VERSION +#endif +#if !defined(BOOST_HW_SIMD_X86) && defined(__SSE3__) +# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSE3_VERSION +#endif +#if !defined(BOOST_HW_SIMD_X86) && (defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)) +# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSE2_VERSION +#endif +#if !defined(BOOST_HW_SIMD_X86) && (defined(__SSE__) || defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1)) +# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSE_VERSION +#endif +#if !defined(BOOST_HW_SIMD_X86) && defined(__MMX__) +# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_MMX_VERSION +#endif + +#if !defined(BOOST_HW_SIMD_X86) +# define BOOST_HW_SIMD_X86 BOOST_VERSION_NUMBER_NOT_AVAILABLE +#else +# define BOOST_HW_SIMD_X86_AVAILABLE +#endif + +#define BOOST_HW_SIMD_X86_NAME "x86 SIMD" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_HW_SIMD_X86, BOOST_HW_SIMD_X86_NAME) diff --git a/boost/predef/hardware/simd/x86/versions.h b/boost/predef/hardware/simd/x86/versions.h new file mode 100644 index 00000000..ef5b002d --- /dev/null +++ b/boost/predef/hardware/simd/x86/versions.h @@ -0,0 +1,135 @@ +/* +Copyright Charly Chevalier 2015 +Copyright Joel Falcou 2015 +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) +*/ + +#ifndef BOOST_PREDEF_HARDWARE_SIMD_X86_VERSIONS_H +#define BOOST_PREDEF_HARDWARE_SIMD_X86_VERSIONS_H + +#include + +/* tag::reference[] += `BOOST_HW_SIMD_X86_*_VERSION` + +Those defines represent x86 SIMD extensions versions. + +NOTE: You *MUST* compare them with the predef `BOOST_HW_SIMD_X86`. +*/ // end::reference[] + +// --------------------------------- + +/* tag::reference[] += `BOOST_HW_SIMD_X86_MMX_VERSION` + +The https://en.wikipedia.org/wiki/MMX_(instruction_set)[MMX] x86 extension +version number. + +Version number is: *0.99.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_MMX_VERSION BOOST_VERSION_NUMBER(0, 99, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_X86_SSE_VERSION` + +The https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions[SSE] x86 extension +version number. + +Version number is: *1.0.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_SSE_VERSION BOOST_VERSION_NUMBER(1, 0, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_X86_SSE2_VERSION` + +The https://en.wikipedia.org/wiki/SSE2[SSE2] x86 extension version number. + +Version number is: *2.0.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_SSE2_VERSION BOOST_VERSION_NUMBER(2, 0, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_X86_SSE3_VERSION` + +The https://en.wikipedia.org/wiki/SSE3[SSE3] x86 extension version number. + +Version number is: *3.0.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_SSE3_VERSION BOOST_VERSION_NUMBER(3, 0, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_X86_SSSE3_VERSION` + +The https://en.wikipedia.org/wiki/SSSE3[SSSE3] x86 extension version number. + +Version number is: *3.1.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_SSSE3_VERSION BOOST_VERSION_NUMBER(3, 1, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_X86_SSE4_1_VERSION` + +The https://en.wikipedia.org/wiki/SSE4#SSE4.1[SSE4_1] x86 extension version +number. + +Version number is: *4.1.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_SSE4_1_VERSION BOOST_VERSION_NUMBER(4, 1, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_X86_SSE4_2_VERSION` + +The https://en.wikipedia.org/wiki/SSE4##SSE4.2[SSE4_2] x86 extension version +number. + +Version number is: *4.2.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_SSE4_2_VERSION BOOST_VERSION_NUMBER(4, 2, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_X86_AVX_VERSION` + +The https://en.wikipedia.org/wiki/Advanced_Vector_Extensions[AVX] x86 +extension version number. + +Version number is: *5.0.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_AVX_VERSION BOOST_VERSION_NUMBER(5, 0, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_X86_FMA3_VERSION` + +The https://en.wikipedia.org/wiki/FMA_instruction_set[FMA3] x86 extension +version number. + +Version number is: *5.2.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_FMA3_VERSION BOOST_VERSION_NUMBER(5, 2, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_X86_AVX2_VERSION` + +The https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2[AVX2] +x86 extension version number. + +Version number is: *5.3.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_AVX2_VERSION BOOST_VERSION_NUMBER(5, 3, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_X86_MIC_VERSION` + +The https://en.wikipedia.org/wiki/Xeon_Phi[MIC] (Xeon Phi) x86 extension +version number. + +Version number is: *9.0.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_MIC_VERSION BOOST_VERSION_NUMBER(9, 0, 0) + +/* tag::reference[] + +*/ // end::reference[] + +#endif diff --git a/boost/predef/hardware/simd/x86_amd.h b/boost/predef/hardware/simd/x86_amd.h new file mode 100644 index 00000000..ed96af35 --- /dev/null +++ b/boost/predef/hardware/simd/x86_amd.h @@ -0,0 +1,89 @@ +/* +Copyright Charly Chevalier 2015 +Copyright Joel Falcou 2015 +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) +*/ + +#ifndef BOOST_PREDEF_HARDWARE_SIMD_X86_AMD_H +#define BOOST_PREDEF_HARDWARE_SIMD_X86_AMD_H + +#include +#include + +/* tag::reference[] += `BOOST_HW_SIMD_X86_AMD` + +The SIMD extension for x86 (AMD) (*if detected*). +Version number depends on the most recent detected extension. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__SSE4A__+` | {predef_detection} + +| `+__FMA4__+` | {predef_detection} + +| `+__XOP__+` | {predef_detection} + +| `BOOST_HW_SIMD_X86` | {predef_detection} +|=== + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__SSE4A__+` | BOOST_HW_SIMD_X86_SSE4A_VERSION + +| `+__FMA4__+` | BOOST_HW_SIMD_X86_FMA4_VERSION + +| `+__XOP__+` | BOOST_HW_SIMD_X86_XOP_VERSION + +| `BOOST_HW_SIMD_X86` | BOOST_HW_SIMD_X86 +|=== + +NOTE: This predef includes every other x86 SIMD extensions and also has other +more specific extensions (FMA4, XOP, SSE4a). You should use this predef +instead of `BOOST_HW_SIMD_X86` to test if those specific extensions have +been detected. + +*/ // end::reference[] + +#define BOOST_HW_SIMD_X86_AMD BOOST_VERSION_NUMBER_NOT_AVAILABLE + +// AMD CPUs also use x86 architecture. We first try to detect if any AMD +// specific extension are detected, if yes, then try to detect more recent x86 +// common extensions. + +#undef BOOST_HW_SIMD_X86_AMD +#if !defined(BOOST_HW_SIMD_X86_AMD) && defined(__XOP__) +# define BOOST_HW_SIMD_X86_AMD BOOST_HW_SIMD_X86_AMD_XOP_VERSION +#endif +#if !defined(BOOST_HW_SIMD_X86_AMD) && defined(__FMA4__) +# define BOOST_HW_SIMD_X86_AMD BOOST_HW_SIMD_X86_AMD_FMA4_VERSION +#endif +#if !defined(BOOST_HW_SIMD_X86_AMD) && defined(__SSE4A__) +# define BOOST_HW_SIMD_X86_AMD BOOST_HW_SIMD_X86_AMD_SSE4A_VERSION +#endif + +#if !defined(BOOST_HW_SIMD_X86_AMD) +# define BOOST_HW_SIMD_X86_AMD BOOST_VERSION_NUMBER_NOT_AVAILABLE +#else + // At this point, we know that we have an AMD CPU, we do need to check for + // other x86 extensions to determine the final version number. +# include +# if BOOST_HW_SIMD_X86 > BOOST_HW_SIMD_X86_AMD +# undef BOOST_HW_SIMD_X86_AMD +# define BOOST_HW_SIMD_X86_AMD BOOST_HW_SIMD_X86 +# endif +# define BOOST_HW_SIMD_X86_AMD_AVAILABLE +#endif + +#define BOOST_HW_SIMD_X86_AMD_NAME "x86 (AMD) SIMD" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_HW_SIMD_X86_AMD, BOOST_HW_SIMD_X86_AMD_NAME) diff --git a/boost/predef/hardware/simd/x86_amd/versions.h b/boost/predef/hardware/simd/x86_amd/versions.h new file mode 100644 index 00000000..aa54a5cb --- /dev/null +++ b/boost/predef/hardware/simd/x86_amd/versions.h @@ -0,0 +1,56 @@ +/* +Copyright Charly Chevalier 2015 +Copyright Joel Falcou 2015 +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) +*/ + +#ifndef BOOST_PREDEF_HARDWARE_SIMD_X86_AMD_VERSIONS_H +#define BOOST_PREDEF_HARDWARE_SIMD_X86_AMD_VERSIONS_H + +#include + +/* tag::reference[] += `BOOST_HW_SIMD_X86_AMD_*_VERSION` + +Those defines represent x86 (AMD specific) SIMD extensions versions. + +NOTE: You *MUST* compare them with the predef `BOOST_HW_SIMD_X86_AMD`. +*/ // end::reference[] + + +// --------------------------------- + +/* tag::reference[] += `BOOST_HW_SIMD_X86_AMD_SSE4A_VERSION` + +https://en.wikipedia.org/wiki/SSE4##SSE4A[SSE4A] x86 extension (AMD specific). + +Version number is: *4.0.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_AMD_SSE4A_VERSION BOOST_VERSION_NUMBER(4, 0, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_X86_AMD_FMA4_VERSION` + +https://en.wikipedia.org/wiki/FMA_instruction_set#FMA4_instruction_set[FMA4] x86 extension (AMD specific). + +Version number is: *5.1.0*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_AMD_FMA4_VERSION BOOST_VERSION_NUMBER(5, 1, 0) + +/* tag::reference[] += `BOOST_HW_SIMD_X86_AMD_XOP_VERSION` + +https://en.wikipedia.org/wiki/XOP_instruction_set[XOP] x86 extension (AMD specific). + +Version number is: *5.1.1*. +*/ // end::reference[] +#define BOOST_HW_SIMD_X86_AMD_XOP_VERSION BOOST_VERSION_NUMBER(5, 1, 1) + +/* tag::reference[] + +*/ // end::reference[] + +#endif diff --git a/boost/predef/language.h b/boost/predef/language.h new file mode 100644 index 00000000..9ce3cc98 --- /dev/null +++ b/boost/predef/language.h @@ -0,0 +1,18 @@ +/* +Copyright Rene Rivera 2011-2015 +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) +*/ + +#if !defined(BOOST_PREDEF_LANGUAGE_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS) +#ifndef BOOST_PREDEF_LANGUAGE_H +#define BOOST_PREDEF_LANGUAGE_H +#endif + +#include +#include +#include +#include + +#endif diff --git a/boost/predef/language/cuda.h b/boost/predef/language/cuda.h new file mode 100644 index 00000000..1159af49 --- /dev/null +++ b/boost/predef/language/cuda.h @@ -0,0 +1,53 @@ +/* +Copyright Benjamin Worpitz 2018 +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) +*/ + +#ifndef BOOST_PREDEF_LANGUAGE_CUDA_H +#define BOOST_PREDEF_LANGUAGE_CUDA_H + +#include +#include + +/* tag::reference[] += `BOOST_LANG_CUDA` + +https://en.wikipedia.org/wiki/CUDA[CUDA C/{CPP}] language. +If available, the version is detected as VV.RR.P. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__CUDACC__+` | {predef_detection} +| `+__CUDA__+` | {predef_detection} + +| `CUDA_VERSION` | VV.RR.P +|=== +*/ // end::reference[] + +#define BOOST_LANG_CUDA BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__CUDACC__) || defined(__CUDA__) +# undef BOOST_LANG_CUDA +# include +# if defined(CUDA_VERSION) +# define BOOST_LANG_CUDA BOOST_PREDEF_MAKE_10_VVRRP(CUDA_VERSION) +# else +# define BOOST_LANG_CUDA BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_LANG_CUDA +# define BOOST_LANG_CUDA_AVAILABLE +#endif + +#define BOOST_LANG_CUDA_NAME "CUDA C/C++" + + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LANG_CUDA,BOOST_LANG_CUDA_NAME) diff --git a/boost/predef/language/objc.h b/boost/predef/language/objc.h new file mode 100644 index 00000000..c521371d --- /dev/null +++ b/boost/predef/language/objc.h @@ -0,0 +1,43 @@ +/* +Copyright Rene Rivera 2011-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LANGUAGE_OBJC_H +#define BOOST_PREDEF_LANGUAGE_OBJC_H + +#include +#include + +/* tag::reference[] += `BOOST_LANG_OBJC` + +http://en.wikipedia.org/wiki/Objective-C[Objective-C] language. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__OBJC__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_LANG_OBJC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__OBJC__) +# undef BOOST_LANG_OBJC +# define BOOST_LANG_OBJC BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_LANG_OBJC +# define BOOST_LANG_OBJC_AVAILABLE +#endif + +#define BOOST_LANG_OBJC_NAME "Objective-C" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LANG_OBJC,BOOST_LANG_OBJC_NAME) diff --git a/boost/predef/language/stdc.h b/boost/predef/language/stdc.h new file mode 100644 index 00000000..8cbd6a10 --- /dev/null +++ b/boost/predef/language/stdc.h @@ -0,0 +1,54 @@ +/* +Copyright Rene Rivera 2011-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LANGUAGE_STDC_H +#define BOOST_PREDEF_LANGUAGE_STDC_H + +#include +#include + +/* tag::reference[] += `BOOST_LANG_STDC` + +http://en.wikipedia.org/wiki/C_(programming_language)[Standard C] language. +If available, the year of the standard is detected as YYYY.MM.1 from the Epoch date. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__STDC__+` | {predef_detection} + +| `+__STDC_VERSION__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_LANG_STDC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__STDC__) +# undef BOOST_LANG_STDC +# if defined(__STDC_VERSION__) +# if (__STDC_VERSION__ > 100) +# define BOOST_LANG_STDC BOOST_PREDEF_MAKE_YYYYMM(__STDC_VERSION__) +# else +# define BOOST_LANG_STDC BOOST_VERSION_NUMBER_AVAILABLE +# endif +# else +# define BOOST_LANG_STDC BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_LANG_STDC +# define BOOST_LANG_STDC_AVAILABLE +#endif + +#define BOOST_LANG_STDC_NAME "Standard C" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LANG_STDC,BOOST_LANG_STDC_NAME) diff --git a/boost/predef/language/stdcpp.h b/boost/predef/language/stdcpp.h new file mode 100644 index 00000000..daa14cfc --- /dev/null +++ b/boost/predef/language/stdcpp.h @@ -0,0 +1,128 @@ +/* +Copyright Rene Rivera 2011-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LANGUAGE_STDCPP_H +#define BOOST_PREDEF_LANGUAGE_STDCPP_H + +#include +#include + +/* tag::reference[] += `BOOST_LANG_STDCPP` + +http://en.wikipedia.org/wiki/C%2B%2B[Standard {CPP}] language. +If available, the year of the standard is detected as YYYY.MM.1 from the Epoch date. +Because of the way the {CPP} standardization process works the +defined version year will not be the commonly known year of the standard. +Specifically the defined versions are: + +.Detected Version Number vs. {CPP} Standard Year +[options="header"] +|=== +| Detected Version Number | Standard Year | {CPP} Standard +| 27.11.1 | 1998 | ISO/IEC 14882:1998 +| 41.3.1 | 2011 | ISO/IEC 14882:2011 +| 44.2.1 | 2014 | ISO/IEC 14882:2014 +| 47.3.1 | 2017 | ISO/IEC 14882:2017 +|=== + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__cplusplus+` | {predef_detection} + +| `+__cplusplus+` | YYYY.MM.1 +|=== +*/ // end::reference[] + +#define BOOST_LANG_STDCPP BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__cplusplus) +# undef BOOST_LANG_STDCPP +# if (__cplusplus > 100) +# define BOOST_LANG_STDCPP BOOST_PREDEF_MAKE_YYYYMM(__cplusplus) +# else +# define BOOST_LANG_STDCPP BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_LANG_STDCPP +# define BOOST_LANG_STDCPP_AVAILABLE +#endif + +#define BOOST_LANG_STDCPP_NAME "Standard C++" + +/* tag::reference[] += `BOOST_LANG_STDCPPCLI` + +http://en.wikipedia.org/wiki/C%2B%2B/CLI[Standard {CPP}/CLI] language. +If available, the year of the standard is detected as YYYY.MM.1 from the Epoch date. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__cplusplus_cli+` | {predef_detection} + +| `+__cplusplus_cli+` | YYYY.MM.1 +|=== +*/ // end::reference[] + +#define BOOST_LANG_STDCPPCLI BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__cplusplus_cli) +# undef BOOST_LANG_STDCPPCLI +# if (__cplusplus_cli > 100) +# define BOOST_LANG_STDCPPCLI BOOST_PREDEF_MAKE_YYYYMM(__cplusplus_cli) +# else +# define BOOST_LANG_STDCPPCLI BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_LANG_STDCPPCLI +# define BOOST_LANG_STDCPPCLI_AVAILABLE +#endif + +#define BOOST_LANG_STDCPPCLI_NAME "Standard C++/CLI" + +/* tag::reference[] += `BOOST_LANG_STDECPP` + +http://en.wikipedia.org/wiki/Embedded_C%2B%2B[Standard Embedded {CPP}] language. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__embedded_cplusplus+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_LANG_STDECPP BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__embedded_cplusplus) +# undef BOOST_LANG_STDECPP +# define BOOST_LANG_STDECPP BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_LANG_STDECPP +# define BOOST_LANG_STDECPP_AVAILABLE +#endif + +#define BOOST_LANG_STDECPP_NAME "Standard Embedded C++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LANG_STDCPP,BOOST_LANG_STDCPP_NAME) + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LANG_STDCPPCLI,BOOST_LANG_STDCPPCLI_NAME) + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LANG_STDECPP,BOOST_LANG_STDECPP_NAME) diff --git a/boost/predef/library.h b/boost/predef/library.h new file mode 100644 index 00000000..40518a90 --- /dev/null +++ b/boost/predef/library.h @@ -0,0 +1,16 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#if !defined(BOOST_PREDEF_LIBRARY_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS) +#ifndef BOOST_PREDEF_LIBRARY_H +#define BOOST_PREDEF_LIBRARY_H +#endif + +#include +#include + +#endif diff --git a/boost/predef/library/c.h b/boost/predef/library/c.h new file mode 100644 index 00000000..7ca84cc0 --- /dev/null +++ b/boost/predef/library/c.h @@ -0,0 +1,21 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#if !defined(BOOST_PREDEF_LIBRARY_C_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS) +#ifndef BOOST_PREDEF_LIBRARY_C_H +#define BOOST_PREDEF_LIBRARY_C_H +#endif + +#include + +#include +#include +#include +#include +#include + +#endif diff --git a/boost/predef/library/c/_prefix.h b/boost/predef/library/c/_prefix.h new file mode 100644 index 00000000..12bcb0fb --- /dev/null +++ b/boost/predef/library/c/_prefix.h @@ -0,0 +1,13 @@ +/* +Copyright Rene Rivera 2008-2013 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_C__PREFIX_H +#define BOOST_PREDEF_LIBRARY_C__PREFIX_H + +#include + +#endif diff --git a/boost/predef/library/c/cloudabi.h b/boost/predef/library/c/cloudabi.h new file mode 100644 index 00000000..80ce81ca --- /dev/null +++ b/boost/predef/library/c/cloudabi.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2017 James E. King III + * + * 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) + */ + +#ifndef BOOST_PREDEF_LIBRARY_C_CLOUDABI_H +#define BOOST_PREDEF_LIBRARY_C_CLOUDABI_H + +#include +#include + +#include + +#if defined(__CloudABI__) +#include +#endif + +/* tag::reference[] += `BOOST_LIB_C_CLOUDABI` + +https://github.com/NuxiNL/cloudlibc[cloudlibc] - CloudABI's standard C library. +Version number available as major, and minor. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__cloudlibc__+` | {predef_detection} + +| `+__cloudlibc_major__+`, `+__cloudlibc_minor__+` | V.R.0 +|=== +*/ // end::reference[] + +#define BOOST_LIB_C_CLOUDABI BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__cloudlibc__) +# undef BOOST_LIB_C_CLOUDABI +# define BOOST_LIB_C_CLOUDABI \ + BOOST_VERSION_NUMBER(__cloudlibc_major__,__cloudlibc_minor__,0) +#endif + +#if BOOST_LIB_C_CLOUDABI +# define BOOST_LIB_C_CLOUDABI_AVAILABLE +#endif + +#define BOOST_LIB_C_CLOUDABI_NAME "cloudlibc" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_C_CLOUDABI,BOOST_LIB_C_CLOUDABI_NAME) diff --git a/boost/predef/library/c/gnu.h b/boost/predef/library/c/gnu.h new file mode 100644 index 00000000..dd7a2052 --- /dev/null +++ b/boost/predef/library/c/gnu.h @@ -0,0 +1,62 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_C_GNU_H +#define BOOST_PREDEF_LIBRARY_C_GNU_H + +#include +#include + +#include + +#if defined(__STDC__) +#include +#elif defined(__cplusplus) +#include +#endif + +/* tag::reference[] += `BOOST_LIB_C_GNU` + +http://en.wikipedia.org/wiki/Glibc[GNU glibc] Standard C library. +Version number available as major, and minor. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__GLIBC__+` | {predef_detection} +| `+__GNU_LIBRARY__+` | {predef_detection} + +| `+__GLIBC__+`, `+__GLIBC_MINOR__+` | V.R.0 +| `+__GNU_LIBRARY__+`, `+__GNU_LIBRARY_MINOR__+` | V.R.0 +|=== +*/ // end::reference[] + +#define BOOST_LIB_C_GNU BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__GLIBC__) || defined(__GNU_LIBRARY__) +# undef BOOST_LIB_C_GNU +# if defined(__GLIBC__) +# define BOOST_LIB_C_GNU \ + BOOST_VERSION_NUMBER(__GLIBC__,__GLIBC_MINOR__,0) +# else +# define BOOST_LIB_C_GNU \ + BOOST_VERSION_NUMBER(__GNU_LIBRARY__,__GNU_LIBRARY_MINOR__,0) +# endif +#endif + +#if BOOST_LIB_C_GNU +# define BOOST_LIB_C_GNU_AVAILABLE +#endif + +#define BOOST_LIB_C_GNU_NAME "GNU" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_C_GNU,BOOST_LIB_C_GNU_NAME) diff --git a/boost/predef/library/c/uc.h b/boost/predef/library/c/uc.h new file mode 100644 index 00000000..6eb22f0c --- /dev/null +++ b/boost/predef/library/c/uc.h @@ -0,0 +1,48 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_C_UC_H +#define BOOST_PREDEF_LIBRARY_C_UC_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_C_UC` + +http://en.wikipedia.org/wiki/Uclibc[uClibc] Standard C library. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__UCLIBC__+` | {predef_detection} + +| `+__UCLIBC_MAJOR__+`, `+__UCLIBC_MINOR__+`, `+__UCLIBC_SUBLEVEL__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_LIB_C_UC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__UCLIBC__) +# undef BOOST_LIB_C_UC +# define BOOST_LIB_C_UC BOOST_VERSION_NUMBER(\ + __UCLIBC_MAJOR__,__UCLIBC_MINOR__,__UCLIBC_SUBLEVEL__) +#endif + +#if BOOST_LIB_C_UC +# define BOOST_LIB_C_UC_AVAILABLE +#endif + +#define BOOST_LIB_C_UC_NAME "uClibc" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_C_UC,BOOST_LIB_C_UC_NAME) diff --git a/boost/predef/library/c/vms.h b/boost/predef/library/c/vms.h new file mode 100644 index 00000000..ca9050f8 --- /dev/null +++ b/boost/predef/library/c/vms.h @@ -0,0 +1,48 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_C_VMS_H +#define BOOST_PREDEF_LIBRARY_C_VMS_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_C_VMS` + +VMS libc Standard C library. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__CRTL_VER+` | {predef_detection} + +| `+__CRTL_VER+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_LIB_C_VMS BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__CRTL_VER) +# undef BOOST_LIB_C_VMS +# define BOOST_LIB_C_VMS BOOST_PREDEF_MAKE_10_VVRR0PP00(__CRTL_VER) +#endif + +#if BOOST_LIB_C_VMS +# define BOOST_LIB_C_VMS_AVAILABLE +#endif + +#define BOOST_LIB_C_VMS_NAME "VMS" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_C_VMS,BOOST_LIB_C_VMS_NAME) diff --git a/boost/predef/library/c/zos.h b/boost/predef/library/c/zos.h new file mode 100644 index 00000000..83907621 --- /dev/null +++ b/boost/predef/library/c/zos.h @@ -0,0 +1,57 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_C_ZOS_H +#define BOOST_PREDEF_LIBRARY_C_ZOS_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_C_ZOS` + +z/OS libc Standard C library. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__LIBREL__+` | {predef_detection} + +| `+__LIBREL__+` | V.R.P +| `+__TARGET_LIB__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_LIB_C_ZOS BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__LIBREL__) +# undef BOOST_LIB_C_ZOS +# if !defined(BOOST_LIB_C_ZOS) && defined(__LIBREL__) +# define BOOST_LIB_C_ZOS BOOST_PREDEF_MAKE_0X_VRRPPPP(__LIBREL__) +# endif +# if !defined(BOOST_LIB_C_ZOS) && defined(__TARGET_LIB__) +# define BOOST_LIB_C_ZOS BOOST_PREDEF_MAKE_0X_VRRPPPP(__TARGET_LIB__) +# endif +# if !defined(BOOST_LIB_C_ZOS) +# define BOOST_LIB_C_ZOS BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_LIB_C_ZOS +# define BOOST_LIB_C_ZOS_AVAILABLE +#endif + +#define BOOST_LIB_C_ZOS_NAME "z/OS" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_C_ZOS,BOOST_LIB_C_ZOS_NAME) diff --git a/boost/predef/library/std.h b/boost/predef/library/std.h new file mode 100644 index 00000000..f8d34b45 --- /dev/null +++ b/boost/predef/library/std.h @@ -0,0 +1,26 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ +#if !defined(BOOST_PREDEF_LIBRARY_STD_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS) +#ifndef BOOST_PREDEF_LIBRARY_STD_H +#define BOOST_PREDEF_LIBRARY_STD_H +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/boost/predef/library/std/_prefix.h b/boost/predef/library/std/_prefix.h new file mode 100644 index 00000000..932b8557 --- /dev/null +++ b/boost/predef/library/std/_prefix.h @@ -0,0 +1,23 @@ +/* +Copyright Rene Rivera 2008-2013 +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) +*/ +#ifndef BOOST_PREDEF_LIBRARY_STD__PREFIX_H +#define BOOST_PREDEF_LIBRARY_STD__PREFIX_H + +/* +We need to include an STD header to gives us the context +of which library we are using. The "smallest" code-wise header +seems to be . Boost uses but as far +as I can tell (RR) it's not a stand-alone header in most +implementations. Using also has the benefit of +being available in EC++, so we get a chance to make this work +for embedded users. And since it's not a header impacted by TR1 +there's no magic needed for inclusion in the face of the +Boost.TR1 library. +*/ +#include + +#endif diff --git a/boost/predef/library/std/cxx.h b/boost/predef/library/std/cxx.h new file mode 100644 index 00000000..470c80da --- /dev/null +++ b/boost/predef/library/std/cxx.h @@ -0,0 +1,47 @@ +/* +Copyright Rene Rivera 2011-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_STD_CXX_H +#define BOOST_PREDEF_LIBRARY_STD_CXX_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_STD_CXX` + +http://libcxx.llvm.org/[libc++] {CPP} Standard Library. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+_LIBCPP_VERSION+` | {predef_detection} + +| `+_LIBCPP_VERSION+` | V.0.P +|=== +*/ // end::reference[] + +#define BOOST_LIB_STD_CXX BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(_LIBCPP_VERSION) +# undef BOOST_LIB_STD_CXX +# define BOOST_LIB_STD_CXX BOOST_PREDEF_MAKE_10_VVPPP(_LIBCPP_VERSION) +#endif + +#if BOOST_LIB_STD_CXX +# define BOOST_LIB_STD_CXX_AVAILABLE +#endif + +#define BOOST_LIB_STD_CXX_NAME "libc++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_CXX,BOOST_LIB_STD_CXX_NAME) diff --git a/boost/predef/library/std/dinkumware.h b/boost/predef/library/std/dinkumware.h new file mode 100644 index 00000000..5a4bc57a --- /dev/null +++ b/boost/predef/library/std/dinkumware.h @@ -0,0 +1,53 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_STD_DINKUMWARE_H +#define BOOST_PREDEF_LIBRARY_STD_DINKUMWARE_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_STD_DINKUMWARE` + +http://en.wikipedia.org/wiki/Dinkumware[Dinkumware] Standard {CPP} Library. +If available version number as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+_YVALS+`, `+__IBMCPP__+` | {predef_detection} +| `+_CPPLIB_VER+` | {predef_detection} + +| `+_CPPLIB_VER+` | V.R.0 +|=== +*/ // end::reference[] + +#define BOOST_LIB_STD_DINKUMWARE BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER) +# undef BOOST_LIB_STD_DINKUMWARE +# if defined(_CPPLIB_VER) +# define BOOST_LIB_STD_DINKUMWARE BOOST_PREDEF_MAKE_10_VVRR(_CPPLIB_VER) +# else +# define BOOST_LIB_STD_DINKUMWARE BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_LIB_STD_DINKUMWARE +# define BOOST_LIB_STD_DINKUMWARE_AVAILABLE +#endif + +#define BOOST_LIB_STD_DINKUMWARE_NAME "Dinkumware" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_DINKUMWARE,BOOST_LIB_STD_DINKUMWARE_NAME) diff --git a/boost/predef/library/std/libcomo.h b/boost/predef/library/std/libcomo.h new file mode 100644 index 00000000..a2116c85 --- /dev/null +++ b/boost/predef/library/std/libcomo.h @@ -0,0 +1,48 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_STD_LIBCOMO_H +#define BOOST_PREDEF_LIBRARY_STD_LIBCOMO_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_STD_COMO` + +http://www.comeaucomputing.com/libcomo/[Comeau Computing] Standard {CPP} Library. +Version number available as major. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__LIBCOMO__+` | {predef_detection} + +| `+__LIBCOMO_VERSION__+` | V.0.0 +|=== +*/ // end::reference[] + +#define BOOST_LIB_STD_COMO BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__LIBCOMO__) +# undef BOOST_LIB_STD_COMO +# define BOOST_LIB_STD_COMO BOOST_VERSION_NUMBER(__LIBCOMO_VERSION__,0,0) +#endif + +#if BOOST_LIB_STD_COMO +# define BOOST_LIB_STD_COMO_AVAILABLE +#endif + +#define BOOST_LIB_STD_COMO_NAME "Comeau Computing" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_COMO,BOOST_LIB_STD_COMO_NAME) diff --git a/boost/predef/library/std/modena.h b/boost/predef/library/std/modena.h new file mode 100644 index 00000000..4ce1cfcd --- /dev/null +++ b/boost/predef/library/std/modena.h @@ -0,0 +1,46 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_STD_MODENA_H +#define BOOST_PREDEF_LIBRARY_STD_MODENA_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_STD_MSIPL` + +http://modena.us/[Modena Software Lib++] Standard {CPP} Library. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `MSIPL_COMPILE_H` | {predef_detection} +| `+__MSIPL_COMPILE_H+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_LIB_STD_MSIPL BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(MSIPL_COMPILE_H) || defined(__MSIPL_COMPILE_H) +# undef BOOST_LIB_STD_MSIPL +# define BOOST_LIB_STD_MSIPL BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_LIB_STD_MSIPL +# define BOOST_LIB_STD_MSIPL_AVAILABLE +#endif + +#define BOOST_LIB_STD_MSIPL_NAME "Modena Software Lib++" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_MSIPL,BOOST_LIB_STD_MSIPL_NAME) diff --git a/boost/predef/library/std/msl.h b/boost/predef/library/std/msl.h new file mode 100644 index 00000000..932da795 --- /dev/null +++ b/boost/predef/library/std/msl.h @@ -0,0 +1,54 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_STD_MSL_H +#define BOOST_PREDEF_LIBRARY_STD_MSL_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_STD_MSL` + +http://www.freescale.com/[Metrowerks] Standard {CPP} Library. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__MSL_CPP__+` | {predef_detection} +| `+__MSL__+` | {predef_detection} + +| `+__MSL_CPP__+` | V.R.P +| `+__MSL__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_LIB_STD_MSL BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__MSL_CPP__) || defined(__MSL__) +# undef BOOST_LIB_STD_MSL +# if defined(__MSL_CPP__) +# define BOOST_LIB_STD_MSL BOOST_PREDEF_MAKE_0X_VRPP(__MSL_CPP__) +# else +# define BOOST_LIB_STD_MSL BOOST_PREDEF_MAKE_0X_VRPP(__MSL__) +# endif +#endif + +#if BOOST_LIB_STD_MSL +# define BOOST_LIB_STD_MSL_AVAILABLE +#endif + +#define BOOST_LIB_STD_MSL_NAME "Metrowerks" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_MSL,BOOST_LIB_STD_MSL_NAME) diff --git a/boost/predef/library/std/msvc.h b/boost/predef/library/std/msvc.h new file mode 100644 index 00000000..de336626 --- /dev/null +++ b/boost/predef/library/std/msvc.h @@ -0,0 +1,53 @@ +/* +Copyright Henrik S. Gaßmann 2023 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_STD_MSVC_H +#define BOOST_PREDEF_LIBRARY_STD_MSVC_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_STD_MSVC` + +https://github.com/microsoft/STL[Microsoft's {CPP} Standard Library]. +If available version number as major, minor, and patch. +The patch number is derived from `_MSVC_STL_UPDATE` by taking its five last +digits (see below). This implies that pasting a `_MSVC_STL_UPDATE` value into +`BOOST_VERSION_NUMBER` will produce a version number that is directly comparable +to `BOOST_LIB_STD_MSVC`. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+_MSVC_STL_VERSION+` | {predef_detection} + +| `+_MSVC_STL_VERSION+` | VV.R.0 +| `+_MSVC_STL_UPDATE+` | 00.0.0YYYMM +|=== +*/ // end::reference[] + +#define BOOST_LIB_STD_MSVC BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(_MSVC_STL_VERSION) +# undef BOOST_LIB_STD_MSVC +# define BOOST_LIB_STD_MSVC BOOST_PREDEF_MAKE_10_VVR_0PPPPP(_MSVC_STL_VERSION, _MSVC_STL_UPDATE) +#endif + +#if BOOST_LIB_STD_MSVC +# define BOOST_LIB_STD_MSVC_AVAILABLE +#endif + +#define BOOST_LIB_STD_MSVC_NAME "Microsoft stdlib" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_MSVC, BOOST_LIB_STD_MSVC_NAME) diff --git a/boost/predef/library/std/roguewave.h b/boost/predef/library/std/roguewave.h new file mode 100644 index 00000000..c64cb061 --- /dev/null +++ b/boost/predef/library/std/roguewave.h @@ -0,0 +1,57 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_STD_ROGUEWAVE_H +#define BOOST_PREDEF_LIBRARY_STD_ROGUEWAVE_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_STD_RW` + +http://stdcxx.apache.org/[Roguewave] Standard {CPP} library. +If available version number as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__STD_RWCOMPILER_H__+` | {predef_detection} +| `+_RWSTD_VER+` | {predef_detection} + +| `+_RWSTD_VER+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_LIB_STD_RW BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER) +# undef BOOST_LIB_STD_RW +# if defined(_RWSTD_VER) +# if _RWSTD_VER < 0x010000 +# define BOOST_LIB_STD_RW BOOST_PREDEF_MAKE_0X_VVRRP(_RWSTD_VER) +# else +# define BOOST_LIB_STD_RW BOOST_PREDEF_MAKE_0X_VVRRPP(_RWSTD_VER) +# endif +# else +# define BOOST_LIB_STD_RW BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_LIB_STD_RW +# define BOOST_LIB_STD_RW_AVAILABLE +#endif + +#define BOOST_LIB_STD_RW_NAME "Roguewave" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_RW,BOOST_LIB_STD_RW_NAME) diff --git a/boost/predef/library/std/sgi.h b/boost/predef/library/std/sgi.h new file mode 100644 index 00000000..3d11dd43 --- /dev/null +++ b/boost/predef/library/std/sgi.h @@ -0,0 +1,52 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_STD_SGI_H +#define BOOST_PREDEF_LIBRARY_STD_SGI_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_STD_SGI` + +http://www.sgi.com/tech/stl/[SGI] Standard {CPP} library. +If available version number as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__STL_CONFIG_H+` | {predef_detection} + +| `+__SGI_STL+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_LIB_STD_SGI BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__STL_CONFIG_H) +# undef BOOST_LIB_STD_SGI +# if defined(__SGI_STL) +# define BOOST_LIB_STD_SGI BOOST_PREDEF_MAKE_0X_VRP(__SGI_STL) +# else +# define BOOST_LIB_STD_SGI BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_LIB_STD_SGI +# define BOOST_LIB_STD_SGI_AVAILABLE +#endif + +#define BOOST_LIB_STD_SGI_NAME "SGI" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_SGI,BOOST_LIB_STD_SGI_NAME) diff --git a/boost/predef/library/std/stdcpp3.h b/boost/predef/library/std/stdcpp3.h new file mode 100644 index 00000000..90aa3d18 --- /dev/null +++ b/boost/predef/library/std/stdcpp3.h @@ -0,0 +1,54 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_STD_STDCPP3_H +#define BOOST_PREDEF_LIBRARY_STD_STDCPP3_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_STD_GNU` + +https://gcc.gnu.org/onlinedocs/libstdc%2b%2b/[GNU libstdc++] Standard {CPP} library. +Version number available as year (from 1970), month, and day. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__GLIBCXX__+` | {predef_detection} +| `+__GLIBCPP__+` | {predef_detection} + +| `+__GLIBCXX__+` | V.R.P +| `+__GLIBCPP__+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_LIB_STD_GNU BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__GLIBCPP__) || defined(__GLIBCXX__) +# undef BOOST_LIB_STD_GNU +# if defined(__GLIBCXX__) +# define BOOST_LIB_STD_GNU BOOST_PREDEF_MAKE_YYYYMMDD(__GLIBCXX__) +# else +# define BOOST_LIB_STD_GNU BOOST_PREDEF_MAKE_YYYYMMDD(__GLIBCPP__) +# endif +#endif + +#if BOOST_LIB_STD_GNU +# define BOOST_LIB_STD_GNU_AVAILABLE +#endif + +#define BOOST_LIB_STD_GNU_NAME "GNU" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_GNU,BOOST_LIB_STD_GNU_NAME) diff --git a/boost/predef/library/std/stlport.h b/boost/predef/library/std/stlport.h new file mode 100644 index 00000000..9d7f14f8 --- /dev/null +++ b/boost/predef/library/std/stlport.h @@ -0,0 +1,60 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_STD_STLPORT_H +#define BOOST_PREDEF_LIBRARY_STD_STLPORT_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_STD_STLPORT` + +http://sourceforge.net/projects/stlport/[STLport Standard {CPP}] library. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__SGI_STL_PORT+` | {predef_detection} +| `+_STLPORT_VERSION+` | {predef_detection} + +| `+_STLPORT_MAJOR+`, `+_STLPORT_MINOR+`, `+_STLPORT_PATCHLEVEL+` | V.R.P +| `+_STLPORT_VERSION+` | V.R.P +| `+__SGI_STL_PORT+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_LIB_STD_STLPORT BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION) +# undef BOOST_LIB_STD_STLPORT +# if !defined(BOOST_LIB_STD_STLPORT) && defined(_STLPORT_MAJOR) +# define BOOST_LIB_STD_STLPORT \ + BOOST_VERSION_NUMBER(_STLPORT_MAJOR,_STLPORT_MINOR,_STLPORT_PATCHLEVEL) +# endif +# if !defined(BOOST_LIB_STD_STLPORT) && defined(_STLPORT_VERSION) +# define BOOST_LIB_STD_STLPORT BOOST_PREDEF_MAKE_0X_VRP(_STLPORT_VERSION) +# endif +# if !defined(BOOST_LIB_STD_STLPORT) +# define BOOST_LIB_STD_STLPORT BOOST_PREDEF_MAKE_0X_VRP(__SGI_STL_PORT) +# endif +#endif + +#if BOOST_LIB_STD_STLPORT +# define BOOST_LIB_STD_STLPORT_AVAILABLE +#endif + +#define BOOST_LIB_STD_STLPORT_NAME "STLport" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_STLPORT,BOOST_LIB_STD_STLPORT_NAME) diff --git a/boost/predef/library/std/vacpp.h b/boost/predef/library/std/vacpp.h new file mode 100644 index 00000000..6165feff --- /dev/null +++ b/boost/predef/library/std/vacpp.h @@ -0,0 +1,45 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_LIBRARY_STD_VACPP_H +#define BOOST_PREDEF_LIBRARY_STD_VACPP_H + +#include + +#include +#include + +/* tag::reference[] += `BOOST_LIB_STD_IBM` + +http://www.ibm.com/software/awdtools/xlcpp/[IBM VACPP Standard {CPP}] library. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__IBMCPP__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_LIB_STD_IBM BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__IBMCPP__) +# undef BOOST_LIB_STD_IBM +# define BOOST_LIB_STD_IBM BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_LIB_STD_IBM +# define BOOST_LIB_STD_IBM_AVAILABLE +#endif + +#define BOOST_LIB_STD_IBM_NAME "IBM VACPP" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_IBM,BOOST_LIB_STD_IBM_NAME) diff --git a/boost/predef/os.h b/boost/predef/os.h new file mode 100644 index 00000000..da28e1c4 --- /dev/null +++ b/boost/predef/os.h @@ -0,0 +1,32 @@ +/* +Copyright Rene Rivera 2008-2015 +Copyright Franz Detro 2014 +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) +*/ + +#if !defined(BOOST_PREDEF_OS_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS) +#ifndef BOOST_PREDEF_OS_H +#define BOOST_PREDEF_OS_H +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/boost/predef/os/aix.h b/boost/predef/os/aix.h new file mode 100644 index 00000000..9bfe740c --- /dev/null +++ b/boost/predef/os/aix.h @@ -0,0 +1,67 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_AIX_H +#define BOOST_PREDEF_OS_AIX_H + +#include +#include + +/* tag::reference[] += `BOOST_OS_AIX` + +http://en.wikipedia.org/wiki/AIX_operating_system[IBM AIX] operating system. +Version number available as major, minor, and patch. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+_AIX+` | {predef_detection} +| `+__TOS_AIX__+` | {predef_detection} + +| `+_AIX43+` | 4.3.0 +| `+_AIX41+` | 4.1.0 +| `+_AIX32+` | 3.2.0 +| `+_AIX3+` | 3.0.0 +|=== +*/ // end::reference[] + +#define BOOST_OS_AIX BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(_AIX) || defined(__TOS_AIX__) \ + ) +# undef BOOST_OS_AIX +# if !defined(BOOST_OS_AIX) && defined(_AIX43) +# define BOOST_OS_AIX BOOST_VERSION_NUMBER(4,3,0) +# endif +# if !defined(BOOST_OS_AIX) && defined(_AIX41) +# define BOOST_OS_AIX BOOST_VERSION_NUMBER(4,1,0) +# endif +# if !defined(BOOST_OS_AIX) && defined(_AIX32) +# define BOOST_OS_AIX BOOST_VERSION_NUMBER(3,2,0) +# endif +# if !defined(BOOST_OS_AIX) && defined(_AIX3) +# define BOOST_OS_AIX BOOST_VERSION_NUMBER(3,0,0) +# endif +# if !defined(BOOST_OS_AIX) +# define BOOST_OS_AIX BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_OS_AIX +# define BOOST_OS_AIX_AVAILABLE +# include +#endif + +#define BOOST_OS_AIX_NAME "IBM AIX" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_AIX,BOOST_OS_AIX_NAME) diff --git a/boost/predef/os/amigaos.h b/boost/predef/os/amigaos.h new file mode 100644 index 00000000..c6a1f71a --- /dev/null +++ b/boost/predef/os/amigaos.h @@ -0,0 +1,47 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_AMIGAOS_H +#define BOOST_PREDEF_OS_AMIGAOS_H + +#include +#include + +/* tag::reference[] += `BOOST_OS_AMIGAOS` + +http://en.wikipedia.org/wiki/AmigaOS[AmigaOS] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `AMIGA` | {predef_detection} +| `+__amigaos__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_OS_AMIGAOS BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(AMIGA) || defined(__amigaos__) \ + ) +# undef BOOST_OS_AMIGAOS +# define BOOST_OS_AMIGAOS BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_OS_AMIGAOS +# define BOOST_OS_AMIGAOS_AVAILABLE +# include +#endif + +#define BOOST_OS_AMIGAOS_NAME "AmigaOS" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_AMIGAOS,BOOST_OS_AMIGAOS_NAME) diff --git a/boost/predef/os/beos.h b/boost/predef/os/beos.h new file mode 100644 index 00000000..8f764875 --- /dev/null +++ b/boost/predef/os/beos.h @@ -0,0 +1,46 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_BEOS_H +#define BOOST_PREDEF_OS_BEOS_H + +#include +#include + +/* tag::reference[] += `BOOST_OS_BEOS` + +http://en.wikipedia.org/wiki/BeOS[BeOS] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__BEOS__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_OS_BEOS BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(__BEOS__) \ + ) +# undef BOOST_OS_BEOS +# define BOOST_OS_BEOS BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_OS_BEOS +# define BOOST_OS_BEOS_AVAILABLE +# include +#endif + +#define BOOST_OS_BEOS_NAME "BeOS" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BEOS,BOOST_OS_BEOS_NAME) diff --git a/boost/predef/os/bsd.h b/boost/predef/os/bsd.h new file mode 100644 index 00000000..528a5972 --- /dev/null +++ b/boost/predef/os/bsd.h @@ -0,0 +1,102 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_BSD_H +#define BOOST_PREDEF_OS_BSD_H + +/* Special case: OSX will define BSD predefs if the sys/param.h + * header is included. We can guard against that, but only if we + * detect OSX first. Hence we will force include OSX detection + * before doing any BSD detection. + */ +#include + +#include +#include + +/* tag::reference[] += `BOOST_OS_BSD` + +http://en.wikipedia.org/wiki/Berkeley_Software_Distribution[BSD] operating system. + +BSD has various branch operating systems possible and each detected +individually. This detects the following variations and sets a specific +version number macro to match: + +* `BOOST_OS_BSD_DRAGONFLY` http://en.wikipedia.org/wiki/DragonFly_BSD[DragonFly BSD] +* `BOOST_OS_BSD_FREE` http://en.wikipedia.org/wiki/Freebsd[FreeBSD] +* `BOOST_OS_BSD_BSDI` http://en.wikipedia.org/wiki/BSD/OS[BSDi BSD/OS] +* `BOOST_OS_BSD_NET` http://en.wikipedia.org/wiki/Netbsd[NetBSD] +* `BOOST_OS_BSD_OPEN` http://en.wikipedia.org/wiki/Openbsd[OpenBSD] + +NOTE: The general `BOOST_OS_BSD` is set in all cases to indicate some form +of BSD. If the above variants is detected the corresponding macro is also set. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `BSD` | {predef_detection} +| `+_SYSTYPE_BSD+` | {predef_detection} + +| `BSD4_2` | 4.2.0 +| `BSD4_3` | 4.3.0 +| `BSD4_4` | 4.4.0 +| `BSD` | V.R.0 +|=== +*/ // end::reference[] + +#include +#include +#include +#include +#include + +#ifndef BOOST_OS_BSD +#define BOOST_OS_BSD BOOST_VERSION_NUMBER_NOT_AVAILABLE +#endif + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(BSD) || \ + defined(_SYSTYPE_BSD) \ + ) +# undef BOOST_OS_BSD +# include +# if !defined(BOOST_OS_BSD) && defined(BSD4_4) +# define BOOST_OS_BSD BOOST_VERSION_NUMBER(4,4,0) +# endif +# if !defined(BOOST_OS_BSD) && defined(BSD4_3) +# define BOOST_OS_BSD BOOST_VERSION_NUMBER(4,3,0) +# endif +# if !defined(BOOST_OS_BSD) && defined(BSD4_2) +# define BOOST_OS_BSD BOOST_VERSION_NUMBER(4,2,0) +# endif +# if !defined(BOOST_OS_BSD) && defined(BSD) +# define BOOST_OS_BSD BOOST_PREDEF_MAKE_10_VVRR(BSD) +# endif +# if !defined(BOOST_OS_BSD) +# define BOOST_OS_BSD BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_OS_BSD +# define BOOST_OS_BSD_AVAILABLE +# include +#endif + +#define BOOST_OS_BSD_NAME "BSD" + +#endif + +#include +#include +#include +#include +#include + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BSD,BOOST_OS_BSD_NAME) diff --git a/boost/predef/os/bsd/bsdi.h b/boost/predef/os/bsd/bsdi.h new file mode 100644 index 00000000..d0a5dcd9 --- /dev/null +++ b/boost/predef/os/bsd/bsdi.h @@ -0,0 +1,50 @@ +/* +Copyright Rene Rivera 2012-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_BSD_BSDI_H +#define BOOST_PREDEF_OS_BSD_BSDI_H + +#include + +/* tag::reference[] += `BOOST_OS_BSD_BSDI` + +http://en.wikipedia.org/wiki/BSD/OS[BSDi BSD/OS] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__bsdi__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_OS_BSD_BSDI BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(__bsdi__) \ + ) +# ifndef BOOST_OS_BSD_AVAILABLE +# undef BOOST_OS_BSD +# define BOOST_OS_BSD BOOST_VERSION_NUMBER_AVAILABLE +# define BOOST_OS_BSD_AVAILABLE +# endif +# undef BOOST_OS_BSD_BSDI +# define BOOST_OS_BSD_BSDI BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_OS_BSD_BSDI +# define BOOST_OS_BSD_BSDI_AVAILABLE +# include +#endif + +#define BOOST_OS_BSD_BSDI_NAME "BSDi BSD/OS" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BSD_BSDI,BOOST_OS_BSD_BSDI_NAME) diff --git a/boost/predef/os/bsd/dragonfly.h b/boost/predef/os/bsd/dragonfly.h new file mode 100644 index 00000000..43207779 --- /dev/null +++ b/boost/predef/os/bsd/dragonfly.h @@ -0,0 +1,52 @@ +/* +Copyright Rene Rivera 2012-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_BSD_DRAGONFLY_H +#define BOOST_PREDEF_OS_BSD_DRAGONFLY_H + +#include + +/* tag::reference[] += `BOOST_OS_BSD_DRAGONFLY` + +http://en.wikipedia.org/wiki/DragonFly_BSD[DragonFly BSD] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__DragonFly__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_OS_BSD_DRAGONFLY BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(__DragonFly__) \ + ) +# ifndef BOOST_OS_BSD_AVAILABLE +# undef BOOST_OS_BSD +# define BOOST_OS_BSD BOOST_VERSION_NUMBER_AVAILABLE +# define BOOST_OS_BSD_AVAILABLE +# endif +# undef BOOST_OS_BSD_DRAGONFLY +# if defined(__DragonFly__) +# define BOOST_OS_DRAGONFLY_BSD BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_OS_BSD_DRAGONFLY +# define BOOST_OS_BSD_DRAGONFLY_AVAILABLE +# include +#endif + +#define BOOST_OS_BSD_DRAGONFLY_NAME "DragonFly BSD" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BSD_DRAGONFLY,BOOST_OS_BSD_DRAGONFLY_NAME) diff --git a/boost/predef/os/bsd/free.h b/boost/predef/os/bsd/free.h new file mode 100644 index 00000000..4098b3a3 --- /dev/null +++ b/boost/predef/os/bsd/free.h @@ -0,0 +1,69 @@ +/* +Copyright Rene Rivera 2012-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_BSD_FREE_H +#define BOOST_PREDEF_OS_BSD_FREE_H + +#include + +/* tag::reference[] += `BOOST_OS_BSD_FREE` + +http://en.wikipedia.org/wiki/Freebsd[FreeBSD] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__FreeBSD__+` | {predef_detection} + +| `+__FreeBSD_version+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_OS_BSD_FREE BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(__FreeBSD__) \ + ) +# ifndef BOOST_OS_BSD_AVAILABLE +# undef BOOST_OS_BSD +# define BOOST_OS_BSD BOOST_VERSION_NUMBER_AVAILABLE +# define BOOST_OS_BSD_AVAILABLE +# endif +# undef BOOST_OS_BSD_FREE +# include +# if defined(__FreeBSD_version) +# if __FreeBSD_version == 491000 +# define BOOST_OS_BSD_FREE \ + BOOST_VERSION_NUMBER(4, 10, 0) +# elif __FreeBSD_version == 492000 +# define BOOST_OS_BSD_FREE \ + BOOST_VERSION_NUMBER(4, 11, 0) +# elif __FreeBSD_version < 500000 +# define BOOST_OS_BSD_FREE \ + BOOST_PREDEF_MAKE_10_VRPPPP(__FreeBSD_version) +# else +# define BOOST_OS_BSD_FREE \ + BOOST_PREDEF_MAKE_10_VVRRPPP(__FreeBSD_version) +# endif +# else +# define BOOST_OS_BSD_FREE BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_OS_BSD_FREE +# define BOOST_OS_BSD_FREE_AVAILABLE +# include +#endif + +#define BOOST_OS_BSD_FREE_NAME "Free BSD" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BSD_FREE,BOOST_OS_BSD_FREE_NAME) diff --git a/boost/predef/os/bsd/net.h b/boost/predef/os/bsd/net.h new file mode 100644 index 00000000..537f16a1 --- /dev/null +++ b/boost/predef/os/bsd/net.h @@ -0,0 +1,86 @@ +/* +Copyright Rene Rivera 2012-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_BSD_NET_H +#define BOOST_PREDEF_OS_BSD_NET_H + +#include + +/* tag::reference[] += `BOOST_OS_BSD_NET` + +http://en.wikipedia.org/wiki/Netbsd[NetBSD] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__NETBSD__+` | {predef_detection} +| `+__NetBSD__+` | {predef_detection} + +| `+__NETBSD_version+` | V.R.P +| `NetBSD0_8` | 0.8.0 +| `NetBSD0_9` | 0.9.0 +| `NetBSD1_0` | 1.0.0 +| `+__NetBSD_Version+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_OS_BSD_NET BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(__NETBSD__) || defined(__NetBSD__) \ + ) +# ifndef BOOST_OS_BSD_AVAILABLE +# undef BOOST_OS_BSD +# define BOOST_OS_BSD BOOST_VERSION_NUMBER_AVAILABLE +# define BOOST_OS_BSD_AVAILABLE +# endif +# undef BOOST_OS_BSD_NET +# if defined(__NETBSD__) +# if defined(__NETBSD_version) +# if __NETBSD_version < 500000 +# define BOOST_OS_BSD_NET \ + BOOST_PREDEF_MAKE_10_VRP000(__NETBSD_version) +# else +# define BOOST_OS_BSD_NET \ + BOOST_PREDEF_MAKE_10_VRR000(__NETBSD_version) +# endif +# else +# define BOOST_OS_BSD_NET BOOST_VERSION_NUMBER_AVAILABLE +# endif +# elif defined(__NetBSD__) +# if !defined(BOOST_OS_BSD_NET) && defined(NetBSD0_8) +# define BOOST_OS_BSD_NET BOOST_VERSION_NUMBER(0,8,0) +# endif +# if !defined(BOOST_OS_BSD_NET) && defined(NetBSD0_9) +# define BOOST_OS_BSD_NET BOOST_VERSION_NUMBER(0,9,0) +# endif +# if !defined(BOOST_OS_BSD_NET) && defined(NetBSD1_0) +# define BOOST_OS_BSD_NET BOOST_VERSION_NUMBER(1,0,0) +# endif +# if !defined(BOOST_OS_BSD_NET) && defined(__NetBSD_Version) +# define BOOST_OS_BSD_NET \ + BOOST_PREDEF_MAKE_10_VVRR00PP00(__NetBSD_Version) +# endif +# if !defined(BOOST_OS_BSD_NET) +# define BOOST_OS_BSD_NET BOOST_VERSION_NUMBER_AVAILABLE +# endif +# endif +#endif + +#if BOOST_OS_BSD_NET +# define BOOST_OS_BSD_NET_AVAILABLE +# include +#endif + +#define BOOST_OS_BSD_NET_NAME "NetBSD" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BSD_NET,BOOST_OS_BSD_NET_NAME) diff --git a/boost/predef/os/bsd/open.h b/boost/predef/os/bsd/open.h new file mode 100644 index 00000000..34f0a71a --- /dev/null +++ b/boost/predef/os/bsd/open.h @@ -0,0 +1,253 @@ +/* +Copyright Rene Rivera 2012-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_BSD_OPEN_H +#define BOOST_PREDEF_OS_BSD_OPEN_H + +#include + +/* tag::reference[] += `BOOST_OS_BSD_OPEN` + +http://en.wikipedia.org/wiki/Openbsd[OpenBSD] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__OpenBSD__+` | {predef_detection} + +| `OpenBSD2_0` | 2.0.0 +| `OpenBSD2_1` | 2.1.0 +| `OpenBSD2_2` | 2.2.0 +| `OpenBSD2_3` | 2.3.0 +| `OpenBSD2_4` | 2.4.0 +| `OpenBSD2_5` | 2.5.0 +| `OpenBSD2_6` | 2.6.0 +| `OpenBSD2_7` | 2.7.0 +| `OpenBSD2_8` | 2.8.0 +| `OpenBSD2_9` | 2.9.0 +| `OpenBSD3_0` | 3.0.0 +| `OpenBSD3_1` | 3.1.0 +| `OpenBSD3_2` | 3.2.0 +| `OpenBSD3_3` | 3.3.0 +| `OpenBSD3_4` | 3.4.0 +| `OpenBSD3_5` | 3.5.0 +| `OpenBSD3_6` | 3.6.0 +| `OpenBSD3_7` | 3.7.0 +| `OpenBSD3_8` | 3.8.0 +| `OpenBSD3_9` | 3.9.0 +| `OpenBSD4_0` | 4.0.0 +| `OpenBSD4_1` | 4.1.0 +| `OpenBSD4_2` | 4.2.0 +| `OpenBSD4_3` | 4.3.0 +| `OpenBSD4_4` | 4.4.0 +| `OpenBSD4_5` | 4.5.0 +| `OpenBSD4_6` | 4.6.0 +| `OpenBSD4_7` | 4.7.0 +| `OpenBSD4_8` | 4.8.0 +| `OpenBSD4_9` | 4.9.0 +| `OpenBSD5_0` | 5.0.0 +| `OpenBSD5_1` | 5.1.0 +| `OpenBSD5_2` | 5.2.0 +| `OpenBSD5_3` | 5.3.0 +| `OpenBSD5_4` | 5.4.0 +| `OpenBSD5_5` | 5.5.0 +| `OpenBSD5_6` | 5.6.0 +| `OpenBSD5_7` | 5.7.0 +| `OpenBSD5_8` | 5.8.0 +| `OpenBSD5_9` | 5.9.0 +| `OpenBSD6_0` | 6.0.0 +| `OpenBSD6_1` | 6.1.0 +| `OpenBSD6_2` | 6.2.0 +| `OpenBSD6_3` | 6.3.0 +| `OpenBSD6_4` | 6.4.0 +| `OpenBSD6_5` | 6.5.0 +| `OpenBSD6_6` | 6.6.0 +| `OpenBSD6_7` | 6.7.0 +| `OpenBSD6_8` | 6.8.0 +| `OpenBSD6_9` | 6.9.0 +|=== +*/ // end::reference[] + +#define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(__OpenBSD__) \ + ) +# ifndef BOOST_OS_BSD_AVAILABLE +# undef BOOST_OS_BSD +# define BOOST_OS_BSD BOOST_VERSION_NUMBER_AVAILABLE +# define BOOST_OS_BSD_AVAILABLE +# endif +# undef BOOST_OS_BSD_OPEN +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_0) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,0,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_1) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,1,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_2) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,2,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_3) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,3,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_4) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,4,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_5) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,5,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_6) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,6,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_7) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,7,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_8) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,8,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_9) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,9,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_0) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,0,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_1) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,1,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_2) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,2,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_3) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,3,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_4) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,4,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_5) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,5,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_6) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,6,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_7) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,7,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_8) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,8,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_9) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,9,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_0) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,0,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_1) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,1,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_2) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,2,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_3) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,3,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_4) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,4,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_5) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,5,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_6) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,6,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_7) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,7,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_8) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,8,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_9) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,9,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD5_0) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(5,0,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD5_1) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(5,1,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD5_2) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(5,2,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD5_3) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(5,3,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD5_4) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(5,4,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD5_5) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(5,5,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD5_6) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(5,6,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD5_7) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(5,7,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD5_8) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(5,8,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD5_9) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(5,9,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD6_0) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(6,0,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD6_1) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(6,1,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD6_2) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(6,2,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD6_3) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(6,3,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD6_4) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(6,4,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD6_5) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(6,5,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD6_6) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(6,6,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD6_7) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(6,7,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD6_8) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(6,8,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD6_9) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(6,9,0) +# endif +# if !defined(BOOST_OS_BSD_OPEN) +# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_OS_BSD_OPEN +# define BOOST_OS_BSD_OPEN_AVAILABLE +# include +#endif + +#define BOOST_OS_BSD_OPEN_NAME "OpenBSD" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BSD_OPEN,BOOST_OS_BSD_OPEN_NAME) diff --git a/boost/predef/os/cygwin.h b/boost/predef/os/cygwin.h new file mode 100644 index 00000000..3ca73d26 --- /dev/null +++ b/boost/predef/os/cygwin.h @@ -0,0 +1,51 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_CYGWIN_H +#define BOOST_PREDEF_OS_CYGWIN_H + +#include +#include + +/* tag::reference[] += `BOOST_OS_CYGWIN` + +http://en.wikipedia.org/wiki/Cygwin[Cygwin] evironment. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__CYGWIN__+` | {predef_detection} + +| `CYGWIN_VERSION_API_MAJOR`, `CYGWIN_VERSION_API_MINOR` | V.R.0 +|=== +*/ // end::reference[] + +#define BOOST_OS_CYGWIN BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(__CYGWIN__) \ + ) +# include +# undef BOOST_OS_CYGWIN +# define BOOST_OS_CYGWIN \ + BOOST_VERSION_NUMBER(CYGWIN_VERSION_API_MAJOR,\ + CYGWIN_VERSION_API_MINOR, 0) +#endif + +#if BOOST_OS_CYGWIN +# define BOOST_OS_CYGWIN_AVAILABLE +# include +#endif + +#define BOOST_OS_CYGWIN_NAME "Cygwin" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_CYGWIN,BOOST_OS_CYGWIN_NAME) diff --git a/boost/predef/os/haiku.h b/boost/predef/os/haiku.h new file mode 100644 index 00000000..4ae31583 --- /dev/null +++ b/boost/predef/os/haiku.h @@ -0,0 +1,47 @@ +/* +Copyright Jessica Hamilton 2014 +Copyright Rene Rivera 2014-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_HAIKU_H +#define BOOST_PREDEF_OS_HAIKU_H + +#include +#include + +/* tag::reference[] += `BOOST_OS_HAIKU` + +http://en.wikipedia.org/wiki/Haiku_(operating_system)[Haiku] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__HAIKU__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_OS_HAIKU BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(__HAIKU__) \ + ) +# undef BOOST_OS_HAIKU +# define BOOST_OS_HAIKU BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_OS_HAIKU +# define BOOST_OS_HAIKU_AVAILABLE +# include +#endif + +#define BOOST_OS_HAIKU_NAME "Haiku" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_HAIKU,BOOST_OS_HAIKU_NAME) diff --git a/boost/predef/os/hpux.h b/boost/predef/os/hpux.h new file mode 100644 index 00000000..79019148 --- /dev/null +++ b/boost/predef/os/hpux.h @@ -0,0 +1,48 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_HPUX_H +#define BOOST_PREDEF_OS_HPUX_H + +#include +#include + +/* tag::reference[] += `BOOST_OS_HPUX` + +http://en.wikipedia.org/wiki/HP-UX[HP-UX] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `hpux` | {predef_detection} +| `+_hpux+` | {predef_detection} +| `+__hpux+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_OS_HPUX BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(hpux) || defined(_hpux) || defined(__hpux) \ + ) +# undef BOOST_OS_HPUX +# define BOOST_OS_HPUX BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_OS_HPUX +# define BOOST_OS_HPUX_AVAILABLE +# include +#endif + +#define BOOST_OS_HPUX_NAME "HP-UX" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_HPUX,BOOST_OS_HPUX_NAME) diff --git a/boost/predef/os/irix.h b/boost/predef/os/irix.h new file mode 100644 index 00000000..7c0bab04 --- /dev/null +++ b/boost/predef/os/irix.h @@ -0,0 +1,47 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_IRIX_H +#define BOOST_PREDEF_OS_IRIX_H + +#include +#include + +/* tag::reference[] += `BOOST_OS_IRIX` + +http://en.wikipedia.org/wiki/Irix[IRIX] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `sgi` | {predef_detection} +| `+__sgi+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_OS_IRIX BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(sgi) || defined(__sgi) \ + ) +# undef BOOST_OS_IRIX +# define BOOST_OS_IRIX BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_OS_IRIX +# define BOOST_OS_IRIX_AVAILABLE +# include +#endif + +#define BOOST_OS_IRIX_NAME "IRIX" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_IRIX,BOOST_OS_IRIX_NAME) diff --git a/boost/predef/os/linux.h b/boost/predef/os/linux.h new file mode 100644 index 00000000..bab64fc4 --- /dev/null +++ b/boost/predef/os/linux.h @@ -0,0 +1,50 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_LINUX_H +#define BOOST_PREDEF_OS_LINUX_H + +#include +#include + +/* tag::reference[] += `BOOST_OS_LINUX` + +http://en.wikipedia.org/wiki/Linux[Linux] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `linux` | {predef_detection} +| `+__linux+` | {predef_detection} +| `+__linux__+` | {predef_detection} +| `+__gnu_linux__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_OS_LINUX BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(linux) || defined(__linux) || \ + defined(__linux__) || defined(__gnu_linux__) \ + ) +# undef BOOST_OS_LINUX +# define BOOST_OS_LINUX BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_OS_LINUX +# define BOOST_OS_LINUX_AVAILABLE +# include +#endif + +#define BOOST_OS_LINUX_NAME "Linux" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_LINUX,BOOST_OS_LINUX_NAME) diff --git a/boost/predef/os/macos.h b/boost/predef/os/macos.h new file mode 100644 index 00000000..1a443184 --- /dev/null +++ b/boost/predef/os/macos.h @@ -0,0 +1,66 @@ +/* +Copyright Rene Rivera 2008-2015 +Copyright Franz Detro 2014 +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) +*/ + +#ifndef BOOST_PREDEF_OS_MACOS_H +#define BOOST_PREDEF_OS_MACOS_H + +/* Special case: iOS will define the same predefs as MacOS, and additionally + '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__'. We can guard against that, + but only if we detect iOS first. Hence we will force include iOS detection + * before doing any MacOS detection. + */ +#include + +#include +#include + +/* tag::reference[] += `BOOST_OS_MACOS` + +http://en.wikipedia.org/wiki/Mac_OS[Mac OS] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `macintosh` | {predef_detection} +| `Macintosh` | {predef_detection} +| `+__APPLE__+` | {predef_detection} +| `+__MACH__+` | {predef_detection} + +| `+__APPLE__+`, `+__MACH__+` | 10.0.0 +| `_otherwise_` | 9.0.0 +|=== +*/ // end::reference[] + +#define BOOST_OS_MACOS BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(macintosh) || defined(Macintosh) || \ + (defined(__APPLE__) && defined(__MACH__)) \ + ) +# undef BOOST_OS_MACOS +# if !defined(BOOST_OS_MACOS) && defined(__APPLE__) && defined(__MACH__) +# define BOOST_OS_MACOS BOOST_VERSION_NUMBER(10,0,0) +# endif +# if !defined(BOOST_OS_MACOS) +# define BOOST_OS_MACOS BOOST_VERSION_NUMBER(9,0,0) +# endif +#endif + +#if BOOST_OS_MACOS +# define BOOST_OS_MACOS_AVAILABLE +# include +#endif + +#define BOOST_OS_MACOS_NAME "Mac OS" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_MACOS,BOOST_OS_MACOS_NAME) diff --git a/boost/predef/os/os400.h b/boost/predef/os/os400.h new file mode 100644 index 00000000..209638d1 --- /dev/null +++ b/boost/predef/os/os400.h @@ -0,0 +1,46 @@ +/* +Copyright Rene Rivera 2011-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_OS400_H +#define BOOST_PREDEF_OS_OS400_H + +#include +#include + +/* tag::reference[] += `BOOST_OS_OS400` + +http://en.wikipedia.org/wiki/IBM_i[IBM OS/400] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__OS400__+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_OS_OS400 BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(__OS400__) \ + ) +# undef BOOST_OS_OS400 +# define BOOST_OS_OS400 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_OS_OS400 +# define BOOST_OS_OS400_AVAILABLE +# include +#endif + +#define BOOST_OS_OS400_NAME "IBM OS/400" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_OS400,BOOST_OS_OS400_NAME) diff --git a/boost/predef/os/qnxnto.h b/boost/predef/os/qnxnto.h new file mode 100644 index 00000000..7507cd08 --- /dev/null +++ b/boost/predef/os/qnxnto.h @@ -0,0 +1,60 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_QNXNTO_H +#define BOOST_PREDEF_OS_QNXNTO_H + +#include +#include + +/* tag::reference[] += `BOOST_OS_QNX` + +http://en.wikipedia.org/wiki/QNX[QNX] operating system. +Version number available as major, and minor if possible. And +version 4 is specifically detected. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__QNX__+` | {predef_detection} +| `+__QNXNTO__+` | {predef_detection} + +| `+_NTO_VERSION+` | V.R.0 +| `+__QNX__+` | 4.0.0 +|=== +*/ // end::reference[] + +#define BOOST_OS_QNX BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(__QNX__) || defined(__QNXNTO__) \ + ) +# undef BOOST_OS_QNX +# if !defined(BOOST_OS_QNX) && defined(_NTO_VERSION) +# define BOOST_OS_QNX BOOST_PREDEF_MAKE_10_VVRR(_NTO_VERSION) +# endif +# if !defined(BOOST_OS_QNX) && defined(__QNX__) +# define BOOST_OS_QNX BOOST_VERSION_NUMBER(4,0,0) +# endif +# if !defined(BOOST_OS_QNX) +# define BOOST_OS_QNX BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_OS_QNX +# define BOOST_OS_QNX_AVAILABLE +# include +#endif + +#define BOOST_OS_QNX_NAME "QNX" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_QNX,BOOST_OS_QNX_NAME) diff --git a/boost/predef/os/solaris.h b/boost/predef/os/solaris.h new file mode 100644 index 00000000..529af2b3 --- /dev/null +++ b/boost/predef/os/solaris.h @@ -0,0 +1,47 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_SOLARIS_H +#define BOOST_PREDEF_OS_SOLARIS_H + +#include +#include + +/* tag::reference[] += `BOOST_OS_SOLARIS` + +http://en.wikipedia.org/wiki/Solaris_Operating_Environment[Solaris] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `sun` | {predef_detection} +| `+__sun+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_OS_SOLARIS BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(sun) || defined(__sun) \ + ) +# undef BOOST_OS_SOLARIS +# define BOOST_OS_SOLARIS BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_OS_SOLARIS +# define BOOST_OS_SOLARIS_AVAILABLE +# include +#endif + +#define BOOST_OS_SOLARIS_NAME "Solaris" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_SOLARIS,BOOST_OS_SOLARIS_NAME) diff --git a/boost/predef/os/unix.h b/boost/predef/os/unix.h new file mode 100644 index 00000000..b86051dd --- /dev/null +++ b/boost/predef/os/unix.h @@ -0,0 +1,78 @@ +/* +Copyright Rene Rivera 2008-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_UNIX_H +#define BOOST_PREDEF_OS_UNIX_H + +#include +#include + +/* tag::reference[] += `BOOST_OS_UNIX` + +http://en.wikipedia.org/wiki/Unix[Unix Environment] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `unix` | {predef_detection} +| `+__unix+` | {predef_detection} +| `+_XOPEN_SOURCE+` | {predef_detection} +| `+_POSIX_SOURCE+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_OS_UNIX BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(unix) || defined(__unix) || \ + defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) +# undef BOOST_OS_UNIX +# define BOOST_OS_UNIX BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_OS_UNIX +# define BOOST_OS_UNIX_AVAILABLE +#endif + +#define BOOST_OS_UNIX_NAME "Unix Environment" + +/* tag::reference[] += `BOOST_OS_SVR4` + +http://en.wikipedia.org/wiki/UNIX_System_V[SVR4 Environment] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `+__sysv__+` | {predef_detection} +| `+__SVR4+` | {predef_detection} +| `+__svr4__+` | {predef_detection} +| `+_SYSTYPE_SVR4+` | {predef_detection} +|=== +*/ // end::reference[] + +#define BOOST_OS_SVR4 BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if defined(__sysv__) || defined(__SVR4) || \ + defined(__svr4__) || defined(_SYSTYPE_SVR4) +# undef BOOST_OS_SVR4 +# define BOOST_OS_SVR4 BOOST_VERSION_NUMBER_AVAILABLE +#endif + +#if BOOST_OS_SVR4 +# define BOOST_OS_SVR4_AVAILABLE +#endif + +#define BOOST_OS_SVR4_NAME "SVR4 Environment" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_UNIX,BOOST_OS_UNIX_NAME) +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_SVR4,BOOST_OS_SVR4_NAME) diff --git a/boost/predef/os/vms.h b/boost/predef/os/vms.h new file mode 100644 index 00000000..452e21d5 --- /dev/null +++ b/boost/predef/os/vms.h @@ -0,0 +1,53 @@ +/* +Copyright Rene Rivera 2011-2015 +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) +*/ + +#ifndef BOOST_PREDEF_OS_VMS_H +#define BOOST_PREDEF_OS_VMS_H + +#include +#include + +/* tag::reference[] += `BOOST_OS_VMS` + +http://en.wikipedia.org/wiki/OpenVMS[VMS] operating system. + +[options="header"] +|=== +| {predef_symbol} | {predef_version} + +| `VMS` | {predef_detection} +| `+__VMS+` | {predef_detection} + +| `+__VMS_VER+` | V.R.P +|=== +*/ // end::reference[] + +#define BOOST_OS_VMS BOOST_VERSION_NUMBER_NOT_AVAILABLE + +#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \ + defined(VMS) || defined(__VMS) \ + ) +# undef BOOST_OS_VMS +# if defined(__VMS_VER) +# define BOOST_OS_VMS BOOST_PREDEF_MAKE_10_VVRR00PP00(__VMS_VER) +# else +# define BOOST_OS_VMS BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +#if BOOST_OS_VMS +# define BOOST_OS_VMS_AVAILABLE +# include +#endif + +#define BOOST_OS_VMS_NAME "VMS" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_OS_VMS,BOOST_OS_VMS_NAME) diff --git a/boost/predef/other.h b/boost/predef/other.h new file mode 100644 index 00000000..dc7e341e --- /dev/null +++ b/boost/predef/other.h @@ -0,0 +1,17 @@ +/* +Copyright Rene Ferdinand Rivera Morell 2013-2020 +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) +*/ + +#if !defined(BOOST_PREDEF_OTHER_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS) +#ifndef BOOST_PREDEF_OTHER_H +#define BOOST_PREDEF_OTHER_H +#endif + +#include +#include +#include + +#endif diff --git a/boost/predef/other/endian.h b/boost/predef/other/endian.h new file mode 100644 index 00000000..435492a0 --- /dev/null +++ b/boost/predef/other/endian.h @@ -0,0 +1,202 @@ +/* +Copyright Rene Rivera 2013-2015 +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) +*/ + +#ifndef BOOST_PREDEF_ENDIAN_H +#define BOOST_PREDEF_ENDIAN_H + +#include +#include +#include +#include +#include +#include + +/* tag::reference[] += `BOOST_ENDIAN_*` + +Detection of endian memory ordering. There are four defined macros +in this header that define the various generally possible endian +memory orderings: + +* `BOOST_ENDIAN_BIG_BYTE`, byte-swapped big-endian. +* `BOOST_ENDIAN_BIG_WORD`, word-swapped big-endian. +* `BOOST_ENDIAN_LITTLE_BYTE`, byte-swapped little-endian. +* `BOOST_ENDIAN_LITTLE_WORD`, word-swapped little-endian. + +The detection is conservative in that it only identifies endianness +that it knows for certain. In particular bi-endianness is not +indicated as is it not practically possible to determine the +endianness from anything but an operating system provided +header. And the currently known headers do not define that +programatic bi-endianness is available. + +This implementation is a compilation of various publicly available +information and acquired knowledge: + +. The indispensable documentation of "Pre-defined Compiler Macros" + http://sourceforge.net/p/predef/wiki/Endianness[Endianness]. +. The various endian specifications available in the + http://wikipedia.org/[Wikipedia] computer architecture pages. +. Generally available searches for headers that define endianness. +*/ // end::reference[] + +#define BOOST_ENDIAN_BIG_BYTE BOOST_VERSION_NUMBER_NOT_AVAILABLE +#define BOOST_ENDIAN_BIG_WORD BOOST_VERSION_NUMBER_NOT_AVAILABLE +#define BOOST_ENDIAN_LITTLE_BYTE BOOST_VERSION_NUMBER_NOT_AVAILABLE +#define BOOST_ENDIAN_LITTLE_WORD BOOST_VERSION_NUMBER_NOT_AVAILABLE + +/* GNU libc provides a header defining __BYTE_ORDER, or _BYTE_ORDER. + * And some OSs provide some for of endian header also. + */ +#if !BOOST_ENDIAN_BIG_BYTE && !BOOST_ENDIAN_BIG_WORD && \ + !BOOST_ENDIAN_LITTLE_BYTE && !BOOST_ENDIAN_LITTLE_WORD +# if BOOST_LIB_C_GNU || BOOST_PLAT_ANDROID || BOOST_OS_BSD_OPEN +# include +# else +# if BOOST_OS_MACOS +# include +# else +# if BOOST_OS_BSD +# include +# endif +# endif +# endif +# if defined(__BYTE_ORDER) +# if defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) +# undef BOOST_ENDIAN_BIG_BYTE +# define BOOST_ENDIAN_BIG_BYTE BOOST_VERSION_NUMBER_AVAILABLE +# endif +# if defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) +# undef BOOST_ENDIAN_LITTLE_BYTE +# define BOOST_ENDIAN_LITTLE_BYTE BOOST_VERSION_NUMBER_AVAILABLE +# endif +# if defined(__PDP_ENDIAN) && (__BYTE_ORDER == __PDP_ENDIAN) +# undef BOOST_ENDIAN_LITTLE_WORD +# define BOOST_ENDIAN_LITTLE_WORD BOOST_VERSION_NUMBER_AVAILABLE +# endif +# endif +# if !defined(__BYTE_ORDER) && defined(_BYTE_ORDER) +# if defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN) +# undef BOOST_ENDIAN_BIG_BYTE +# define BOOST_ENDIAN_BIG_BYTE BOOST_VERSION_NUMBER_AVAILABLE +# endif +# if defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN) +# undef BOOST_ENDIAN_LITTLE_BYTE +# define BOOST_ENDIAN_LITTLE_BYTE BOOST_VERSION_NUMBER_AVAILABLE +# endif +# if defined(_PDP_ENDIAN) && (_BYTE_ORDER == _PDP_ENDIAN) +# undef BOOST_ENDIAN_LITTLE_WORD +# define BOOST_ENDIAN_LITTLE_WORD BOOST_VERSION_NUMBER_AVAILABLE +# endif +# endif +#endif + +/* Built-in byte-swapped big-endian macros. + */ +#if !BOOST_ENDIAN_BIG_BYTE && !BOOST_ENDIAN_BIG_WORD && \ + !BOOST_ENDIAN_LITTLE_BYTE && !BOOST_ENDIAN_LITTLE_WORD +# if (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) || \ + (defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || \ + defined(__ARMEB__) || \ + defined(__THUMBEB__) || \ + defined(__AARCH64EB__) || \ + defined(_MIPSEB) || \ + defined(__MIPSEB) || \ + defined(__MIPSEB__) +# undef BOOST_ENDIAN_BIG_BYTE +# define BOOST_ENDIAN_BIG_BYTE BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +/* Built-in byte-swapped little-endian macros. + */ +#if !BOOST_ENDIAN_BIG_BYTE && !BOOST_ENDIAN_BIG_WORD && \ + !BOOST_ENDIAN_LITTLE_BYTE && !BOOST_ENDIAN_LITTLE_WORD +# if (defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ + (defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \ + defined(__ARMEL__) || \ + defined(__THUMBEL__) || \ + defined(__AARCH64EL__) || \ + defined(__loongarch__) || \ + defined(_MIPSEL) || \ + defined(__MIPSEL) || \ + defined(__MIPSEL__) || \ + defined(__riscv) || \ + defined(__e2k__) +# undef BOOST_ENDIAN_LITTLE_BYTE +# define BOOST_ENDIAN_LITTLE_BYTE BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +/* Some architectures are strictly one endianess (as opposed + * the current common bi-endianess). + */ +#if !BOOST_ENDIAN_BIG_BYTE && !BOOST_ENDIAN_BIG_WORD && \ + !BOOST_ENDIAN_LITTLE_BYTE && !BOOST_ENDIAN_LITTLE_WORD +# include +# if BOOST_ARCH_M68K || \ + BOOST_ARCH_PARISC || \ + BOOST_ARCH_SPARC || \ + BOOST_ARCH_SYS370 || \ + BOOST_ARCH_SYS390 || \ + BOOST_ARCH_Z +# undef BOOST_ENDIAN_BIG_BYTE +# define BOOST_ENDIAN_BIG_BYTE BOOST_VERSION_NUMBER_AVAILABLE +# endif +# if BOOST_ARCH_IA64 || \ + BOOST_ARCH_X86 || \ + BOOST_ARCH_BLACKFIN +# undef BOOST_ENDIAN_LITTLE_BYTE +# define BOOST_ENDIAN_LITTLE_BYTE BOOST_VERSION_NUMBER_AVAILABLE +# endif +#endif + +/* Windows on ARM, if not otherwise detected/specified, is always + * byte-swapped little-endian. + */ +#if !BOOST_ENDIAN_BIG_BYTE && !BOOST_ENDIAN_BIG_WORD && \ + !BOOST_ENDIAN_LITTLE_BYTE && !BOOST_ENDIAN_LITTLE_WORD +# if BOOST_ARCH_ARM +# include +# if BOOST_OS_WINDOWS +# undef BOOST_ENDIAN_LITTLE_BYTE +# define BOOST_ENDIAN_LITTLE_BYTE BOOST_VERSION_NUMBER_AVAILABLE +# endif +# endif +#endif + +#if BOOST_ENDIAN_BIG_BYTE +# define BOOST_ENDIAN_BIG_BYTE_AVAILABLE +#endif +#if BOOST_ENDIAN_BIG_WORD +# define BOOST_ENDIAN_BIG_WORD_BYTE_AVAILABLE +#endif +#if BOOST_ENDIAN_LITTLE_BYTE +# define BOOST_ENDIAN_LITTLE_BYTE_AVAILABLE +#endif +#if BOOST_ENDIAN_LITTLE_WORD +# define BOOST_ENDIAN_LITTLE_WORD_BYTE_AVAILABLE +#endif + +#define BOOST_ENDIAN_BIG_BYTE_NAME "Byte-Swapped Big-Endian" +#define BOOST_ENDIAN_BIG_WORD_NAME "Word-Swapped Big-Endian" +#define BOOST_ENDIAN_LITTLE_BYTE_NAME "Byte-Swapped Little-Endian" +#define BOOST_ENDIAN_LITTLE_WORD_NAME "Word-Swapped Little-Endian" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ENDIAN_BIG_BYTE,BOOST_ENDIAN_BIG_BYTE_NAME) + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ENDIAN_BIG_WORD,BOOST_ENDIAN_BIG_WORD_NAME) + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ENDIAN_LITTLE_BYTE,BOOST_ENDIAN_LITTLE_BYTE_NAME) + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ENDIAN_LITTLE_WORD,BOOST_ENDIAN_LITTLE_WORD_NAME) diff --git a/boost/predef/other/wordsize.h b/boost/predef/other/wordsize.h new file mode 100644 index 00000000..ce3016fe --- /dev/null +++ b/boost/predef/other/wordsize.h @@ -0,0 +1,73 @@ +/* +Copyright Rene Ferdinand Rivera Morell 2020-2021 +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) +*/ + +#ifndef BOOST_PREDEF_OTHER_WORD_SIZE_H +#define BOOST_PREDEF_OTHER_WORD_SIZE_H + +#include +#include +#include + +/* tag::reference[] += `BOOST_ARCH_WORD_BITS` + +Detects the native word size, in bits, for the current architecture. There are +two types of macros for this detection: + +* `BOOST_ARCH_WORD_BITS`, gives the number of word size bits + (16, 32, 64). +* `BOOST_ARCH_WORD_BITS_16`, `BOOST_ARCH_WORD_BITS_32`, and + `BOOST_ARCH_WORD_BITS_64`, indicate when the given word size is + detected. + +They allow for both single checks and direct use of the size in code. + +NOTE: The word size is determined manually on each architecture. Hence use of +the `wordsize.h` header will also include all the architecture headers. + +*/ // end::reference[] + +#if !defined(BOOST_ARCH_WORD_BITS_64) +# define BOOST_ARCH_WORD_BITS_64 BOOST_VERSION_NUMBER_NOT_AVAILABLE +#elif !defined(BOOST_ARCH_WORD_BITS) +# define BOOST_ARCH_WORD_BITS 64 +#endif + +#if !defined(BOOST_ARCH_WORD_BITS_32) +# define BOOST_ARCH_WORD_BITS_32 BOOST_VERSION_NUMBER_NOT_AVAILABLE +#elif !defined(BOOST_ARCH_WORD_BITS) +# define BOOST_ARCH_WORD_BITS 32 +#endif + +#if !defined(BOOST_ARCH_WORD_BITS_16) +# define BOOST_ARCH_WORD_BITS_16 BOOST_VERSION_NUMBER_NOT_AVAILABLE +#elif !defined(BOOST_ARCH_WORD_BITS) +# define BOOST_ARCH_WORD_BITS 16 +#endif + +#if !defined(BOOST_ARCH_WORD_BITS) +# define BOOST_ARCH_WORD_BITS 0 +#endif + +#define BOOST_ARCH_WORD_BITS_NAME "Word Bits" +#define BOOST_ARCH_WORD_BITS_16_NAME "16-bit Word Size" +#define BOOST_ARCH_WORD_BITS_32_NAME "32-bit Word Size" +#define BOOST_ARCH_WORD_BITS_64_NAME "64-bit Word Size" + +#endif + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_WORD_BITS,BOOST_ARCH_WORD_BITS_NAME) + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_WORD_BITS_16,BOOST_ARCH_WORD_BITS_16_NAME) + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_WORD_BITS_32,BOOST_ARCH_WORD_BITS_32_NAME) + +#include +BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_WORD_BITS_64,BOOST_ARCH_WORD_BITS_64_NAME) diff --git a/boost/predef/other/workaround.h b/boost/predef/other/workaround.h new file mode 100644 index 00000000..21f04d3f --- /dev/null +++ b/boost/predef/other/workaround.h @@ -0,0 +1,95 @@ +/* +Copyright Rene Rivera 2017 +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) +*/ + +#ifndef BOOST_PREDEF_WORKAROUND_H +#define BOOST_PREDEF_WORKAROUND_H + +/* tag::reference[] + += `BOOST_PREDEF_WORKAROUND` + +[source] +---- +BOOST_PREDEF_WORKAROUND(symbol,comp,major,minor,patch) +---- + +Usage: + +[source] +---- +#if BOOST_PREDEF_WORKAROUND(BOOST_COMP_CLANG,<,3,0,0) + // Workaround for old clang compilers.. +#endif +---- + +Defines a comparison against two version numbers that depends on the definion +of `BOOST_STRICT_CONFIG`. When `BOOST_STRICT_CONFIG` is defined this will expand +to a value convertible to `false`. Which has the effect of disabling all code +conditionally guarded by `BOOST_PREDEF_WORKAROUND`. When `BOOST_STRICT_CONFIG` +is undefine this expand to test the given `symbol` version value with the +`comp` comparison against `BOOST_VERSION_NUMBER(major,minor,patch)`. + +*/ // end::reference[] +#ifdef BOOST_STRICT_CONFIG +# define BOOST_PREDEF_WORKAROUND(symbol, comp, major, minor, patch) (0) +#else +# include +# define BOOST_PREDEF_WORKAROUND(symbol, comp, major, minor, patch) \ + ( (symbol) != (0) ) && \ + ( (symbol) comp (BOOST_VERSION_NUMBER( (major) , (minor) , (patch) )) ) +#endif + +/* tag::reference[] + += `BOOST_PREDEF_TESTED_AT` + +[source] +---- +BOOST_PREDEF_TESTED_AT(symbol,major,minor,patch) +---- + +Usage: + +[source] +---- +#if BOOST_PREDEF_TESTED_AT(BOOST_COMP_CLANG,3,5,0) + // Needed for clang, and last checked for 3.5.0. +#endif +---- + +Defines a comparison against two version numbers that depends on the definion +of `BOOST_STRICT_CONFIG` and `BOOST_DETECT_OUTDATED_WORKAROUNDS`. +When `BOOST_STRICT_CONFIG` is defined this will expand to a value convertible +to `false`. Which has the effect of disabling all code +conditionally guarded by `BOOST_PREDEF_TESTED_AT`. When `BOOST_STRICT_CONFIG` +is undefined this expand to either: + +* A value convertible to `true` when `BOOST_DETECT_OUTDATED_WORKAROUNDS` is not + defined. +* A value convertible `true` when the expansion of + `BOOST_PREDEF_WORKAROUND(symbol, <=, major, minor, patch)` is `true` and + `BOOST_DETECT_OUTDATED_WORKAROUNDS` is defined. +* A compile error when the expansion of + `BOOST_PREDEF_WORKAROUND(symbol, >, major, minor, patch)` is true and + `BOOST_DETECT_OUTDATED_WORKAROUNDS` is defined. + +*/ // end::reference[] +#ifdef BOOST_STRICT_CONFIG +# define BOOST_PREDEF_TESTED_AT(symbol, major, minor, patch) (0) +#else +# ifdef BOOST_DETECT_OUTDATED_WORKAROUNDS +# define BOOST_PREDEF_TESTED_AT(symbol, major, minor, patch) ( \ + BOOST_PREDEF_WORKAROUND(symbol, <=, major, minor, patch) \ + ? 1 \ + : (1%0) ) +# else +# define BOOST_PREDEF_TESTED_AT(symbol, major, minor, patch) \ + ( (symbol) >= BOOST_VERSION_NUMBER_AVAILABLE ) +# endif +#endif + +#endif diff --git a/boost/predef/version.h b/boost/predef/version.h new file mode 100644 index 00000000..4428eb56 --- /dev/null +++ b/boost/predef/version.h @@ -0,0 +1,15 @@ +/* +Copyright Rene Rivera 2015-2016 +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) +*/ + +#ifndef BOOST_PREDEF_VERSION_H +#define BOOST_PREDEF_VERSION_H + +#include + +#define BOOST_PREDEF_VERSION BOOST_VERSION_NUMBER(1,15,0) + +#endif diff --git a/boost/preprocessor/arithmetic/div.hpp b/boost/preprocessor/arithmetic/div.hpp new file mode 100644 index 00000000..c574b4aa --- /dev/null +++ b/boost/preprocessor/arithmetic/div.hpp @@ -0,0 +1,75 @@ +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * 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) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# /* Revised by Edward Diener (2020) */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_ARITHMETIC_DIV_HPP +# define BOOST_PREPROCESSOR_ARITHMETIC_DIV_HPP +# +# include +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() +# +# include +# include +# +# /* BOOST_PP_DIV */ +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() +# define BOOST_PP_DIV(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE(x, y)) +# else +# define BOOST_PP_DIV(x, y) BOOST_PP_DIV_I(x, y) +# define BOOST_PP_DIV_I(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE(x, y)) +# endif +# +# /* BOOST_PP_DIV_D */ +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() +# define BOOST_PP_DIV_D(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE_D(d, x, y)) +# else +# define BOOST_PP_DIV_D(d, x, y) BOOST_PP_DIV_D_I(d, x, y) +# define BOOST_PP_DIV_D_I(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE_D(d, x, y)) +# endif +# +# else +# +# include +# include +# include +# include +# include +# +# /* BOOST_PP_DIV */ +# +# define BOOST_PP_DIV(x, y) BOOST_PP_IIF(BOOST_PP_DETAIL_IS_1_NUMBER(y),BOOST_PP_IDENTITY_N(x,2),BOOST_PP_DIV_DO)(x,y) +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() +# define BOOST_PP_DIV_DO(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE(x, y)) +# else +# define BOOST_PP_DIV_DO(x, y) BOOST_PP_DIV_I(x, y) +# define BOOST_PP_DIV_I(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE(x, y)) +# endif +# +# /* BOOST_PP_DIV_D */ +# +# define BOOST_PP_DIV_D(d, x, y) BOOST_PP_IIF(BOOST_PP_DETAIL_IS_1_NUMBER(y),BOOST_PP_IDENTITY_N(x,3),BOOST_PP_DIV_DO_D)(d,x,y) +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() +# define BOOST_PP_DIV_DO_D(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE_D(d, x, y)) +# else +# define BOOST_PP_DIV_DO_D(d, x, y) BOOST_PP_DIV_D_I(d, x, y) +# define BOOST_PP_DIV_D_I(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE_D(d, x, y)) +# endif +# +# endif +# +# endif diff --git a/boost/preprocessor/arithmetic/mul.hpp b/boost/preprocessor/arithmetic/mul.hpp new file mode 100644 index 00000000..112e23e1 --- /dev/null +++ b/boost/preprocessor/arithmetic/mul.hpp @@ -0,0 +1,112 @@ +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * 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) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# /* Revised by Edward Diener (2020) */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_ARITHMETIC_MUL_HPP +# define BOOST_PREPROCESSOR_ARITHMETIC_MUL_HPP +# +# include +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() +# +# include +# include +# include +# include +# include +# +# /* BOOST_PP_MUL */ +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() +# define BOOST_PP_MUL(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_WHILE(BOOST_PP_MUL_P, BOOST_PP_MUL_O, (0, x, y))) +# else +# define BOOST_PP_MUL(x, y) BOOST_PP_MUL_I(x, y) +# define BOOST_PP_MUL_I(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_WHILE(BOOST_PP_MUL_P, BOOST_PP_MUL_O, (0, x, y))) +# endif +# +# define BOOST_PP_MUL_P(d, rxy) BOOST_PP_TUPLE_ELEM(3, 2, rxy) +# +# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() +# define BOOST_PP_MUL_O(d, rxy) BOOST_PP_MUL_O_IM(d, BOOST_PP_TUPLE_REM_3 rxy) +# define BOOST_PP_MUL_O_IM(d, im) BOOST_PP_MUL_O_I(d, im) +# else +# define BOOST_PP_MUL_O(d, rxy) BOOST_PP_MUL_O_I(d, BOOST_PP_TUPLE_ELEM(3, 0, rxy), BOOST_PP_TUPLE_ELEM(3, 1, rxy), BOOST_PP_TUPLE_ELEM(3, 2, rxy)) +# endif +# +# define BOOST_PP_MUL_O_I(d, r, x, y) (BOOST_PP_ADD_D(d, r, x), x, BOOST_PP_DEC(y)) +# +# /* BOOST_PP_MUL_D */ +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() +# define BOOST_PP_MUL_D(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_WHILE_ ## d(BOOST_PP_MUL_P, BOOST_PP_MUL_O, (0, x, y))) +# else +# define BOOST_PP_MUL_D(d, x, y) BOOST_PP_MUL_D_I(d, x, y) +# define BOOST_PP_MUL_D_I(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_WHILE_ ## d(BOOST_PP_MUL_P, BOOST_PP_MUL_O, (0, x, y))) +# endif +# +# else +# +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# +# /* BOOST_PP_MUL */ +# +# define BOOST_PP_MUL(x, y) BOOST_PP_IIF(BOOST_PP_DETAIL_IS_MINIMUM_NUMBER(x),BOOST_PP_IDENTITY_N(x,2),BOOST_PP_MUL_CHECK_1X)(x,y) +# +# define BOOST_PP_MUL_CHECK_1X(x, y) BOOST_PP_IIF(BOOST_PP_DETAIL_IS_1_NUMBER(x),BOOST_PP_IDENTITY_N(y,2),BOOST_PP_MUL_DO)(x,y) +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() +# define BOOST_PP_MUL_DO(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_WHILE(BOOST_PP_MUL_P, BOOST_PP_MUL_O, (0, x, y))) +# else +# define BOOST_PP_MUL_DO(x, y) BOOST_PP_MUL_I(x, y) +# define BOOST_PP_MUL_I(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_WHILE(BOOST_PP_MUL_P, BOOST_PP_MUL_O, (0, x, y))) +# endif +# +# define BOOST_PP_MUL_P(d, rxy) BOOST_PP_BITAND(BOOST_PP_BOOL(BOOST_PP_TUPLE_ELEM(3, 2, rxy)),BOOST_PP_COMPL(BOOST_PP_DETAIL_IS_MAXIMUM_NUMBER(BOOST_PP_TUPLE_ELEM(3, 0, rxy)))) +# +# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() +# define BOOST_PP_MUL_O(d, rxy) BOOST_PP_MUL_O_IM(d, BOOST_PP_TUPLE_REM_3 rxy) +# define BOOST_PP_MUL_O_IM(d, im) BOOST_PP_MUL_O_I(d, im) +# else +# define BOOST_PP_MUL_O(d, rxy) BOOST_PP_MUL_O_I(d, BOOST_PP_TUPLE_ELEM(3, 0, rxy), BOOST_PP_TUPLE_ELEM(3, 1, rxy), BOOST_PP_TUPLE_ELEM(3, 2, rxy)) +# endif +# +# define BOOST_PP_MUL_O_I(d, r, x, y) (BOOST_PP_ADD_D(d, r, x), x, BOOST_PP_DEC(y)) +# +# /* BOOST_PP_MUL_D */ +# +# define BOOST_PP_MUL_D(d, x, y) BOOST_PP_IIF(BOOST_PP_DETAIL_IS_MINIMUM_NUMBER(x),BOOST_PP_IDENTITY_N(x,3),BOOST_PP_MUL_CHECK_1X_D)(d,x,y) +# +# define BOOST_PP_MUL_CHECK_1X_D(d, x, y) BOOST_PP_IIF(BOOST_PP_DETAIL_IS_1_NUMBER(x),BOOST_PP_IDENTITY_N(y,3),BOOST_PP_MUL_DO_D)(d,x,y) +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() +# define BOOST_PP_MUL_DO_D(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_WHILE_ ## d(BOOST_PP_MUL_P, BOOST_PP_MUL_O, (0, x, y))) +# else +# define BOOST_PP_MUL_DO_D(d, x, y) BOOST_PP_MUL_D_I(d, x, y) +# define BOOST_PP_MUL_D_I(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_WHILE_ ## d(BOOST_PP_MUL_P, BOOST_PP_MUL_O, (0, x, y))) +# endif +# +# endif +# +# endif diff --git a/boost/preprocessor/detail/is_unary.hpp b/boost/preprocessor/detail/is_unary.hpp new file mode 100644 index 00000000..e73cdfb7 --- /dev/null +++ b/boost/preprocessor/detail/is_unary.hpp @@ -0,0 +1,30 @@ +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * 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) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_DETAIL_IS_UNARY_HPP +# define BOOST_PREPROCESSOR_DETAIL_IS_UNARY_HPP +# +# include +# include +# +# /* BOOST_PP_IS_UNARY */ +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() +# define BOOST_PP_IS_UNARY(x) BOOST_PP_CHECK(x, BOOST_PP_IS_UNARY_CHECK) +# else +# define BOOST_PP_IS_UNARY(x) BOOST_PP_IS_UNARY_I(x) +# define BOOST_PP_IS_UNARY_I(x) BOOST_PP_CHECK(x, BOOST_PP_IS_UNARY_CHECK) +# endif +# +# define BOOST_PP_IS_UNARY_CHECK(a) 1 +# define BOOST_PP_CHECK_RESULT_BOOST_PP_IS_UNARY_CHECK 0, BOOST_PP_NIL +# +# endif diff --git a/boost/preprocessor/enum.hpp b/boost/preprocessor/enum.hpp new file mode 100644 index 00000000..ae05bb0c --- /dev/null +++ b/boost/preprocessor/enum.hpp @@ -0,0 +1,17 @@ +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * 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) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_ENUM_HPP +# define BOOST_PREPROCESSOR_ENUM_HPP +# +# include +# +# endif diff --git a/boost/preprocessor/enum_params.hpp b/boost/preprocessor/enum_params.hpp new file mode 100644 index 00000000..414f8aa6 --- /dev/null +++ b/boost/preprocessor/enum_params.hpp @@ -0,0 +1,17 @@ +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * 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) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_ENUM_PARAMS_HPP +# define BOOST_PREPROCESSOR_ENUM_PARAMS_HPP +# +# include +# +# endif diff --git a/boost/preprocessor/enum_params_with_a_default.hpp b/boost/preprocessor/enum_params_with_a_default.hpp new file mode 100644 index 00000000..fd1ad4cc --- /dev/null +++ b/boost/preprocessor/enum_params_with_a_default.hpp @@ -0,0 +1,17 @@ +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * 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) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_ENUM_PARAMS_WITH_A_DEFAULT_HPP +# define BOOST_PREPROCESSOR_ENUM_PARAMS_WITH_A_DEFAULT_HPP +# +# include +# +# endif diff --git a/boost/preprocessor/facilities/intercept.hpp b/boost/preprocessor/facilities/intercept.hpp new file mode 100644 index 00000000..3b301350 --- /dev/null +++ b/boost/preprocessor/facilities/intercept.hpp @@ -0,0 +1,306 @@ +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * 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) +# * * +# ************************************************************************** */ +# +# /* Revised by Edward Diener (2020) */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_FACILITIES_INTERCEPT_HPP +# define BOOST_PREPROCESSOR_FACILITIES_INTERCEPT_HPP +# +# include +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() +# +# /* BOOST_PP_INTERCEPT */ +# +# define BOOST_PP_INTERCEPT BOOST_PP_INTERCEPT_ +# +# define BOOST_PP_INTERCEPT_0 +# define BOOST_PP_INTERCEPT_1 +# define BOOST_PP_INTERCEPT_2 +# define BOOST_PP_INTERCEPT_3 +# define BOOST_PP_INTERCEPT_4 +# define BOOST_PP_INTERCEPT_5 +# define BOOST_PP_INTERCEPT_6 +# define BOOST_PP_INTERCEPT_7 +# define BOOST_PP_INTERCEPT_8 +# define BOOST_PP_INTERCEPT_9 +# define BOOST_PP_INTERCEPT_10 +# define BOOST_PP_INTERCEPT_11 +# define BOOST_PP_INTERCEPT_12 +# define BOOST_PP_INTERCEPT_13 +# define BOOST_PP_INTERCEPT_14 +# define BOOST_PP_INTERCEPT_15 +# define BOOST_PP_INTERCEPT_16 +# define BOOST_PP_INTERCEPT_17 +# define BOOST_PP_INTERCEPT_18 +# define BOOST_PP_INTERCEPT_19 +# define BOOST_PP_INTERCEPT_20 +# define BOOST_PP_INTERCEPT_21 +# define BOOST_PP_INTERCEPT_22 +# define BOOST_PP_INTERCEPT_23 +# define BOOST_PP_INTERCEPT_24 +# define BOOST_PP_INTERCEPT_25 +# define BOOST_PP_INTERCEPT_26 +# define BOOST_PP_INTERCEPT_27 +# define BOOST_PP_INTERCEPT_28 +# define BOOST_PP_INTERCEPT_29 +# define BOOST_PP_INTERCEPT_30 +# define BOOST_PP_INTERCEPT_31 +# define BOOST_PP_INTERCEPT_32 +# define BOOST_PP_INTERCEPT_33 +# define BOOST_PP_INTERCEPT_34 +# define BOOST_PP_INTERCEPT_35 +# define BOOST_PP_INTERCEPT_36 +# define BOOST_PP_INTERCEPT_37 +# define BOOST_PP_INTERCEPT_38 +# define BOOST_PP_INTERCEPT_39 +# define BOOST_PP_INTERCEPT_40 +# define BOOST_PP_INTERCEPT_41 +# define BOOST_PP_INTERCEPT_42 +# define BOOST_PP_INTERCEPT_43 +# define BOOST_PP_INTERCEPT_44 +# define BOOST_PP_INTERCEPT_45 +# define BOOST_PP_INTERCEPT_46 +# define BOOST_PP_INTERCEPT_47 +# define BOOST_PP_INTERCEPT_48 +# define BOOST_PP_INTERCEPT_49 +# define BOOST_PP_INTERCEPT_50 +# define BOOST_PP_INTERCEPT_51 +# define BOOST_PP_INTERCEPT_52 +# define BOOST_PP_INTERCEPT_53 +# define BOOST_PP_INTERCEPT_54 +# define BOOST_PP_INTERCEPT_55 +# define BOOST_PP_INTERCEPT_56 +# define BOOST_PP_INTERCEPT_57 +# define BOOST_PP_INTERCEPT_58 +# define BOOST_PP_INTERCEPT_59 +# define BOOST_PP_INTERCEPT_60 +# define BOOST_PP_INTERCEPT_61 +# define BOOST_PP_INTERCEPT_62 +# define BOOST_PP_INTERCEPT_63 +# define BOOST_PP_INTERCEPT_64 +# define BOOST_PP_INTERCEPT_65 +# define BOOST_PP_INTERCEPT_66 +# define BOOST_PP_INTERCEPT_67 +# define BOOST_PP_INTERCEPT_68 +# define BOOST_PP_INTERCEPT_69 +# define BOOST_PP_INTERCEPT_70 +# define BOOST_PP_INTERCEPT_71 +# define BOOST_PP_INTERCEPT_72 +# define BOOST_PP_INTERCEPT_73 +# define BOOST_PP_INTERCEPT_74 +# define BOOST_PP_INTERCEPT_75 +# define BOOST_PP_INTERCEPT_76 +# define BOOST_PP_INTERCEPT_77 +# define BOOST_PP_INTERCEPT_78 +# define BOOST_PP_INTERCEPT_79 +# define BOOST_PP_INTERCEPT_80 +# define BOOST_PP_INTERCEPT_81 +# define BOOST_PP_INTERCEPT_82 +# define BOOST_PP_INTERCEPT_83 +# define BOOST_PP_INTERCEPT_84 +# define BOOST_PP_INTERCEPT_85 +# define BOOST_PP_INTERCEPT_86 +# define BOOST_PP_INTERCEPT_87 +# define BOOST_PP_INTERCEPT_88 +# define BOOST_PP_INTERCEPT_89 +# define BOOST_PP_INTERCEPT_90 +# define BOOST_PP_INTERCEPT_91 +# define BOOST_PP_INTERCEPT_92 +# define BOOST_PP_INTERCEPT_93 +# define BOOST_PP_INTERCEPT_94 +# define BOOST_PP_INTERCEPT_95 +# define BOOST_PP_INTERCEPT_96 +# define BOOST_PP_INTERCEPT_97 +# define BOOST_PP_INTERCEPT_98 +# define BOOST_PP_INTERCEPT_99 +# define BOOST_PP_INTERCEPT_100 +# define BOOST_PP_INTERCEPT_101 +# define BOOST_PP_INTERCEPT_102 +# define BOOST_PP_INTERCEPT_103 +# define BOOST_PP_INTERCEPT_104 +# define BOOST_PP_INTERCEPT_105 +# define BOOST_PP_INTERCEPT_106 +# define BOOST_PP_INTERCEPT_107 +# define BOOST_PP_INTERCEPT_108 +# define BOOST_PP_INTERCEPT_109 +# define BOOST_PP_INTERCEPT_110 +# define BOOST_PP_INTERCEPT_111 +# define BOOST_PP_INTERCEPT_112 +# define BOOST_PP_INTERCEPT_113 +# define BOOST_PP_INTERCEPT_114 +# define BOOST_PP_INTERCEPT_115 +# define BOOST_PP_INTERCEPT_116 +# define BOOST_PP_INTERCEPT_117 +# define BOOST_PP_INTERCEPT_118 +# define BOOST_PP_INTERCEPT_119 +# define BOOST_PP_INTERCEPT_120 +# define BOOST_PP_INTERCEPT_121 +# define BOOST_PP_INTERCEPT_122 +# define BOOST_PP_INTERCEPT_123 +# define BOOST_PP_INTERCEPT_124 +# define BOOST_PP_INTERCEPT_125 +# define BOOST_PP_INTERCEPT_126 +# define BOOST_PP_INTERCEPT_127 +# define BOOST_PP_INTERCEPT_128 +# define BOOST_PP_INTERCEPT_129 +# define BOOST_PP_INTERCEPT_130 +# define BOOST_PP_INTERCEPT_131 +# define BOOST_PP_INTERCEPT_132 +# define BOOST_PP_INTERCEPT_133 +# define BOOST_PP_INTERCEPT_134 +# define BOOST_PP_INTERCEPT_135 +# define BOOST_PP_INTERCEPT_136 +# define BOOST_PP_INTERCEPT_137 +# define BOOST_PP_INTERCEPT_138 +# define BOOST_PP_INTERCEPT_139 +# define BOOST_PP_INTERCEPT_140 +# define BOOST_PP_INTERCEPT_141 +# define BOOST_PP_INTERCEPT_142 +# define BOOST_PP_INTERCEPT_143 +# define BOOST_PP_INTERCEPT_144 +# define BOOST_PP_INTERCEPT_145 +# define BOOST_PP_INTERCEPT_146 +# define BOOST_PP_INTERCEPT_147 +# define BOOST_PP_INTERCEPT_148 +# define BOOST_PP_INTERCEPT_149 +# define BOOST_PP_INTERCEPT_150 +# define BOOST_PP_INTERCEPT_151 +# define BOOST_PP_INTERCEPT_152 +# define BOOST_PP_INTERCEPT_153 +# define BOOST_PP_INTERCEPT_154 +# define BOOST_PP_INTERCEPT_155 +# define BOOST_PP_INTERCEPT_156 +# define BOOST_PP_INTERCEPT_157 +# define BOOST_PP_INTERCEPT_158 +# define BOOST_PP_INTERCEPT_159 +# define BOOST_PP_INTERCEPT_160 +# define BOOST_PP_INTERCEPT_161 +# define BOOST_PP_INTERCEPT_162 +# define BOOST_PP_INTERCEPT_163 +# define BOOST_PP_INTERCEPT_164 +# define BOOST_PP_INTERCEPT_165 +# define BOOST_PP_INTERCEPT_166 +# define BOOST_PP_INTERCEPT_167 +# define BOOST_PP_INTERCEPT_168 +# define BOOST_PP_INTERCEPT_169 +# define BOOST_PP_INTERCEPT_170 +# define BOOST_PP_INTERCEPT_171 +# define BOOST_PP_INTERCEPT_172 +# define BOOST_PP_INTERCEPT_173 +# define BOOST_PP_INTERCEPT_174 +# define BOOST_PP_INTERCEPT_175 +# define BOOST_PP_INTERCEPT_176 +# define BOOST_PP_INTERCEPT_177 +# define BOOST_PP_INTERCEPT_178 +# define BOOST_PP_INTERCEPT_179 +# define BOOST_PP_INTERCEPT_180 +# define BOOST_PP_INTERCEPT_181 +# define BOOST_PP_INTERCEPT_182 +# define BOOST_PP_INTERCEPT_183 +# define BOOST_PP_INTERCEPT_184 +# define BOOST_PP_INTERCEPT_185 +# define BOOST_PP_INTERCEPT_186 +# define BOOST_PP_INTERCEPT_187 +# define BOOST_PP_INTERCEPT_188 +# define BOOST_PP_INTERCEPT_189 +# define BOOST_PP_INTERCEPT_190 +# define BOOST_PP_INTERCEPT_191 +# define BOOST_PP_INTERCEPT_192 +# define BOOST_PP_INTERCEPT_193 +# define BOOST_PP_INTERCEPT_194 +# define BOOST_PP_INTERCEPT_195 +# define BOOST_PP_INTERCEPT_196 +# define BOOST_PP_INTERCEPT_197 +# define BOOST_PP_INTERCEPT_198 +# define BOOST_PP_INTERCEPT_199 +# define BOOST_PP_INTERCEPT_200 +# define BOOST_PP_INTERCEPT_201 +# define BOOST_PP_INTERCEPT_202 +# define BOOST_PP_INTERCEPT_203 +# define BOOST_PP_INTERCEPT_204 +# define BOOST_PP_INTERCEPT_205 +# define BOOST_PP_INTERCEPT_206 +# define BOOST_PP_INTERCEPT_207 +# define BOOST_PP_INTERCEPT_208 +# define BOOST_PP_INTERCEPT_209 +# define BOOST_PP_INTERCEPT_210 +# define BOOST_PP_INTERCEPT_211 +# define BOOST_PP_INTERCEPT_212 +# define BOOST_PP_INTERCEPT_213 +# define BOOST_PP_INTERCEPT_214 +# define BOOST_PP_INTERCEPT_215 +# define BOOST_PP_INTERCEPT_216 +# define BOOST_PP_INTERCEPT_217 +# define BOOST_PP_INTERCEPT_218 +# define BOOST_PP_INTERCEPT_219 +# define BOOST_PP_INTERCEPT_220 +# define BOOST_PP_INTERCEPT_221 +# define BOOST_PP_INTERCEPT_222 +# define BOOST_PP_INTERCEPT_223 +# define BOOST_PP_INTERCEPT_224 +# define BOOST_PP_INTERCEPT_225 +# define BOOST_PP_INTERCEPT_226 +# define BOOST_PP_INTERCEPT_227 +# define BOOST_PP_INTERCEPT_228 +# define BOOST_PP_INTERCEPT_229 +# define BOOST_PP_INTERCEPT_230 +# define BOOST_PP_INTERCEPT_231 +# define BOOST_PP_INTERCEPT_232 +# define BOOST_PP_INTERCEPT_233 +# define BOOST_PP_INTERCEPT_234 +# define BOOST_PP_INTERCEPT_235 +# define BOOST_PP_INTERCEPT_236 +# define BOOST_PP_INTERCEPT_237 +# define BOOST_PP_INTERCEPT_238 +# define BOOST_PP_INTERCEPT_239 +# define BOOST_PP_INTERCEPT_240 +# define BOOST_PP_INTERCEPT_241 +# define BOOST_PP_INTERCEPT_242 +# define BOOST_PP_INTERCEPT_243 +# define BOOST_PP_INTERCEPT_244 +# define BOOST_PP_INTERCEPT_245 +# define BOOST_PP_INTERCEPT_246 +# define BOOST_PP_INTERCEPT_247 +# define BOOST_PP_INTERCEPT_248 +# define BOOST_PP_INTERCEPT_249 +# define BOOST_PP_INTERCEPT_250 +# define BOOST_PP_INTERCEPT_251 +# define BOOST_PP_INTERCEPT_252 +# define BOOST_PP_INTERCEPT_253 +# define BOOST_PP_INTERCEPT_254 +# define BOOST_PP_INTERCEPT_255 +# define BOOST_PP_INTERCEPT_256 +# +# else +# +# /* BOOST_PP_INTERCEPT */ +# +# define BOOST_PP_INTERCEPT BOOST_PP_INTERCEPT_ +# +# include +# +# if BOOST_PP_LIMIT_MAG == 256 +# include +# elif BOOST_PP_LIMIT_MAG == 512 +# include +# include +# elif BOOST_PP_LIMIT_MAG == 1024 +# include +# include +# include +# else +# error Incorrect value for the BOOST_PP_LIMIT_MAG limit +# endif +# +# endif +# +# endif diff --git a/boost/preprocessor/facilities/limits/intercept_1024.hpp b/boost/preprocessor/facilities/limits/intercept_1024.hpp new file mode 100644 index 00000000..a1cae87d --- /dev/null +++ b/boost/preprocessor/facilities/limits/intercept_1024.hpp @@ -0,0 +1,530 @@ +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * 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) +# * * +# ************************************************************************** */ +# +# /* Revised by Edward Diener (2020) */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_FACILITIES_INTERCEPT_1024_HPP +# define BOOST_PREPROCESSOR_FACILITIES_INTERCEPT_1024_HPP +# +# define BOOST_PP_INTERCEPT_513 +# define BOOST_PP_INTERCEPT_514 +# define BOOST_PP_INTERCEPT_515 +# define BOOST_PP_INTERCEPT_516 +# define BOOST_PP_INTERCEPT_517 +# define BOOST_PP_INTERCEPT_518 +# define BOOST_PP_INTERCEPT_519 +# define BOOST_PP_INTERCEPT_520 +# define BOOST_PP_INTERCEPT_521 +# define BOOST_PP_INTERCEPT_522 +# define BOOST_PP_INTERCEPT_523 +# define BOOST_PP_INTERCEPT_524 +# define BOOST_PP_INTERCEPT_525 +# define BOOST_PP_INTERCEPT_526 +# define BOOST_PP_INTERCEPT_527 +# define BOOST_PP_INTERCEPT_528 +# define BOOST_PP_INTERCEPT_529 +# define BOOST_PP_INTERCEPT_530 +# define BOOST_PP_INTERCEPT_531 +# define BOOST_PP_INTERCEPT_532 +# define BOOST_PP_INTERCEPT_533 +# define BOOST_PP_INTERCEPT_534 +# define BOOST_PP_INTERCEPT_535 +# define BOOST_PP_INTERCEPT_536 +# define BOOST_PP_INTERCEPT_537 +# define BOOST_PP_INTERCEPT_538 +# define BOOST_PP_INTERCEPT_539 +# define BOOST_PP_INTERCEPT_540 +# define BOOST_PP_INTERCEPT_541 +# define BOOST_PP_INTERCEPT_542 +# define BOOST_PP_INTERCEPT_543 +# define BOOST_PP_INTERCEPT_544 +# define BOOST_PP_INTERCEPT_545 +# define BOOST_PP_INTERCEPT_546 +# define BOOST_PP_INTERCEPT_547 +# define BOOST_PP_INTERCEPT_548 +# define BOOST_PP_INTERCEPT_549 +# define BOOST_PP_INTERCEPT_550 +# define BOOST_PP_INTERCEPT_551 +# define BOOST_PP_INTERCEPT_552 +# define BOOST_PP_INTERCEPT_553 +# define BOOST_PP_INTERCEPT_554 +# define BOOST_PP_INTERCEPT_555 +# define BOOST_PP_INTERCEPT_556 +# define BOOST_PP_INTERCEPT_557 +# define BOOST_PP_INTERCEPT_558 +# define BOOST_PP_INTERCEPT_559 +# define BOOST_PP_INTERCEPT_560 +# define BOOST_PP_INTERCEPT_561 +# define BOOST_PP_INTERCEPT_562 +# define BOOST_PP_INTERCEPT_563 +# define BOOST_PP_INTERCEPT_564 +# define BOOST_PP_INTERCEPT_565 +# define BOOST_PP_INTERCEPT_566 +# define BOOST_PP_INTERCEPT_567 +# define BOOST_PP_INTERCEPT_568 +# define BOOST_PP_INTERCEPT_569 +# define BOOST_PP_INTERCEPT_570 +# define BOOST_PP_INTERCEPT_571 +# define BOOST_PP_INTERCEPT_572 +# define BOOST_PP_INTERCEPT_573 +# define BOOST_PP_INTERCEPT_574 +# define BOOST_PP_INTERCEPT_575 +# define BOOST_PP_INTERCEPT_576 +# define BOOST_PP_INTERCEPT_577 +# define BOOST_PP_INTERCEPT_578 +# define BOOST_PP_INTERCEPT_579 +# define BOOST_PP_INTERCEPT_580 +# define BOOST_PP_INTERCEPT_581 +# define BOOST_PP_INTERCEPT_582 +# define BOOST_PP_INTERCEPT_583 +# define BOOST_PP_INTERCEPT_584 +# define BOOST_PP_INTERCEPT_585 +# define BOOST_PP_INTERCEPT_586 +# define BOOST_PP_INTERCEPT_587 +# define BOOST_PP_INTERCEPT_588 +# define BOOST_PP_INTERCEPT_589 +# define BOOST_PP_INTERCEPT_590 +# define BOOST_PP_INTERCEPT_591 +# define BOOST_PP_INTERCEPT_592 +# define BOOST_PP_INTERCEPT_593 +# define BOOST_PP_INTERCEPT_594 +# define BOOST_PP_INTERCEPT_595 +# define BOOST_PP_INTERCEPT_596 +# define BOOST_PP_INTERCEPT_597 +# define BOOST_PP_INTERCEPT_598 +# define BOOST_PP_INTERCEPT_599 +# define BOOST_PP_INTERCEPT_600 +# define BOOST_PP_INTERCEPT_601 +# define BOOST_PP_INTERCEPT_602 +# define BOOST_PP_INTERCEPT_603 +# define BOOST_PP_INTERCEPT_604 +# define BOOST_PP_INTERCEPT_605 +# define BOOST_PP_INTERCEPT_606 +# define BOOST_PP_INTERCEPT_607 +# define BOOST_PP_INTERCEPT_608 +# define BOOST_PP_INTERCEPT_609 +# define BOOST_PP_INTERCEPT_610 +# define BOOST_PP_INTERCEPT_611 +# define BOOST_PP_INTERCEPT_612 +# define BOOST_PP_INTERCEPT_613 +# define BOOST_PP_INTERCEPT_614 +# define BOOST_PP_INTERCEPT_615 +# define BOOST_PP_INTERCEPT_616 +# define BOOST_PP_INTERCEPT_617 +# define BOOST_PP_INTERCEPT_618 +# define BOOST_PP_INTERCEPT_619 +# define BOOST_PP_INTERCEPT_620 +# define BOOST_PP_INTERCEPT_621 +# define BOOST_PP_INTERCEPT_622 +# define BOOST_PP_INTERCEPT_623 +# define BOOST_PP_INTERCEPT_624 +# define BOOST_PP_INTERCEPT_625 +# define BOOST_PP_INTERCEPT_626 +# define BOOST_PP_INTERCEPT_627 +# define BOOST_PP_INTERCEPT_628 +# define BOOST_PP_INTERCEPT_629 +# define BOOST_PP_INTERCEPT_630 +# define BOOST_PP_INTERCEPT_631 +# define BOOST_PP_INTERCEPT_632 +# define BOOST_PP_INTERCEPT_633 +# define BOOST_PP_INTERCEPT_634 +# define BOOST_PP_INTERCEPT_635 +# define BOOST_PP_INTERCEPT_636 +# define BOOST_PP_INTERCEPT_637 +# define BOOST_PP_INTERCEPT_638 +# define BOOST_PP_INTERCEPT_639 +# define BOOST_PP_INTERCEPT_640 +# define BOOST_PP_INTERCEPT_641 +# define BOOST_PP_INTERCEPT_642 +# define BOOST_PP_INTERCEPT_643 +# define BOOST_PP_INTERCEPT_644 +# define BOOST_PP_INTERCEPT_645 +# define BOOST_PP_INTERCEPT_646 +# define BOOST_PP_INTERCEPT_647 +# define BOOST_PP_INTERCEPT_648 +# define BOOST_PP_INTERCEPT_649 +# define BOOST_PP_INTERCEPT_650 +# define BOOST_PP_INTERCEPT_651 +# define BOOST_PP_INTERCEPT_652 +# define BOOST_PP_INTERCEPT_653 +# define BOOST_PP_INTERCEPT_654 +# define BOOST_PP_INTERCEPT_655 +# define BOOST_PP_INTERCEPT_656 +# define BOOST_PP_INTERCEPT_657 +# define BOOST_PP_INTERCEPT_658 +# define BOOST_PP_INTERCEPT_659 +# define BOOST_PP_INTERCEPT_660 +# define BOOST_PP_INTERCEPT_661 +# define BOOST_PP_INTERCEPT_662 +# define BOOST_PP_INTERCEPT_663 +# define BOOST_PP_INTERCEPT_664 +# define BOOST_PP_INTERCEPT_665 +# define BOOST_PP_INTERCEPT_666 +# define BOOST_PP_INTERCEPT_667 +# define BOOST_PP_INTERCEPT_668 +# define BOOST_PP_INTERCEPT_669 +# define BOOST_PP_INTERCEPT_670 +# define BOOST_PP_INTERCEPT_671 +# define BOOST_PP_INTERCEPT_672 +# define BOOST_PP_INTERCEPT_673 +# define BOOST_PP_INTERCEPT_674 +# define BOOST_PP_INTERCEPT_675 +# define BOOST_PP_INTERCEPT_676 +# define BOOST_PP_INTERCEPT_677 +# define BOOST_PP_INTERCEPT_678 +# define BOOST_PP_INTERCEPT_679 +# define BOOST_PP_INTERCEPT_680 +# define BOOST_PP_INTERCEPT_681 +# define BOOST_PP_INTERCEPT_682 +# define BOOST_PP_INTERCEPT_683 +# define BOOST_PP_INTERCEPT_684 +# define BOOST_PP_INTERCEPT_685 +# define BOOST_PP_INTERCEPT_686 +# define BOOST_PP_INTERCEPT_687 +# define BOOST_PP_INTERCEPT_688 +# define BOOST_PP_INTERCEPT_689 +# define BOOST_PP_INTERCEPT_690 +# define BOOST_PP_INTERCEPT_691 +# define BOOST_PP_INTERCEPT_692 +# define BOOST_PP_INTERCEPT_693 +# define BOOST_PP_INTERCEPT_694 +# define BOOST_PP_INTERCEPT_695 +# define BOOST_PP_INTERCEPT_696 +# define BOOST_PP_INTERCEPT_697 +# define BOOST_PP_INTERCEPT_698 +# define BOOST_PP_INTERCEPT_699 +# define BOOST_PP_INTERCEPT_700 +# define BOOST_PP_INTERCEPT_701 +# define BOOST_PP_INTERCEPT_702 +# define BOOST_PP_INTERCEPT_703 +# define BOOST_PP_INTERCEPT_704 +# define BOOST_PP_INTERCEPT_705 +# define BOOST_PP_INTERCEPT_706 +# define BOOST_PP_INTERCEPT_707 +# define BOOST_PP_INTERCEPT_708 +# define BOOST_PP_INTERCEPT_709 +# define BOOST_PP_INTERCEPT_710 +# define BOOST_PP_INTERCEPT_711 +# define BOOST_PP_INTERCEPT_712 +# define BOOST_PP_INTERCEPT_713 +# define BOOST_PP_INTERCEPT_714 +# define BOOST_PP_INTERCEPT_715 +# define BOOST_PP_INTERCEPT_716 +# define BOOST_PP_INTERCEPT_717 +# define BOOST_PP_INTERCEPT_718 +# define BOOST_PP_INTERCEPT_719 +# define BOOST_PP_INTERCEPT_720 +# define BOOST_PP_INTERCEPT_721 +# define BOOST_PP_INTERCEPT_722 +# define BOOST_PP_INTERCEPT_723 +# define BOOST_PP_INTERCEPT_724 +# define BOOST_PP_INTERCEPT_725 +# define BOOST_PP_INTERCEPT_726 +# define BOOST_PP_INTERCEPT_727 +# define BOOST_PP_INTERCEPT_728 +# define BOOST_PP_INTERCEPT_729 +# define BOOST_PP_INTERCEPT_730 +# define BOOST_PP_INTERCEPT_731 +# define BOOST_PP_INTERCEPT_732 +# define BOOST_PP_INTERCEPT_733 +# define BOOST_PP_INTERCEPT_734 +# define BOOST_PP_INTERCEPT_735 +# define BOOST_PP_INTERCEPT_736 +# define BOOST_PP_INTERCEPT_737 +# define BOOST_PP_INTERCEPT_738 +# define BOOST_PP_INTERCEPT_739 +# define BOOST_PP_INTERCEPT_740 +# define BOOST_PP_INTERCEPT_741 +# define BOOST_PP_INTERCEPT_742 +# define BOOST_PP_INTERCEPT_743 +# define BOOST_PP_INTERCEPT_744 +# define BOOST_PP_INTERCEPT_745 +# define BOOST_PP_INTERCEPT_746 +# define BOOST_PP_INTERCEPT_747 +# define BOOST_PP_INTERCEPT_748 +# define BOOST_PP_INTERCEPT_749 +# define BOOST_PP_INTERCEPT_750 +# define BOOST_PP_INTERCEPT_751 +# define BOOST_PP_INTERCEPT_752 +# define BOOST_PP_INTERCEPT_753 +# define BOOST_PP_INTERCEPT_754 +# define BOOST_PP_INTERCEPT_755 +# define BOOST_PP_INTERCEPT_756 +# define BOOST_PP_INTERCEPT_757 +# define BOOST_PP_INTERCEPT_758 +# define BOOST_PP_INTERCEPT_759 +# define BOOST_PP_INTERCEPT_760 +# define BOOST_PP_INTERCEPT_761 +# define BOOST_PP_INTERCEPT_762 +# define BOOST_PP_INTERCEPT_763 +# define BOOST_PP_INTERCEPT_764 +# define BOOST_PP_INTERCEPT_765 +# define BOOST_PP_INTERCEPT_766 +# define BOOST_PP_INTERCEPT_767 +# define BOOST_PP_INTERCEPT_768 +# define BOOST_PP_INTERCEPT_769 +# define BOOST_PP_INTERCEPT_770 +# define BOOST_PP_INTERCEPT_771 +# define BOOST_PP_INTERCEPT_772 +# define BOOST_PP_INTERCEPT_773 +# define BOOST_PP_INTERCEPT_774 +# define BOOST_PP_INTERCEPT_775 +# define BOOST_PP_INTERCEPT_776 +# define BOOST_PP_INTERCEPT_777 +# define BOOST_PP_INTERCEPT_778 +# define BOOST_PP_INTERCEPT_779 +# define BOOST_PP_INTERCEPT_780 +# define BOOST_PP_INTERCEPT_781 +# define BOOST_PP_INTERCEPT_782 +# define BOOST_PP_INTERCEPT_783 +# define BOOST_PP_INTERCEPT_784 +# define BOOST_PP_INTERCEPT_785 +# define BOOST_PP_INTERCEPT_786 +# define BOOST_PP_INTERCEPT_787 +# define BOOST_PP_INTERCEPT_788 +# define BOOST_PP_INTERCEPT_789 +# define BOOST_PP_INTERCEPT_790 +# define BOOST_PP_INTERCEPT_791 +# define BOOST_PP_INTERCEPT_792 +# define BOOST_PP_INTERCEPT_793 +# define BOOST_PP_INTERCEPT_794 +# define BOOST_PP_INTERCEPT_795 +# define BOOST_PP_INTERCEPT_796 +# define BOOST_PP_INTERCEPT_797 +# define BOOST_PP_INTERCEPT_798 +# define BOOST_PP_INTERCEPT_799 +# define BOOST_PP_INTERCEPT_800 +# define BOOST_PP_INTERCEPT_801 +# define BOOST_PP_INTERCEPT_802 +# define BOOST_PP_INTERCEPT_803 +# define BOOST_PP_INTERCEPT_804 +# define BOOST_PP_INTERCEPT_805 +# define BOOST_PP_INTERCEPT_806 +# define BOOST_PP_INTERCEPT_807 +# define BOOST_PP_INTERCEPT_808 +# define BOOST_PP_INTERCEPT_809 +# define BOOST_PP_INTERCEPT_810 +# define BOOST_PP_INTERCEPT_811 +# define BOOST_PP_INTERCEPT_812 +# define BOOST_PP_INTERCEPT_813 +# define BOOST_PP_INTERCEPT_814 +# define BOOST_PP_INTERCEPT_815 +# define BOOST_PP_INTERCEPT_816 +# define BOOST_PP_INTERCEPT_817 +# define BOOST_PP_INTERCEPT_818 +# define BOOST_PP_INTERCEPT_819 +# define BOOST_PP_INTERCEPT_820 +# define BOOST_PP_INTERCEPT_821 +# define BOOST_PP_INTERCEPT_822 +# define BOOST_PP_INTERCEPT_823 +# define BOOST_PP_INTERCEPT_824 +# define BOOST_PP_INTERCEPT_825 +# define BOOST_PP_INTERCEPT_826 +# define BOOST_PP_INTERCEPT_827 +# define BOOST_PP_INTERCEPT_828 +# define BOOST_PP_INTERCEPT_829 +# define BOOST_PP_INTERCEPT_830 +# define BOOST_PP_INTERCEPT_831 +# define BOOST_PP_INTERCEPT_832 +# define BOOST_PP_INTERCEPT_833 +# define BOOST_PP_INTERCEPT_834 +# define BOOST_PP_INTERCEPT_835 +# define BOOST_PP_INTERCEPT_836 +# define BOOST_PP_INTERCEPT_837 +# define BOOST_PP_INTERCEPT_838 +# define BOOST_PP_INTERCEPT_839 +# define BOOST_PP_INTERCEPT_840 +# define BOOST_PP_INTERCEPT_841 +# define BOOST_PP_INTERCEPT_842 +# define BOOST_PP_INTERCEPT_843 +# define BOOST_PP_INTERCEPT_844 +# define BOOST_PP_INTERCEPT_845 +# define BOOST_PP_INTERCEPT_846 +# define BOOST_PP_INTERCEPT_847 +# define BOOST_PP_INTERCEPT_848 +# define BOOST_PP_INTERCEPT_849 +# define BOOST_PP_INTERCEPT_850 +# define BOOST_PP_INTERCEPT_851 +# define BOOST_PP_INTERCEPT_852 +# define BOOST_PP_INTERCEPT_853 +# define BOOST_PP_INTERCEPT_854 +# define BOOST_PP_INTERCEPT_855 +# define BOOST_PP_INTERCEPT_856 +# define BOOST_PP_INTERCEPT_857 +# define BOOST_PP_INTERCEPT_858 +# define BOOST_PP_INTERCEPT_859 +# define BOOST_PP_INTERCEPT_860 +# define BOOST_PP_INTERCEPT_861 +# define BOOST_PP_INTERCEPT_862 +# define BOOST_PP_INTERCEPT_863 +# define BOOST_PP_INTERCEPT_864 +# define BOOST_PP_INTERCEPT_865 +# define BOOST_PP_INTERCEPT_866 +# define BOOST_PP_INTERCEPT_867 +# define BOOST_PP_INTERCEPT_868 +# define BOOST_PP_INTERCEPT_869 +# define BOOST_PP_INTERCEPT_870 +# define BOOST_PP_INTERCEPT_871 +# define BOOST_PP_INTERCEPT_872 +# define BOOST_PP_INTERCEPT_873 +# define BOOST_PP_INTERCEPT_874 +# define BOOST_PP_INTERCEPT_875 +# define BOOST_PP_INTERCEPT_876 +# define BOOST_PP_INTERCEPT_877 +# define BOOST_PP_INTERCEPT_878 +# define BOOST_PP_INTERCEPT_879 +# define BOOST_PP_INTERCEPT_880 +# define BOOST_PP_INTERCEPT_881 +# define BOOST_PP_INTERCEPT_882 +# define BOOST_PP_INTERCEPT_883 +# define BOOST_PP_INTERCEPT_884 +# define BOOST_PP_INTERCEPT_885 +# define BOOST_PP_INTERCEPT_886 +# define BOOST_PP_INTERCEPT_887 +# define BOOST_PP_INTERCEPT_888 +# define BOOST_PP_INTERCEPT_889 +# define BOOST_PP_INTERCEPT_890 +# define BOOST_PP_INTERCEPT_891 +# define BOOST_PP_INTERCEPT_892 +# define BOOST_PP_INTERCEPT_893 +# define BOOST_PP_INTERCEPT_894 +# define BOOST_PP_INTERCEPT_895 +# define BOOST_PP_INTERCEPT_896 +# define BOOST_PP_INTERCEPT_897 +# define BOOST_PP_INTERCEPT_898 +# define BOOST_PP_INTERCEPT_899 +# define BOOST_PP_INTERCEPT_900 +# define BOOST_PP_INTERCEPT_901 +# define BOOST_PP_INTERCEPT_902 +# define BOOST_PP_INTERCEPT_903 +# define BOOST_PP_INTERCEPT_904 +# define BOOST_PP_INTERCEPT_905 +# define BOOST_PP_INTERCEPT_906 +# define BOOST_PP_INTERCEPT_907 +# define BOOST_PP_INTERCEPT_908 +# define BOOST_PP_INTERCEPT_909 +# define BOOST_PP_INTERCEPT_910 +# define BOOST_PP_INTERCEPT_911 +# define BOOST_PP_INTERCEPT_912 +# define BOOST_PP_INTERCEPT_913 +# define BOOST_PP_INTERCEPT_914 +# define BOOST_PP_INTERCEPT_915 +# define BOOST_PP_INTERCEPT_916 +# define BOOST_PP_INTERCEPT_917 +# define BOOST_PP_INTERCEPT_918 +# define BOOST_PP_INTERCEPT_919 +# define BOOST_PP_INTERCEPT_920 +# define BOOST_PP_INTERCEPT_921 +# define BOOST_PP_INTERCEPT_922 +# define BOOST_PP_INTERCEPT_923 +# define BOOST_PP_INTERCEPT_924 +# define BOOST_PP_INTERCEPT_925 +# define BOOST_PP_INTERCEPT_926 +# define BOOST_PP_INTERCEPT_927 +# define BOOST_PP_INTERCEPT_928 +# define BOOST_PP_INTERCEPT_929 +# define BOOST_PP_INTERCEPT_930 +# define BOOST_PP_INTERCEPT_931 +# define BOOST_PP_INTERCEPT_932 +# define BOOST_PP_INTERCEPT_933 +# define BOOST_PP_INTERCEPT_934 +# define BOOST_PP_INTERCEPT_935 +# define BOOST_PP_INTERCEPT_936 +# define BOOST_PP_INTERCEPT_937 +# define BOOST_PP_INTERCEPT_938 +# define BOOST_PP_INTERCEPT_939 +# define BOOST_PP_INTERCEPT_940 +# define BOOST_PP_INTERCEPT_941 +# define BOOST_PP_INTERCEPT_942 +# define BOOST_PP_INTERCEPT_943 +# define BOOST_PP_INTERCEPT_944 +# define BOOST_PP_INTERCEPT_945 +# define BOOST_PP_INTERCEPT_946 +# define BOOST_PP_INTERCEPT_947 +# define BOOST_PP_INTERCEPT_948 +# define BOOST_PP_INTERCEPT_949 +# define BOOST_PP_INTERCEPT_950 +# define BOOST_PP_INTERCEPT_951 +# define BOOST_PP_INTERCEPT_952 +# define BOOST_PP_INTERCEPT_953 +# define BOOST_PP_INTERCEPT_954 +# define BOOST_PP_INTERCEPT_955 +# define BOOST_PP_INTERCEPT_956 +# define BOOST_PP_INTERCEPT_957 +# define BOOST_PP_INTERCEPT_958 +# define BOOST_PP_INTERCEPT_959 +# define BOOST_PP_INTERCEPT_960 +# define BOOST_PP_INTERCEPT_961 +# define BOOST_PP_INTERCEPT_962 +# define BOOST_PP_INTERCEPT_963 +# define BOOST_PP_INTERCEPT_964 +# define BOOST_PP_INTERCEPT_965 +# define BOOST_PP_INTERCEPT_966 +# define BOOST_PP_INTERCEPT_967 +# define BOOST_PP_INTERCEPT_968 +# define BOOST_PP_INTERCEPT_969 +# define BOOST_PP_INTERCEPT_970 +# define BOOST_PP_INTERCEPT_971 +# define BOOST_PP_INTERCEPT_972 +# define BOOST_PP_INTERCEPT_973 +# define BOOST_PP_INTERCEPT_974 +# define BOOST_PP_INTERCEPT_975 +# define BOOST_PP_INTERCEPT_976 +# define BOOST_PP_INTERCEPT_977 +# define BOOST_PP_INTERCEPT_978 +# define BOOST_PP_INTERCEPT_979 +# define BOOST_PP_INTERCEPT_980 +# define BOOST_PP_INTERCEPT_981 +# define BOOST_PP_INTERCEPT_982 +# define BOOST_PP_INTERCEPT_983 +# define BOOST_PP_INTERCEPT_984 +# define BOOST_PP_INTERCEPT_985 +# define BOOST_PP_INTERCEPT_986 +# define BOOST_PP_INTERCEPT_987 +# define BOOST_PP_INTERCEPT_988 +# define BOOST_PP_INTERCEPT_989 +# define BOOST_PP_INTERCEPT_990 +# define BOOST_PP_INTERCEPT_991 +# define BOOST_PP_INTERCEPT_992 +# define BOOST_PP_INTERCEPT_993 +# define BOOST_PP_INTERCEPT_994 +# define BOOST_PP_INTERCEPT_995 +# define BOOST_PP_INTERCEPT_996 +# define BOOST_PP_INTERCEPT_997 +# define BOOST_PP_INTERCEPT_998 +# define BOOST_PP_INTERCEPT_999 +# define BOOST_PP_INTERCEPT_1000 +# define BOOST_PP_INTERCEPT_1001 +# define BOOST_PP_INTERCEPT_1002 +# define BOOST_PP_INTERCEPT_1003 +# define BOOST_PP_INTERCEPT_1004 +# define BOOST_PP_INTERCEPT_1005 +# define BOOST_PP_INTERCEPT_1006 +# define BOOST_PP_INTERCEPT_1007 +# define BOOST_PP_INTERCEPT_1008 +# define BOOST_PP_INTERCEPT_1009 +# define BOOST_PP_INTERCEPT_1010 +# define BOOST_PP_INTERCEPT_1011 +# define BOOST_PP_INTERCEPT_1012 +# define BOOST_PP_INTERCEPT_1013 +# define BOOST_PP_INTERCEPT_1014 +# define BOOST_PP_INTERCEPT_1015 +# define BOOST_PP_INTERCEPT_1016 +# define BOOST_PP_INTERCEPT_1017 +# define BOOST_PP_INTERCEPT_1018 +# define BOOST_PP_INTERCEPT_1019 +# define BOOST_PP_INTERCEPT_1020 +# define BOOST_PP_INTERCEPT_1021 +# define BOOST_PP_INTERCEPT_1022 +# define BOOST_PP_INTERCEPT_1023 +# define BOOST_PP_INTERCEPT_1024 +# +# endif diff --git a/boost/preprocessor/facilities/limits/intercept_256.hpp b/boost/preprocessor/facilities/limits/intercept_256.hpp new file mode 100644 index 00000000..1a3675da --- /dev/null +++ b/boost/preprocessor/facilities/limits/intercept_256.hpp @@ -0,0 +1,273 @@ +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * 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) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_FACILITIES_INTERCEPT_256_HPP +# define BOOST_PREPROCESSOR_FACILITIES_INTERCEPT_256_HPP +# +# define BOOST_PP_INTERCEPT_0 +# define BOOST_PP_INTERCEPT_1 +# define BOOST_PP_INTERCEPT_2 +# define BOOST_PP_INTERCEPT_3 +# define BOOST_PP_INTERCEPT_4 +# define BOOST_PP_INTERCEPT_5 +# define BOOST_PP_INTERCEPT_6 +# define BOOST_PP_INTERCEPT_7 +# define BOOST_PP_INTERCEPT_8 +# define BOOST_PP_INTERCEPT_9 +# define BOOST_PP_INTERCEPT_10 +# define BOOST_PP_INTERCEPT_11 +# define BOOST_PP_INTERCEPT_12 +# define BOOST_PP_INTERCEPT_13 +# define BOOST_PP_INTERCEPT_14 +# define BOOST_PP_INTERCEPT_15 +# define BOOST_PP_INTERCEPT_16 +# define BOOST_PP_INTERCEPT_17 +# define BOOST_PP_INTERCEPT_18 +# define BOOST_PP_INTERCEPT_19 +# define BOOST_PP_INTERCEPT_20 +# define BOOST_PP_INTERCEPT_21 +# define BOOST_PP_INTERCEPT_22 +# define BOOST_PP_INTERCEPT_23 +# define BOOST_PP_INTERCEPT_24 +# define BOOST_PP_INTERCEPT_25 +# define BOOST_PP_INTERCEPT_26 +# define BOOST_PP_INTERCEPT_27 +# define BOOST_PP_INTERCEPT_28 +# define BOOST_PP_INTERCEPT_29 +# define BOOST_PP_INTERCEPT_30 +# define BOOST_PP_INTERCEPT_31 +# define BOOST_PP_INTERCEPT_32 +# define BOOST_PP_INTERCEPT_33 +# define BOOST_PP_INTERCEPT_34 +# define BOOST_PP_INTERCEPT_35 +# define BOOST_PP_INTERCEPT_36 +# define BOOST_PP_INTERCEPT_37 +# define BOOST_PP_INTERCEPT_38 +# define BOOST_PP_INTERCEPT_39 +# define BOOST_PP_INTERCEPT_40 +# define BOOST_PP_INTERCEPT_41 +# define BOOST_PP_INTERCEPT_42 +# define BOOST_PP_INTERCEPT_43 +# define BOOST_PP_INTERCEPT_44 +# define BOOST_PP_INTERCEPT_45 +# define BOOST_PP_INTERCEPT_46 +# define BOOST_PP_INTERCEPT_47 +# define BOOST_PP_INTERCEPT_48 +# define BOOST_PP_INTERCEPT_49 +# define BOOST_PP_INTERCEPT_50 +# define BOOST_PP_INTERCEPT_51 +# define BOOST_PP_INTERCEPT_52 +# define BOOST_PP_INTERCEPT_53 +# define BOOST_PP_INTERCEPT_54 +# define BOOST_PP_INTERCEPT_55 +# define BOOST_PP_INTERCEPT_56 +# define BOOST_PP_INTERCEPT_57 +# define BOOST_PP_INTERCEPT_58 +# define BOOST_PP_INTERCEPT_59 +# define BOOST_PP_INTERCEPT_60 +# define BOOST_PP_INTERCEPT_61 +# define BOOST_PP_INTERCEPT_62 +# define BOOST_PP_INTERCEPT_63 +# define BOOST_PP_INTERCEPT_64 +# define BOOST_PP_INTERCEPT_65 +# define BOOST_PP_INTERCEPT_66 +# define BOOST_PP_INTERCEPT_67 +# define BOOST_PP_INTERCEPT_68 +# define BOOST_PP_INTERCEPT_69 +# define BOOST_PP_INTERCEPT_70 +# define BOOST_PP_INTERCEPT_71 +# define BOOST_PP_INTERCEPT_72 +# define BOOST_PP_INTERCEPT_73 +# define BOOST_PP_INTERCEPT_74 +# define BOOST_PP_INTERCEPT_75 +# define BOOST_PP_INTERCEPT_76 +# define BOOST_PP_INTERCEPT_77 +# define BOOST_PP_INTERCEPT_78 +# define BOOST_PP_INTERCEPT_79 +# define BOOST_PP_INTERCEPT_80 +# define BOOST_PP_INTERCEPT_81 +# define BOOST_PP_INTERCEPT_82 +# define BOOST_PP_INTERCEPT_83 +# define BOOST_PP_INTERCEPT_84 +# define BOOST_PP_INTERCEPT_85 +# define BOOST_PP_INTERCEPT_86 +# define BOOST_PP_INTERCEPT_87 +# define BOOST_PP_INTERCEPT_88 +# define BOOST_PP_INTERCEPT_89 +# define BOOST_PP_INTERCEPT_90 +# define BOOST_PP_INTERCEPT_91 +# define BOOST_PP_INTERCEPT_92 +# define BOOST_PP_INTERCEPT_93 +# define BOOST_PP_INTERCEPT_94 +# define BOOST_PP_INTERCEPT_95 +# define BOOST_PP_INTERCEPT_96 +# define BOOST_PP_INTERCEPT_97 +# define BOOST_PP_INTERCEPT_98 +# define BOOST_PP_INTERCEPT_99 +# define BOOST_PP_INTERCEPT_100 +# define BOOST_PP_INTERCEPT_101 +# define BOOST_PP_INTERCEPT_102 +# define BOOST_PP_INTERCEPT_103 +# define BOOST_PP_INTERCEPT_104 +# define BOOST_PP_INTERCEPT_105 +# define BOOST_PP_INTERCEPT_106 +# define BOOST_PP_INTERCEPT_107 +# define BOOST_PP_INTERCEPT_108 +# define BOOST_PP_INTERCEPT_109 +# define BOOST_PP_INTERCEPT_110 +# define BOOST_PP_INTERCEPT_111 +# define BOOST_PP_INTERCEPT_112 +# define BOOST_PP_INTERCEPT_113 +# define BOOST_PP_INTERCEPT_114 +# define BOOST_PP_INTERCEPT_115 +# define BOOST_PP_INTERCEPT_116 +# define BOOST_PP_INTERCEPT_117 +# define BOOST_PP_INTERCEPT_118 +# define BOOST_PP_INTERCEPT_119 +# define BOOST_PP_INTERCEPT_120 +# define BOOST_PP_INTERCEPT_121 +# define BOOST_PP_INTERCEPT_122 +# define BOOST_PP_INTERCEPT_123 +# define BOOST_PP_INTERCEPT_124 +# define BOOST_PP_INTERCEPT_125 +# define BOOST_PP_INTERCEPT_126 +# define BOOST_PP_INTERCEPT_127 +# define BOOST_PP_INTERCEPT_128 +# define BOOST_PP_INTERCEPT_129 +# define BOOST_PP_INTERCEPT_130 +# define BOOST_PP_INTERCEPT_131 +# define BOOST_PP_INTERCEPT_132 +# define BOOST_PP_INTERCEPT_133 +# define BOOST_PP_INTERCEPT_134 +# define BOOST_PP_INTERCEPT_135 +# define BOOST_PP_INTERCEPT_136 +# define BOOST_PP_INTERCEPT_137 +# define BOOST_PP_INTERCEPT_138 +# define BOOST_PP_INTERCEPT_139 +# define BOOST_PP_INTERCEPT_140 +# define BOOST_PP_INTERCEPT_141 +# define BOOST_PP_INTERCEPT_142 +# define BOOST_PP_INTERCEPT_143 +# define BOOST_PP_INTERCEPT_144 +# define BOOST_PP_INTERCEPT_145 +# define BOOST_PP_INTERCEPT_146 +# define BOOST_PP_INTERCEPT_147 +# define BOOST_PP_INTERCEPT_148 +# define BOOST_PP_INTERCEPT_149 +# define BOOST_PP_INTERCEPT_150 +# define BOOST_PP_INTERCEPT_151 +# define BOOST_PP_INTERCEPT_152 +# define BOOST_PP_INTERCEPT_153 +# define BOOST_PP_INTERCEPT_154 +# define BOOST_PP_INTERCEPT_155 +# define BOOST_PP_INTERCEPT_156 +# define BOOST_PP_INTERCEPT_157 +# define BOOST_PP_INTERCEPT_158 +# define BOOST_PP_INTERCEPT_159 +# define BOOST_PP_INTERCEPT_160 +# define BOOST_PP_INTERCEPT_161 +# define BOOST_PP_INTERCEPT_162 +# define BOOST_PP_INTERCEPT_163 +# define BOOST_PP_INTERCEPT_164 +# define BOOST_PP_INTERCEPT_165 +# define BOOST_PP_INTERCEPT_166 +# define BOOST_PP_INTERCEPT_167 +# define BOOST_PP_INTERCEPT_168 +# define BOOST_PP_INTERCEPT_169 +# define BOOST_PP_INTERCEPT_170 +# define BOOST_PP_INTERCEPT_171 +# define BOOST_PP_INTERCEPT_172 +# define BOOST_PP_INTERCEPT_173 +# define BOOST_PP_INTERCEPT_174 +# define BOOST_PP_INTERCEPT_175 +# define BOOST_PP_INTERCEPT_176 +# define BOOST_PP_INTERCEPT_177 +# define BOOST_PP_INTERCEPT_178 +# define BOOST_PP_INTERCEPT_179 +# define BOOST_PP_INTERCEPT_180 +# define BOOST_PP_INTERCEPT_181 +# define BOOST_PP_INTERCEPT_182 +# define BOOST_PP_INTERCEPT_183 +# define BOOST_PP_INTERCEPT_184 +# define BOOST_PP_INTERCEPT_185 +# define BOOST_PP_INTERCEPT_186 +# define BOOST_PP_INTERCEPT_187 +# define BOOST_PP_INTERCEPT_188 +# define BOOST_PP_INTERCEPT_189 +# define BOOST_PP_INTERCEPT_190 +# define BOOST_PP_INTERCEPT_191 +# define BOOST_PP_INTERCEPT_192 +# define BOOST_PP_INTERCEPT_193 +# define BOOST_PP_INTERCEPT_194 +# define BOOST_PP_INTERCEPT_195 +# define BOOST_PP_INTERCEPT_196 +# define BOOST_PP_INTERCEPT_197 +# define BOOST_PP_INTERCEPT_198 +# define BOOST_PP_INTERCEPT_199 +# define BOOST_PP_INTERCEPT_200 +# define BOOST_PP_INTERCEPT_201 +# define BOOST_PP_INTERCEPT_202 +# define BOOST_PP_INTERCEPT_203 +# define BOOST_PP_INTERCEPT_204 +# define BOOST_PP_INTERCEPT_205 +# define BOOST_PP_INTERCEPT_206 +# define BOOST_PP_INTERCEPT_207 +# define BOOST_PP_INTERCEPT_208 +# define BOOST_PP_INTERCEPT_209 +# define BOOST_PP_INTERCEPT_210 +# define BOOST_PP_INTERCEPT_211 +# define BOOST_PP_INTERCEPT_212 +# define BOOST_PP_INTERCEPT_213 +# define BOOST_PP_INTERCEPT_214 +# define BOOST_PP_INTERCEPT_215 +# define BOOST_PP_INTERCEPT_216 +# define BOOST_PP_INTERCEPT_217 +# define BOOST_PP_INTERCEPT_218 +# define BOOST_PP_INTERCEPT_219 +# define BOOST_PP_INTERCEPT_220 +# define BOOST_PP_INTERCEPT_221 +# define BOOST_PP_INTERCEPT_222 +# define BOOST_PP_INTERCEPT_223 +# define BOOST_PP_INTERCEPT_224 +# define BOOST_PP_INTERCEPT_225 +# define BOOST_PP_INTERCEPT_226 +# define BOOST_PP_INTERCEPT_227 +# define BOOST_PP_INTERCEPT_228 +# define BOOST_PP_INTERCEPT_229 +# define BOOST_PP_INTERCEPT_230 +# define BOOST_PP_INTERCEPT_231 +# define BOOST_PP_INTERCEPT_232 +# define BOOST_PP_INTERCEPT_233 +# define BOOST_PP_INTERCEPT_234 +# define BOOST_PP_INTERCEPT_235 +# define BOOST_PP_INTERCEPT_236 +# define BOOST_PP_INTERCEPT_237 +# define BOOST_PP_INTERCEPT_238 +# define BOOST_PP_INTERCEPT_239 +# define BOOST_PP_INTERCEPT_240 +# define BOOST_PP_INTERCEPT_241 +# define BOOST_PP_INTERCEPT_242 +# define BOOST_PP_INTERCEPT_243 +# define BOOST_PP_INTERCEPT_244 +# define BOOST_PP_INTERCEPT_245 +# define BOOST_PP_INTERCEPT_246 +# define BOOST_PP_INTERCEPT_247 +# define BOOST_PP_INTERCEPT_248 +# define BOOST_PP_INTERCEPT_249 +# define BOOST_PP_INTERCEPT_250 +# define BOOST_PP_INTERCEPT_251 +# define BOOST_PP_INTERCEPT_252 +# define BOOST_PP_INTERCEPT_253 +# define BOOST_PP_INTERCEPT_254 +# define BOOST_PP_INTERCEPT_255 +# define BOOST_PP_INTERCEPT_256 +# +# endif diff --git a/boost/preprocessor/facilities/limits/intercept_512.hpp b/boost/preprocessor/facilities/limits/intercept_512.hpp new file mode 100644 index 00000000..856ddf25 --- /dev/null +++ b/boost/preprocessor/facilities/limits/intercept_512.hpp @@ -0,0 +1,274 @@ +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * 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) +# * * +# ************************************************************************** */ +# +# /* Revised by Edward Diener (2020) */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_FACILITIES_INTERCEPT_512_HPP +# define BOOST_PREPROCESSOR_FACILITIES_INTERCEPT_512_HPP +# +# define BOOST_PP_INTERCEPT_257 +# define BOOST_PP_INTERCEPT_258 +# define BOOST_PP_INTERCEPT_259 +# define BOOST_PP_INTERCEPT_260 +# define BOOST_PP_INTERCEPT_261 +# define BOOST_PP_INTERCEPT_262 +# define BOOST_PP_INTERCEPT_263 +# define BOOST_PP_INTERCEPT_264 +# define BOOST_PP_INTERCEPT_265 +# define BOOST_PP_INTERCEPT_266 +# define BOOST_PP_INTERCEPT_267 +# define BOOST_PP_INTERCEPT_268 +# define BOOST_PP_INTERCEPT_269 +# define BOOST_PP_INTERCEPT_270 +# define BOOST_PP_INTERCEPT_271 +# define BOOST_PP_INTERCEPT_272 +# define BOOST_PP_INTERCEPT_273 +# define BOOST_PP_INTERCEPT_274 +# define BOOST_PP_INTERCEPT_275 +# define BOOST_PP_INTERCEPT_276 +# define BOOST_PP_INTERCEPT_277 +# define BOOST_PP_INTERCEPT_278 +# define BOOST_PP_INTERCEPT_279 +# define BOOST_PP_INTERCEPT_280 +# define BOOST_PP_INTERCEPT_281 +# define BOOST_PP_INTERCEPT_282 +# define BOOST_PP_INTERCEPT_283 +# define BOOST_PP_INTERCEPT_284 +# define BOOST_PP_INTERCEPT_285 +# define BOOST_PP_INTERCEPT_286 +# define BOOST_PP_INTERCEPT_287 +# define BOOST_PP_INTERCEPT_288 +# define BOOST_PP_INTERCEPT_289 +# define BOOST_PP_INTERCEPT_290 +# define BOOST_PP_INTERCEPT_291 +# define BOOST_PP_INTERCEPT_292 +# define BOOST_PP_INTERCEPT_293 +# define BOOST_PP_INTERCEPT_294 +# define BOOST_PP_INTERCEPT_295 +# define BOOST_PP_INTERCEPT_296 +# define BOOST_PP_INTERCEPT_297 +# define BOOST_PP_INTERCEPT_298 +# define BOOST_PP_INTERCEPT_299 +# define BOOST_PP_INTERCEPT_300 +# define BOOST_PP_INTERCEPT_301 +# define BOOST_PP_INTERCEPT_302 +# define BOOST_PP_INTERCEPT_303 +# define BOOST_PP_INTERCEPT_304 +# define BOOST_PP_INTERCEPT_305 +# define BOOST_PP_INTERCEPT_306 +# define BOOST_PP_INTERCEPT_307 +# define BOOST_PP_INTERCEPT_308 +# define BOOST_PP_INTERCEPT_309 +# define BOOST_PP_INTERCEPT_310 +# define BOOST_PP_INTERCEPT_311 +# define BOOST_PP_INTERCEPT_312 +# define BOOST_PP_INTERCEPT_313 +# define BOOST_PP_INTERCEPT_314 +# define BOOST_PP_INTERCEPT_315 +# define BOOST_PP_INTERCEPT_316 +# define BOOST_PP_INTERCEPT_317 +# define BOOST_PP_INTERCEPT_318 +# define BOOST_PP_INTERCEPT_319 +# define BOOST_PP_INTERCEPT_320 +# define BOOST_PP_INTERCEPT_321 +# define BOOST_PP_INTERCEPT_322 +# define BOOST_PP_INTERCEPT_323 +# define BOOST_PP_INTERCEPT_324 +# define BOOST_PP_INTERCEPT_325 +# define BOOST_PP_INTERCEPT_326 +# define BOOST_PP_INTERCEPT_327 +# define BOOST_PP_INTERCEPT_328 +# define BOOST_PP_INTERCEPT_329 +# define BOOST_PP_INTERCEPT_330 +# define BOOST_PP_INTERCEPT_331 +# define BOOST_PP_INTERCEPT_332 +# define BOOST_PP_INTERCEPT_333 +# define BOOST_PP_INTERCEPT_334 +# define BOOST_PP_INTERCEPT_335 +# define BOOST_PP_INTERCEPT_336 +# define BOOST_PP_INTERCEPT_337 +# define BOOST_PP_INTERCEPT_338 +# define BOOST_PP_INTERCEPT_339 +# define BOOST_PP_INTERCEPT_340 +# define BOOST_PP_INTERCEPT_341 +# define BOOST_PP_INTERCEPT_342 +# define BOOST_PP_INTERCEPT_343 +# define BOOST_PP_INTERCEPT_344 +# define BOOST_PP_INTERCEPT_345 +# define BOOST_PP_INTERCEPT_346 +# define BOOST_PP_INTERCEPT_347 +# define BOOST_PP_INTERCEPT_348 +# define BOOST_PP_INTERCEPT_349 +# define BOOST_PP_INTERCEPT_350 +# define BOOST_PP_INTERCEPT_351 +# define BOOST_PP_INTERCEPT_352 +# define BOOST_PP_INTERCEPT_353 +# define BOOST_PP_INTERCEPT_354 +# define BOOST_PP_INTERCEPT_355 +# define BOOST_PP_INTERCEPT_356 +# define BOOST_PP_INTERCEPT_357 +# define BOOST_PP_INTERCEPT_358 +# define BOOST_PP_INTERCEPT_359 +# define BOOST_PP_INTERCEPT_360 +# define BOOST_PP_INTERCEPT_361 +# define BOOST_PP_INTERCEPT_362 +# define BOOST_PP_INTERCEPT_363 +# define BOOST_PP_INTERCEPT_364 +# define BOOST_PP_INTERCEPT_365 +# define BOOST_PP_INTERCEPT_366 +# define BOOST_PP_INTERCEPT_367 +# define BOOST_PP_INTERCEPT_368 +# define BOOST_PP_INTERCEPT_369 +# define BOOST_PP_INTERCEPT_370 +# define BOOST_PP_INTERCEPT_371 +# define BOOST_PP_INTERCEPT_372 +# define BOOST_PP_INTERCEPT_373 +# define BOOST_PP_INTERCEPT_374 +# define BOOST_PP_INTERCEPT_375 +# define BOOST_PP_INTERCEPT_376 +# define BOOST_PP_INTERCEPT_377 +# define BOOST_PP_INTERCEPT_378 +# define BOOST_PP_INTERCEPT_379 +# define BOOST_PP_INTERCEPT_380 +# define BOOST_PP_INTERCEPT_381 +# define BOOST_PP_INTERCEPT_382 +# define BOOST_PP_INTERCEPT_383 +# define BOOST_PP_INTERCEPT_384 +# define BOOST_PP_INTERCEPT_385 +# define BOOST_PP_INTERCEPT_386 +# define BOOST_PP_INTERCEPT_387 +# define BOOST_PP_INTERCEPT_388 +# define BOOST_PP_INTERCEPT_389 +# define BOOST_PP_INTERCEPT_390 +# define BOOST_PP_INTERCEPT_391 +# define BOOST_PP_INTERCEPT_392 +# define BOOST_PP_INTERCEPT_393 +# define BOOST_PP_INTERCEPT_394 +# define BOOST_PP_INTERCEPT_395 +# define BOOST_PP_INTERCEPT_396 +# define BOOST_PP_INTERCEPT_397 +# define BOOST_PP_INTERCEPT_398 +# define BOOST_PP_INTERCEPT_399 +# define BOOST_PP_INTERCEPT_400 +# define BOOST_PP_INTERCEPT_401 +# define BOOST_PP_INTERCEPT_402 +# define BOOST_PP_INTERCEPT_403 +# define BOOST_PP_INTERCEPT_404 +# define BOOST_PP_INTERCEPT_405 +# define BOOST_PP_INTERCEPT_406 +# define BOOST_PP_INTERCEPT_407 +# define BOOST_PP_INTERCEPT_408 +# define BOOST_PP_INTERCEPT_409 +# define BOOST_PP_INTERCEPT_410 +# define BOOST_PP_INTERCEPT_411 +# define BOOST_PP_INTERCEPT_412 +# define BOOST_PP_INTERCEPT_413 +# define BOOST_PP_INTERCEPT_414 +# define BOOST_PP_INTERCEPT_415 +# define BOOST_PP_INTERCEPT_416 +# define BOOST_PP_INTERCEPT_417 +# define BOOST_PP_INTERCEPT_418 +# define BOOST_PP_INTERCEPT_419 +# define BOOST_PP_INTERCEPT_420 +# define BOOST_PP_INTERCEPT_421 +# define BOOST_PP_INTERCEPT_422 +# define BOOST_PP_INTERCEPT_423 +# define BOOST_PP_INTERCEPT_424 +# define BOOST_PP_INTERCEPT_425 +# define BOOST_PP_INTERCEPT_426 +# define BOOST_PP_INTERCEPT_427 +# define BOOST_PP_INTERCEPT_428 +# define BOOST_PP_INTERCEPT_429 +# define BOOST_PP_INTERCEPT_430 +# define BOOST_PP_INTERCEPT_431 +# define BOOST_PP_INTERCEPT_432 +# define BOOST_PP_INTERCEPT_433 +# define BOOST_PP_INTERCEPT_434 +# define BOOST_PP_INTERCEPT_435 +# define BOOST_PP_INTERCEPT_436 +# define BOOST_PP_INTERCEPT_437 +# define BOOST_PP_INTERCEPT_438 +# define BOOST_PP_INTERCEPT_439 +# define BOOST_PP_INTERCEPT_440 +# define BOOST_PP_INTERCEPT_441 +# define BOOST_PP_INTERCEPT_442 +# define BOOST_PP_INTERCEPT_443 +# define BOOST_PP_INTERCEPT_444 +# define BOOST_PP_INTERCEPT_445 +# define BOOST_PP_INTERCEPT_446 +# define BOOST_PP_INTERCEPT_447 +# define BOOST_PP_INTERCEPT_448 +# define BOOST_PP_INTERCEPT_449 +# define BOOST_PP_INTERCEPT_450 +# define BOOST_PP_INTERCEPT_451 +# define BOOST_PP_INTERCEPT_452 +# define BOOST_PP_INTERCEPT_453 +# define BOOST_PP_INTERCEPT_454 +# define BOOST_PP_INTERCEPT_455 +# define BOOST_PP_INTERCEPT_456 +# define BOOST_PP_INTERCEPT_457 +# define BOOST_PP_INTERCEPT_458 +# define BOOST_PP_INTERCEPT_459 +# define BOOST_PP_INTERCEPT_460 +# define BOOST_PP_INTERCEPT_461 +# define BOOST_PP_INTERCEPT_462 +# define BOOST_PP_INTERCEPT_463 +# define BOOST_PP_INTERCEPT_464 +# define BOOST_PP_INTERCEPT_465 +# define BOOST_PP_INTERCEPT_466 +# define BOOST_PP_INTERCEPT_467 +# define BOOST_PP_INTERCEPT_468 +# define BOOST_PP_INTERCEPT_469 +# define BOOST_PP_INTERCEPT_470 +# define BOOST_PP_INTERCEPT_471 +# define BOOST_PP_INTERCEPT_472 +# define BOOST_PP_INTERCEPT_473 +# define BOOST_PP_INTERCEPT_474 +# define BOOST_PP_INTERCEPT_475 +# define BOOST_PP_INTERCEPT_476 +# define BOOST_PP_INTERCEPT_477 +# define BOOST_PP_INTERCEPT_478 +# define BOOST_PP_INTERCEPT_479 +# define BOOST_PP_INTERCEPT_480 +# define BOOST_PP_INTERCEPT_481 +# define BOOST_PP_INTERCEPT_482 +# define BOOST_PP_INTERCEPT_483 +# define BOOST_PP_INTERCEPT_484 +# define BOOST_PP_INTERCEPT_485 +# define BOOST_PP_INTERCEPT_486 +# define BOOST_PP_INTERCEPT_487 +# define BOOST_PP_INTERCEPT_488 +# define BOOST_PP_INTERCEPT_489 +# define BOOST_PP_INTERCEPT_490 +# define BOOST_PP_INTERCEPT_491 +# define BOOST_PP_INTERCEPT_492 +# define BOOST_PP_INTERCEPT_493 +# define BOOST_PP_INTERCEPT_494 +# define BOOST_PP_INTERCEPT_495 +# define BOOST_PP_INTERCEPT_496 +# define BOOST_PP_INTERCEPT_497 +# define BOOST_PP_INTERCEPT_498 +# define BOOST_PP_INTERCEPT_499 +# define BOOST_PP_INTERCEPT_500 +# define BOOST_PP_INTERCEPT_501 +# define BOOST_PP_INTERCEPT_502 +# define BOOST_PP_INTERCEPT_503 +# define BOOST_PP_INTERCEPT_504 +# define BOOST_PP_INTERCEPT_505 +# define BOOST_PP_INTERCEPT_506 +# define BOOST_PP_INTERCEPT_507 +# define BOOST_PP_INTERCEPT_508 +# define BOOST_PP_INTERCEPT_509 +# define BOOST_PP_INTERCEPT_510 +# define BOOST_PP_INTERCEPT_511 +# define BOOST_PP_INTERCEPT_512 +# +# endif diff --git a/boost/preprocessor/list/for_each.hpp b/boost/preprocessor/list/for_each.hpp new file mode 100644 index 00000000..dd04eaa5 --- /dev/null +++ b/boost/preprocessor/list/for_each.hpp @@ -0,0 +1,49 @@ +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * 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) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_LIST_FOR_EACH_HPP +# define BOOST_PREPROCESSOR_LIST_FOR_EACH_HPP +# +# include +# include +# include +# include +# +# /* BOOST_PP_LIST_FOR_EACH */ +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() +# define BOOST_PP_LIST_FOR_EACH(macro, data, list) BOOST_PP_LIST_FOR_EACH_I(BOOST_PP_LIST_FOR_EACH_O, (macro, data), list) +# else +# define BOOST_PP_LIST_FOR_EACH(macro, data, list) BOOST_PP_LIST_FOR_EACH_X(macro, data, list) +# define BOOST_PP_LIST_FOR_EACH_X(macro, data, list) BOOST_PP_LIST_FOR_EACH_I(BOOST_PP_LIST_FOR_EACH_O, (macro, data), list) +# endif +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() +# define BOOST_PP_LIST_FOR_EACH_O(r, md, i, elem) BOOST_PP_LIST_FOR_EACH_O_D(r, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md), elem) +# else +# define BOOST_PP_LIST_FOR_EACH_O(r, md, i, elem) BOOST_PP_LIST_FOR_EACH_O_I(r, BOOST_PP_TUPLE_REM_2 md, elem) +# define BOOST_PP_LIST_FOR_EACH_O_I(r, im, elem) BOOST_PP_LIST_FOR_EACH_O_D(r, im, elem) +# endif +# +# define BOOST_PP_LIST_FOR_EACH_O_D(r, m, d, elem) m(r, d, elem) +# +# /* BOOST_PP_LIST_FOR_EACH_R */ +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() +# define BOOST_PP_LIST_FOR_EACH_R(r, macro, data, list) BOOST_PP_LIST_FOR_EACH_I_R(r, BOOST_PP_LIST_FOR_EACH_O, (macro, data), list) +# else +# define BOOST_PP_LIST_FOR_EACH_R(r, macro, data, list) BOOST_PP_LIST_FOR_EACH_R_X(r, macro, data, list) +# define BOOST_PP_LIST_FOR_EACH_R_X(r, macro, data, list) BOOST_PP_LIST_FOR_EACH_I_R(r, BOOST_PP_LIST_FOR_EACH_O, (macro, data), list) +# endif +# +# endif diff --git a/boost/preprocessor/punctuation/paren.hpp b/boost/preprocessor/punctuation/paren.hpp new file mode 100644 index 00000000..28c18cb8 --- /dev/null +++ b/boost/preprocessor/punctuation/paren.hpp @@ -0,0 +1,23 @@ +# /* ************************************************************************** +# * * +# * (C) Copyright Paul Mensonides 2002. +# * 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) +# * * +# ************************************************************************** */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_PUNCTUATION_PAREN_HPP +# define BOOST_PREPROCESSOR_PUNCTUATION_PAREN_HPP +# +# /* BOOST_PP_LPAREN */ +# +# define BOOST_PP_LPAREN() ( +# +# /* BOOST_PP_RPAREN */ +# +# define BOOST_PP_RPAREN() ) +# +# endif diff --git a/boost/preprocessor/repetition/enum.hpp b/boost/preprocessor/repetition/enum.hpp new file mode 100644 index 00000000..0198cd9b --- /dev/null +++ b/boost/preprocessor/repetition/enum.hpp @@ -0,0 +1,66 @@ +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * 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) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_HPP +# define BOOST_PREPROCESSOR_REPETITION_ENUM_HPP +# +# include +# include +# include +# include +# include +# include +# include +# include +# +# /* BOOST_PP_ENUM */ +# +# if 0 +# define BOOST_PP_ENUM(count, macro, data) +# endif +# +# define BOOST_PP_ENUM BOOST_PP_CAT(BOOST_PP_ENUM_, BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4)) +# +# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG() +# define BOOST_PP_ENUM_1(c, m, d) BOOST_PP_REPEAT_1(c, BOOST_PP_ENUM_M_1, (m, d)) +# define BOOST_PP_ENUM_2(c, m, d) BOOST_PP_REPEAT_2(c, BOOST_PP_ENUM_M_2, (m, d)) +# define BOOST_PP_ENUM_3(c, m, d) BOOST_PP_REPEAT_3(c, BOOST_PP_ENUM_M_3, (m, d)) +# else +# define BOOST_PP_ENUM_1(c, m, d) BOOST_PP_ENUM_1_I(c, m, d) +# define BOOST_PP_ENUM_2(c, m, d) BOOST_PP_ENUM_2_I(c, m, d) +# define BOOST_PP_ENUM_3(c, m, d) BOOST_PP_ENUM_3_I(c, m, d) +# define BOOST_PP_ENUM_1_I(c, m, d) BOOST_PP_REPEAT_1(c, BOOST_PP_ENUM_M_1, (m, d)) +# define BOOST_PP_ENUM_2_I(c, m, d) BOOST_PP_REPEAT_2(c, BOOST_PP_ENUM_M_2, (m, d)) +# define BOOST_PP_ENUM_3_I(c, m, d) BOOST_PP_REPEAT_3(c, BOOST_PP_ENUM_M_3, (m, d)) +# endif +# +# define BOOST_PP_ENUM_4(c, m, d) BOOST_PP_ERROR(0x0003) +# +# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT() +# define BOOST_PP_ENUM_M_1(z, n, md) BOOST_PP_ENUM_M_1_IM(z, n, BOOST_PP_TUPLE_REM_2 md) +# define BOOST_PP_ENUM_M_2(z, n, md) BOOST_PP_ENUM_M_2_IM(z, n, BOOST_PP_TUPLE_REM_2 md) +# define BOOST_PP_ENUM_M_3(z, n, md) BOOST_PP_ENUM_M_3_IM(z, n, BOOST_PP_TUPLE_REM_2 md) +# define BOOST_PP_ENUM_M_1_IM(z, n, im) BOOST_PP_ENUM_M_1_I(z, n, im) +# define BOOST_PP_ENUM_M_2_IM(z, n, im) BOOST_PP_ENUM_M_2_I(z, n, im) +# define BOOST_PP_ENUM_M_3_IM(z, n, im) BOOST_PP_ENUM_M_3_I(z, n, im) +# else +# define BOOST_PP_ENUM_M_1(z, n, md) BOOST_PP_ENUM_M_1_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md)) +# define BOOST_PP_ENUM_M_2(z, n, md) BOOST_PP_ENUM_M_2_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md)) +# define BOOST_PP_ENUM_M_3(z, n, md) BOOST_PP_ENUM_M_3_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md)) +# endif +# +# define BOOST_PP_ENUM_M_1_I(z, n, m, d) BOOST_PP_COMMA_IF(n) m(z, n, d) +# define BOOST_PP_ENUM_M_2_I(z, n, m, d) BOOST_PP_COMMA_IF(n) m(z, n, d) +# define BOOST_PP_ENUM_M_3_I(z, n, m, d) BOOST_PP_COMMA_IF(n) m(z, n, d) +# +# endif diff --git a/boost/preprocessor/repetition/enum_params_with_a_default.hpp b/boost/preprocessor/repetition/enum_params_with_a_default.hpp new file mode 100644 index 00000000..7496df62 --- /dev/null +++ b/boost/preprocessor/repetition/enum_params_with_a_default.hpp @@ -0,0 +1,25 @@ +# /* Copyright (C) 2001 +# * Housemarque Oy +# * http://www.housemarque.com +# * +# * 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) +# */ +# +# /* Revised by Paul Mensonides (2002) */ +# +# /* See http://www.boost.org for most recent version. */ +# +# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_PARAMS_WITH_A_DEFAULT_HPP +# define BOOST_PREPROCESSOR_REPETITION_ENUM_PARAMS_WITH_A_DEFAULT_HPP +# +# include +# include +# include +# +# /* BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT */ +# +# define BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(count, param, def) BOOST_PP_ENUM_BINARY_PARAMS(count, param, = def BOOST_PP_INTERCEPT) +# +# endif diff --git a/boost/ref.hpp b/boost/ref.hpp new file mode 100644 index 00000000..17b56ec0 --- /dev/null +++ b/boost/ref.hpp @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014 Glen Fernandes + * + * 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) + */ + +#ifndef BOOST_REF_HPP +#define BOOST_REF_HPP + +// The header file at this path is deprecated; +// use boost/core/ref.hpp instead. + +#include + +#endif diff --git a/boost/regex.hpp b/boost/regex.hpp new file mode 100644 index 00000000..b0c8bf13 --- /dev/null +++ b/boost/regex.hpp @@ -0,0 +1,41 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org/libs/regex for documentation. + * FILE regex.cpp + * VERSION see + * DESCRIPTION: Declares boost::basic_regex<> and associated + * functions and classes. This header is the main + * entry point for the template regex code. + */ + + +/* start with C compatibility API */ + +#ifndef BOOST_RE_REGEX_HPP +#define BOOST_RE_REGEX_HPP + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif + +#ifdef BOOST_REGEX_CXX03 +#include +#else +#include +#endif + +#endif // include + + + + diff --git a/boost/regex/config.hpp b/boost/regex/config.hpp new file mode 100644 index 00000000..bed485fa --- /dev/null +++ b/boost/regex/config.hpp @@ -0,0 +1,480 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE config.hpp + * VERSION see + * DESCRIPTION: regex extended config setup. + */ + +#ifndef BOOST_REGEX_CONFIG_HPP +#define BOOST_REGEX_CONFIG_HPP + +#if !((__cplusplus >= 201103L) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(BOOST_REGEX_CXX03)) +# define BOOST_REGEX_CXX03 +#endif + +#if defined(BOOST_REGEX_RECURSIVE) && !defined(BOOST_REGEX_CXX03) +# define BOOST_REGEX_CXX03 +#endif + +#if defined(__has_include) +#if !defined(BOOST_REGEX_STANDALONE) && !__has_include() +#define BOOST_REGEX_STANDALONE +#endif +#endif + +/* + * Borland C++ Fix/error check + * this has to go *before* we include any std lib headers: + */ +#if defined(__BORLANDC__) && !defined(__clang__) +# include +#endif +#ifndef BOOST_REGEX_STANDALONE +#include +#endif + +/************************************************************************* +* +* Asserts: +* +*************************************************************************/ + +#ifdef BOOST_REGEX_STANDALONE +#include +# define BOOST_REGEX_ASSERT(x) assert(x) +#else +#include +# define BOOST_REGEX_ASSERT(x) BOOST_ASSERT(x) +#endif + +/***************************************************************************** + * + * Include all the headers we need here: + * + ****************************************************************************/ + +#ifdef __cplusplus + +# ifndef BOOST_REGEX_USER_CONFIG +# define BOOST_REGEX_USER_CONFIG +# endif + +# include BOOST_REGEX_USER_CONFIG + +#ifndef BOOST_REGEX_STANDALONE +# include +# include +#endif + +#else + /* + * C build, + * don't include because that may + * do C++ specific things in future... + */ +# include +# include +# ifdef _MSC_VER +# define BOOST_MSVC _MSC_VER +# endif +#endif + + +/**************************************************************************** +* +* Legacy support: +* +*******************************************************************************/ + +#if defined(BOOST_NO_STD_LOCALE) || defined(BOOST_NO_CXX11_HDR_MUTEX) || defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) \ + || defined(BOOST_NO_CXX11_HDR_ATOMIC) || defined(BOOST_NO_CXX11_ALLOCATOR) || defined(BOOST_NO_CXX11_SMART_PTR) \ + || defined(BOOST_NO_CXX11_STATIC_ASSERT) || defined(BOOST_NO_NOEXCEPT) +#ifndef BOOST_REGEX_CXX03 +# define BOOST_REGEX_CXX03 +#endif +#endif + +/***************************************************************************** + * + * Boilerplate regex config options: + * + ****************************************************************************/ + +/* Obsolete macro, use BOOST_VERSION instead: */ +#define BOOST_RE_VERSION 500 + +/* fix: */ +#if defined(_UNICODE) && !defined(UNICODE) +#define UNICODE +#endif + +#define BOOST_REGEX_JOIN(X, Y) BOOST_REGEX_DO_JOIN(X, Y) +#define BOOST_REGEX_DO_JOIN(X, Y) BOOST_REGEX_DO_JOIN2(X,Y) +#define BOOST_REGEX_DO_JOIN2(X, Y) X##Y + +#ifdef BOOST_FALLTHROUGH +# define BOOST_REGEX_FALLTHROUGH BOOST_FALLTHROUGH +#else + +#if defined(__clang__) && (__cplusplus >= 201103L) && defined(__has_warning) +# if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") +# define BOOST_REGEX_FALLTHROUGH [[clang::fallthrough]] +# endif +#endif +#if !defined(BOOST_REGEX_FALLTHROUGH) && defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1800) && (__cplusplus >= 201703) +# define BOOST_REGEX_FALLTHROUGH [[fallthrough]] +#endif +#if !defined(BOOST_REGEX_FALLTHROUGH) && defined(__GNUC__) && (__GNUC__ >= 7) +# define BOOST_REGEX_FALLTHROUGH __attribute__((fallthrough)) +#endif + +#if !defined(BOOST_REGEX_FALLTHROUGH) +# define BOOST_REGEX_FALLTHROUGH +#endif +#endif + +#ifdef BOOST_NORETURN +# define BOOST_REGEX_NORETURN BOOST_NORETURN +#else +# define BOOST_REGEX_NORETURN +#endif + + +/* +* Define a macro for the namespace that details are placed in, this includes the Boost +* version number to avoid mismatched header and library versions: +*/ +#define BOOST_REGEX_DETAIL_NS BOOST_REGEX_JOIN(re_detail_, BOOST_RE_VERSION) + +/* + * Fix for gcc prior to 3.4: std::ctype doesn't allow + * masks to be combined, for example: + * std::use_facet >.is(std::ctype_base::lower|std::ctype_base::upper, L'a'); + * returns *false*. + */ +#if defined(__GLIBCPP__) && defined(BOOST_REGEX_CXX03) +# define BOOST_REGEX_BUGGY_CTYPE_FACET +#endif + +/* + * If there isn't good enough wide character support then there will + * be no wide character regular expressions: + */ +#if (defined(BOOST_NO_CWCHAR) || defined(BOOST_NO_CWCTYPE) || defined(BOOST_NO_STD_WSTRING)) +# if !defined(BOOST_NO_WREGEX) +# define BOOST_NO_WREGEX +# endif +#else +# if defined(__sgi) && (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) + /* STLPort on IRIX is misconfigured: does not compile + * as a temporary fix include instead and prevent inclusion + * of STLPort version of */ +# include +# define __STLPORT_CWCTYPE +# define _STLP_CWCTYPE +# endif + +#if defined(__cplusplus) && defined(BOOST_REGEX_CXX03) +# include +#endif + +#endif + +/* + * If Win32 support has been disabled for boost in general, then + * it is for regex in particular: + */ +#if defined(BOOST_DISABLE_WIN32) && !defined(BOOST_REGEX_NO_W32) +# define BOOST_REGEX_NO_W32 +#endif + +/* disable our own file-iterators and mapfiles if we can't + * support them: */ +#if defined(_WIN32) +# if defined(BOOST_REGEX_NO_W32) || BOOST_PLAT_WINDOWS_RUNTIME +# define BOOST_REGEX_NO_FILEITER +# endif +#else /* defined(_WIN32) */ +# if !defined(BOOST_HAS_DIRENT_H) +# define BOOST_REGEX_NO_FILEITER +# endif +#endif + +/* backwards compatibitity: */ +#if defined(BOOST_RE_NO_LIB) +# define BOOST_REGEX_NO_LIB +#endif + +#if defined(__GNUC__) && !defined(_MSC_VER) && (defined(_WIN32) || defined(__CYGWIN__)) +/* gcc on win32 has problems if you include + (sporadically generates bad code). */ +# define BOOST_REGEX_NO_W32 +#endif +#if defined(__COMO__) && !defined(BOOST_REGEX_NO_W32) && !defined(_MSC_EXTENSIONS) +# define BOOST_REGEX_NO_W32 +#endif + +#ifdef BOOST_REGEX_STANDALONE +# if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__) +# define BOOST_REGEX_MSVC _MSC_VER +#endif +#elif defined(BOOST_MSVC) +# define BOOST_REGEX_MSVC BOOST_MSVC +#endif + + +/***************************************************************************** + * + * Set up dll import/export options: + * + ****************************************************************************/ + +#if (defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(BOOST_REGEX_STATIC_LINK) && defined(BOOST_SYMBOL_IMPORT) +# if defined(BOOST_REGEX_SOURCE) +# define BOOST_REGEX_BUILD_DLL +# define BOOST_REGEX_DECL BOOST_SYMBOL_EXPORT +# else +# define BOOST_REGEX_DECL BOOST_SYMBOL_IMPORT +# endif +#else +# define BOOST_REGEX_DECL +#endif + +#ifdef BOOST_REGEX_CXX03 +#if !defined(BOOST_REGEX_NO_LIB) && !defined(BOOST_REGEX_SOURCE) && !defined(BOOST_ALL_NO_LIB) && defined(__cplusplus) +# define BOOST_LIB_NAME boost_regex +# if defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK) +# define BOOST_DYN_LINK +# endif +# ifdef BOOST_REGEX_DIAG +# define BOOST_LIB_DIAGNOSTIC +# endif +# include +#endif +#endif + +/***************************************************************************** + * + * Set up function call type: + * + ****************************************************************************/ + +#if defined(_MSC_VER) && defined(_MSC_EXTENSIONS) +#if defined(_DEBUG) || defined(__MSVC_RUNTIME_CHECKS) || defined(_MANAGED) || defined(BOOST_REGEX_NO_FASTCALL) +# define BOOST_REGEX_CALL __cdecl +#else +# define BOOST_REGEX_CALL __fastcall +#endif +# define BOOST_REGEX_CCALL __cdecl +#endif + +#if defined(__BORLANDC__) && !defined(BOOST_DISABLE_WIN32) +#if defined(__clang__) +# define BOOST_REGEX_CALL __cdecl +# define BOOST_REGEX_CCALL __cdecl +#else +# define BOOST_REGEX_CALL __fastcall +# define BOOST_REGEX_CCALL __stdcall +#endif +#endif + +#ifndef BOOST_REGEX_CALL +# define BOOST_REGEX_CALL +#endif +#ifndef BOOST_REGEX_CCALL +#define BOOST_REGEX_CCALL +#endif + +/***************************************************************************** + * + * Set up localisation model: + * + ****************************************************************************/ + +/* backwards compatibility: */ +#ifdef BOOST_RE_LOCALE_C +# define BOOST_REGEX_USE_C_LOCALE +#endif + +#ifdef BOOST_RE_LOCALE_CPP +# define BOOST_REGEX_USE_CPP_LOCALE +#endif + +#if defined(__CYGWIN__) +# define BOOST_REGEX_USE_C_LOCALE +#endif + +/* use C++ locale when targeting windows store */ +#if BOOST_PLAT_WINDOWS_RUNTIME +# define BOOST_REGEX_USE_CPP_LOCALE +# define BOOST_REGEX_NO_WIN32_LOCALE +#endif + +/* Win32 defaults to native Win32 locale: */ +#if defined(_WIN32) && \ + !defined(BOOST_REGEX_USE_WIN32_LOCALE) && \ + !defined(BOOST_REGEX_USE_C_LOCALE) && \ + !defined(BOOST_REGEX_USE_CPP_LOCALE) && \ + !defined(BOOST_REGEX_NO_W32) && \ + !defined(BOOST_REGEX_NO_WIN32_LOCALE) +# define BOOST_REGEX_USE_WIN32_LOCALE +#endif +/* otherwise use C++ locale if supported: */ +#if !defined(BOOST_REGEX_USE_WIN32_LOCALE) && !defined(BOOST_REGEX_USE_C_LOCALE) && !defined(BOOST_REGEX_USE_CPP_LOCALE) && !defined(BOOST_NO_STD_LOCALE) +# define BOOST_REGEX_USE_CPP_LOCALE +#endif +/* otherwise use C locale: */ +#if !defined(BOOST_REGEX_USE_WIN32_LOCALE) && !defined(BOOST_REGEX_USE_C_LOCALE) && !defined(BOOST_REGEX_USE_CPP_LOCALE) +# define BOOST_REGEX_USE_C_LOCALE +#endif + +#ifndef BOOST_REGEX_MAX_STATE_COUNT +# define BOOST_REGEX_MAX_STATE_COUNT 100000000 +#endif + + +/***************************************************************************** + * + * Error Handling for exception free compilers: + * + ****************************************************************************/ + +#ifdef BOOST_NO_EXCEPTIONS +/* + * If there are no exceptions then we must report critical-errors + * the only way we know how; by terminating. + */ +#include +#include +#include + +# define BOOST_REGEX_NOEH_ASSERT(x)\ +if(0 == (x))\ +{\ + std::string s("Error: critical regex++ failure in: ");\ + s.append(#x);\ + std::runtime_error e(s);\ + boost::throw_exception(e);\ +} +#else +/* + * With exceptions then error handling is taken care of and + * there is no need for these checks: + */ +# define BOOST_REGEX_NOEH_ASSERT(x) +#endif + + +/***************************************************************************** + * + * Stack protection under MS Windows: + * + ****************************************************************************/ + +#if !defined(BOOST_REGEX_NO_W32) && !defined(BOOST_REGEX_V3) +# if(defined(_WIN32) || defined(_WIN64) || defined(_WINCE)) \ + && !(defined(__GNUC__) || defined(__BORLANDC__) && defined(__clang__)) \ + && !(defined(__BORLANDC__) && (__BORLANDC__ >= 0x600)) \ + && !(defined(__MWERKS__) && (__MWERKS__ <= 0x3003)) +# define BOOST_REGEX_HAS_MS_STACK_GUARD +# endif +#elif defined(BOOST_REGEX_HAS_MS_STACK_GUARD) +# undef BOOST_REGEX_HAS_MS_STACK_GUARD +#endif + +#if defined(__cplusplus) && defined(BOOST_REGEX_HAS_MS_STACK_GUARD) + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +BOOST_REGEX_DECL void BOOST_REGEX_CALL reset_stack_guard_page(); + +} +} + +#endif + + +/***************************************************************************** + * + * Algorithm selection and configuration. + * These options are now obsolete for C++11 and later (regex v5). + * + ****************************************************************************/ + +#if !defined(BOOST_REGEX_RECURSIVE) && !defined(BOOST_REGEX_NON_RECURSIVE) +# if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && !defined(_STLP_DEBUG) && !defined(__STL_DEBUG) && !(defined(_MSC_VER) && (_MSC_VER >= 1400)) && defined(BOOST_REGEX_CXX03) +# define BOOST_REGEX_RECURSIVE +# else +# define BOOST_REGEX_NON_RECURSIVE +# endif +#endif + +#ifdef BOOST_REGEX_NON_RECURSIVE +# ifdef BOOST_REGEX_RECURSIVE +# error "Can't set both BOOST_REGEX_RECURSIVE and BOOST_REGEX_NON_RECURSIVE" +# endif +# ifndef BOOST_REGEX_BLOCKSIZE +# define BOOST_REGEX_BLOCKSIZE 4096 +# endif +# if BOOST_REGEX_BLOCKSIZE < 512 +# error "BOOST_REGEX_BLOCKSIZE must be at least 512" +# endif +# ifndef BOOST_REGEX_MAX_BLOCKS +# define BOOST_REGEX_MAX_BLOCKS 1024 +# endif +# ifdef BOOST_REGEX_HAS_MS_STACK_GUARD +# undef BOOST_REGEX_HAS_MS_STACK_GUARD +# endif +# ifndef BOOST_REGEX_MAX_CACHE_BLOCKS +# define BOOST_REGEX_MAX_CACHE_BLOCKS 16 +# endif +#endif + + +/***************************************************************************** + * + * Diagnostics: + * + ****************************************************************************/ + +#ifdef BOOST_REGEX_CONFIG_INFO +BOOST_REGEX_DECL void BOOST_REGEX_CALL print_regex_library_info(); +#endif + +#if defined(BOOST_REGEX_DIAG) +# pragma message ("BOOST_REGEX_DECL" BOOST_STRINGIZE(=BOOST_REGEX_DECL)) +# pragma message ("BOOST_REGEX_CALL" BOOST_STRINGIZE(=BOOST_REGEX_CALL)) +# pragma message ("BOOST_REGEX_CCALL" BOOST_STRINGIZE(=BOOST_REGEX_CCALL)) +#ifdef BOOST_REGEX_USE_C_LOCALE +# pragma message ("Using C locale in regex traits class") +#elif BOOST_REGEX_USE_CPP_LOCALE +# pragma message ("Using C++ locale in regex traits class") +#else +# pragma message ("Using Win32 locale in regex traits class") +#endif +#if defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK) +# pragma message ("Dynamic linking enabled") +#endif +#if defined(BOOST_REGEX_NO_LIB) || defined(BOOST_ALL_NO_LIB) +# pragma message ("Auto-linking disabled") +#endif +#ifdef BOOST_REGEX_NO_EXTERNAL_TEMPLATES +# pragma message ("Extern templates disabled") +#endif + +#endif + +#endif + diff --git a/boost/regex/config/borland.hpp b/boost/regex/config/borland.hpp new file mode 100644 index 00000000..981113e5 --- /dev/null +++ b/boost/regex/config/borland.hpp @@ -0,0 +1,72 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE boost/regex/config/borland.hpp + * VERSION see + * DESCRIPTION: regex borland-specific config setup. + */ + + +#if defined(__BORLANDC__) && !defined(__clang__) +# if (__BORLANDC__ == 0x550) || (__BORLANDC__ == 0x551) + // problems with std::basic_string and dll RTL: +# if defined(_RTLDLL) && defined(_RWSTD_COMPILE_INSTANTIATE) +# ifdef BOOST_REGEX_BUILD_DLL +# error _RWSTD_COMPILE_INSTANTIATE must not be defined when building regex++ as a DLL +# else +# pragma message("Defining _RWSTD_COMPILE_INSTANTIATE when linking to the DLL version of the RTL may produce memory corruption problems in std::basic_string, as a result of separate versions of basic_string's static data in the RTL and you're exe/dll: be warned!!") +# endif +# endif +# ifndef _RTLDLL + // this is harmless for a staic link: +# define _RWSTD_COMPILE_INSTANTIATE +# endif + // external templates cause problems for some reason: +# define BOOST_REGEX_NO_EXTERNAL_TEMPLATES +# endif +# if (__BORLANDC__ <= 0x540) && !defined(BOOST_REGEX_NO_LIB) && !defined(_NO_VCL) + // C++ Builder 4 and earlier, we can't tell whether we should be using + // the VCL runtime or not, do a static link instead: +# define BOOST_REGEX_STATIC_LINK +# endif + // + // VCL support: + // if we're building a console app then there can't be any VCL (can there?) +# if !defined(__CONSOLE__) && !defined(_NO_VCL) +# define BOOST_REGEX_USE_VCL +# endif + // + // if this isn't Win32 then don't automatically select link + // libraries: + // +# ifndef _Windows +# ifndef BOOST_REGEX_NO_LIB +# define BOOST_REGEX_NO_LIB +# endif +# ifndef BOOST_REGEX_STATIC_LINK +# define BOOST_REGEX_STATIC_LINK +# endif +# endif + +#if __BORLANDC__ < 0x600 +// +// string workarounds: +// +#include +#undef strcmp +#undef strcpy +#endif + +#endif + + diff --git a/boost/regex/config/cwchar.hpp b/boost/regex/config/cwchar.hpp new file mode 100644 index 00000000..a55089d0 --- /dev/null +++ b/boost/regex/config/cwchar.hpp @@ -0,0 +1,207 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE boost/regex/config/cwchar.hpp + * VERSION see + * DESCRIPTION: regex wide character string fixes. + */ + +#ifndef BOOST_REGEX_CONFIG_CWCHAR_HPP +#define BOOST_REGEX_CONFIG_CWCHAR_HPP + +#include +#include +#include + +#if defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER) +// apparently this is required for the RW STL on Linux: +#undef iswalnum +#undef iswalpha +#undef iswblank +#undef iswcntrl +#undef iswdigit +#undef iswgraph +#undef iswlower +#undef iswprint +#undef iswprint +#undef iswpunct +#undef iswspace +#undef iswupper +#undef iswxdigit +#undef iswctype +#undef towlower +#undef towupper +#undef towctrans +#undef wctrans +#undef wctype +#endif + +namespace std{ + +#ifndef BOOST_NO_STDC_NAMESPACE +extern "C"{ +#endif + +#ifdef iswalnum +inline int (iswalnum)(wint_t i) +{ return iswalnum(i); } +#undef iswalnum +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::iswalnum; +#endif + +#ifdef iswalpha +inline int (iswalpha)(wint_t i) +{ return iswalpha(i); } +#undef iswalpha +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::iswalpha; +#endif + +#ifdef iswcntrl +inline int (iswcntrl)(wint_t i) +{ return iswcntrl(i); } +#undef iswcntrl +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::iswcntrl; +#endif + +#ifdef iswdigit +inline int (iswdigit)(wint_t i) +{ return iswdigit(i); } +#undef iswdigit +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::iswdigit; +#endif + +#ifdef iswgraph +inline int (iswgraph)(wint_t i) +{ return iswgraph(i); } +#undef iswgraph +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::iswgraph; +#endif + +#ifdef iswlower +inline int (iswlower)(wint_t i) +{ return iswlower(i); } +#undef iswlower +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::iswlower; +#endif + +#ifdef iswprint +inline int (iswprint)(wint_t i) +{ return iswprint(i); } +#undef iswprint +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::iswprint; +#endif + +#ifdef iswpunct +inline int (iswpunct)(wint_t i) +{ return iswpunct(i); } +#undef iswpunct +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::iswpunct; +#endif + +#ifdef iswspace +inline int (iswspace)(wint_t i) +{ return iswspace(i); } +#undef iswspace +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::iswspace; +#endif + +#ifdef iswupper +inline int (iswupper)(wint_t i) +{ return iswupper(i); } +#undef iswupper +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::iswupper; +#endif + +#ifdef iswxdigit +inline int (iswxdigit)(wint_t i) +{ return iswxdigit(i); } +#undef iswxdigit +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::iswxdigit; +#endif + +#ifdef towlower +inline wint_t (towlower)(wint_t i) +{ return towlower(i); } +#undef towlower +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::towlower; +#endif + +#ifdef towupper +inline wint_t (towupper)(wint_t i) +{ return towupper(i); } +#undef towupper +#elif defined(BOOST_NO_STDC_NAMESPACE) +using :: towupper; +#endif + +#ifdef wcscmp +inline int (wcscmp)(const wchar_t *p1, const wchar_t *p2) +{ return wcscmp(p1,p2); } +#undef wcscmp +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::wcscmp; +#endif + +#ifdef wcscoll +inline int (wcscoll)(const wchar_t *p1, const wchar_t *p2) +{ return wcscoll(p1,p2); } +#undef wcscoll +#elif defined(BOOST_NO_STDC_NAMESPACE) && !defined(UNDER_CE) +using ::wcscoll; +#endif + +#ifdef wcscpy +inline wchar_t *(wcscpy)(wchar_t *p1, const wchar_t *p2) +{ return wcscpy(p1,p2); } +#undef wcscpy +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::wcscpy; +#endif + +#ifdef wcslen +inline size_t (wcslen)(const wchar_t *p) +{ return wcslen(p); } +#undef wcslen +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::wcslen; +#endif + +#ifdef wcsxfrm +size_t wcsxfrm(wchar_t *p1, const wchar_t *p2, size_t s) +{ return wcsxfrm(p1,p2,s); } +#undef wcsxfrm +#elif defined(BOOST_NO_STDC_NAMESPACE) +using ::wcsxfrm; +#endif + + +#ifndef BOOST_NO_STDC_NAMESPACE +} // extern "C" +#endif + +} // namespace std + +#endif + diff --git a/boost/regex/pattern_except.hpp b/boost/regex/pattern_except.hpp new file mode 100644 index 00000000..f2af1afe --- /dev/null +++ b/boost/regex/pattern_except.hpp @@ -0,0 +1,32 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE pattern_except.hpp + * VERSION see + * DESCRIPTION: Declares pattern-matching exception classes. + */ + +#ifndef BOOST_RE_PAT_EXCEPT_HPP +#define BOOST_RE_PAT_EXCEPT_HPP + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif + +#ifdef BOOST_REGEX_CXX03 +#include +#else +#include +#endif + +#endif diff --git a/boost/regex/pending/static_mutex.hpp b/boost/regex/pending/static_mutex.hpp new file mode 100644 index 00000000..344926f6 --- /dev/null +++ b/boost/regex/pending/static_mutex.hpp @@ -0,0 +1,182 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE static_mutex.hpp + * VERSION see + * DESCRIPTION: Declares static_mutex lock type, there are three different + * implementations: POSIX pthreads, WIN32 threads, and portable, + * these are described in more detail below. + */ + +#ifndef BOOST_REGEX_STATIC_MUTEX_HPP +#define BOOST_REGEX_STATIC_MUTEX_HPP + +#include +#include // dll import/export options. + +#ifdef BOOST_HAS_PTHREADS +#include +#endif + +#if defined(BOOST_HAS_PTHREADS) && defined(PTHREAD_MUTEX_INITIALIZER) +// +// pthreads version: +// simple wrap around a pthread_mutex_t initialized with +// PTHREAD_MUTEX_INITIALIZER. +// +namespace boost{ + +class static_mutex; + +#define BOOST_STATIC_MUTEX_INIT { PTHREAD_MUTEX_INITIALIZER, } + +class BOOST_REGEX_DECL scoped_static_mutex_lock +{ +public: + scoped_static_mutex_lock(static_mutex& mut, bool lk = true); + ~scoped_static_mutex_lock(); + inline bool locked()const + { + return m_have_lock; + } + inline operator void const*()const + { + return locked() ? this : 0; + } + void lock(); + void unlock(); +private: + static_mutex& m_mutex; + bool m_have_lock; +}; + +class static_mutex +{ +public: + typedef scoped_static_mutex_lock scoped_lock; + pthread_mutex_t m_mutex; +}; + +} // namespace boost +#elif defined(BOOST_HAS_WINTHREADS) +// +// Win32 version: +// Use a 32-bit int as a lock, along with a test-and-set +// implementation using InterlockedCompareExchange. +// + +#include + +namespace boost{ + +class BOOST_REGEX_DECL scoped_static_mutex_lock; + +class static_mutex +{ +public: + typedef scoped_static_mutex_lock scoped_lock; + boost::int32_t m_mutex; +}; + +#define BOOST_STATIC_MUTEX_INIT { 0, } + +class BOOST_REGEX_DECL scoped_static_mutex_lock +{ +public: + scoped_static_mutex_lock(static_mutex& mut, bool lk = true); + ~scoped_static_mutex_lock(); + operator void const*()const + { + return locked() ? this : 0; + } + bool locked()const + { + return m_have_lock; + } + void lock(); + void unlock(); +private: + static_mutex& m_mutex; + bool m_have_lock; + scoped_static_mutex_lock(const scoped_static_mutex_lock&); + scoped_static_mutex_lock& operator=(const scoped_static_mutex_lock&); +}; + +} // namespace + +#else +// +// Portable version of a static mutex based on Boost.Thread library: +// This has to use a single mutex shared by all instances of static_mutex +// because boost::call_once doesn't alow us to pass instance information +// down to the initialisation proceedure. In fact the initialisation routine +// may need to be called more than once - but only once per instance. +// +// Since this preprocessor path is almost never taken, we hide these header +// dependencies so that build tools don't find them. +// +#define BOOST_REGEX_H1 +#define BOOST_REGEX_H2 +#define BOOST_REGEX_H3 +#include BOOST_REGEX_H1 +#include BOOST_REGEX_H2 +#include BOOST_REGEX_H3 +#undef BOOST_REGEX_H1 +#undef BOOST_REGEX_H2 +#undef BOOST_REGEX_H3 + +namespace boost{ + +class BOOST_REGEX_DECL scoped_static_mutex_lock; +extern "C" BOOST_REGEX_DECL void boost_regex_free_static_mutex(); + +class BOOST_REGEX_DECL static_mutex +{ +public: + typedef scoped_static_mutex_lock scoped_lock; + static void init(); + static boost::recursive_mutex* m_pmutex; + static boost::once_flag m_once; +}; + +#define BOOST_STATIC_MUTEX_INIT { } + +class BOOST_REGEX_DECL scoped_static_mutex_lock +{ +public: + scoped_static_mutex_lock(static_mutex& mut, bool lk = true); + ~scoped_static_mutex_lock(); + operator void const*()const; + bool locked()const; + void lock(); + void unlock(); +private: + boost::unique_lock* m_plock; + bool m_have_lock; +}; + +inline scoped_static_mutex_lock::operator void const*()const +{ + return locked() ? this : 0; +} + +inline bool scoped_static_mutex_lock::locked()const +{ + return m_have_lock; +} + +} // namespace + +#endif + +#endif diff --git a/boost/regex/regex_traits.hpp b/boost/regex/regex_traits.hpp new file mode 100644 index 00000000..2b383160 --- /dev/null +++ b/boost/regex/regex_traits.hpp @@ -0,0 +1,39 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_traits.hpp + * VERSION see + * DESCRIPTION: Declares regular expression traits classes. + */ + +#ifndef BOOST_REGEX_TRAITS_HPP +#define BOOST_REGEX_TRAITS_HPP + +#ifndef BOOST_REGEX_CONFIG_HPP +# include +#endif + +# ifndef BOOST_REGEX_TRAITS_HPP_INCLUDED +#ifdef BOOST_REGEX_CXX03 +# include +#else +# include +#endif +# endif + +#endif // include + + + + + diff --git a/boost/regex/user.hpp b/boost/regex/user.hpp new file mode 100644 index 00000000..4b159bc5 --- /dev/null +++ b/boost/regex/user.hpp @@ -0,0 +1,95 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE user.hpp + * VERSION see + * DESCRIPTION: User settable options. + */ + +// define if you want the regex library to use the C locale +// even on Win32: +// #define BOOST_REGEX_USE_C_LOCALE + +// define this is you want the regex library to use the C++ +// locale: +// #define BOOST_REGEX_USE_CPP_LOCALE + +// define this if the runtime library is a dll, and you +// want BOOST_REGEX_DYN_LINK to set up dll exports/imports +// with __declspec(dllexport)/__declspec(dllimport.) +// #define BOOST_REGEX_HAS_DLL_RUNTIME + +// define this if you want to dynamically link to regex, +// if the runtime library is also a dll (Probably Win32 specific, +// and has no effect unless BOOST_REGEX_HAS_DLL_RUNTIME is set): +// #define BOOST_REGEX_DYN_LINK + +// define this if you don't want the lib to automatically +// select its link libraries: +// #define BOOST_REGEX_NO_LIB + +// define this if templates with switch statements cause problems: +// #define BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE + +// define this to disable Win32 support when available: +// #define BOOST_REGEX_NO_W32 + +// define this if bool is not a real type: +// #define BOOST_REGEX_NO_BOOL + +// define this if no template instances are to be placed in +// the library rather than users object files: +// #define BOOST_REGEX_NO_EXTERNAL_TEMPLATES + +// define this if the forward declarations in regex_fwd.hpp +// cause more problems than they are worth: +// #define BOOST_REGEX_NO_FWD + +// define this if your compiler supports MS Windows structured +// exception handling. +// #define BOOST_REGEX_HAS_MS_STACK_GUARD + +// define this if you want to use the recursive algorithm +// even if BOOST_REGEX_HAS_MS_STACK_GUARD is not defined. +// NOTE: OBSOLETE!! +// #define BOOST_REGEX_RECURSIVE + +// define this if you want to use the non-recursive +// algorithm, even if the recursive version would be the default. +// NOTE: OBSOLETE!! +// #define BOOST_REGEX_NON_RECURSIVE + +// define this if you want to set the size of the memory blocks +// used by the non-recursive algorithm. +// #define BOOST_REGEX_BLOCKSIZE 4096 + +// define this if you want to set the maximum number of memory blocks +// used by the non-recursive algorithm. +// #define BOOST_REGEX_MAX_BLOCKS 1024 + +// define this if you want to set the maximum number of memory blocks +// cached by the non-recursive algorithm: Normally this is 16, but can be +// higher if you have multiple threads all using boost.regex, or lower +// if you don't want boost.regex to cache memory. +// #define BOOST_REGEX_MAX_CACHE_BLOCKS 16 + +// define this if you want to be able to access extended capture +// information in your sub_match's (caution this will slow things +// down quite a bit). +// #define BOOST_REGEX_MATCH_EXTRA + +// define this if you want to enable support for Unicode via ICU. +// #define BOOST_HAS_ICU + +// define this if you want regex to use __cdecl calling convensions, even when __fastcall is available: +// #define BOOST_REGEX_NO_FASTCALL diff --git a/boost/regex/v4/basic_regex.hpp b/boost/regex/v4/basic_regex.hpp new file mode 100644 index 00000000..0408a754 --- /dev/null +++ b/boost/regex/v4/basic_regex.hpp @@ -0,0 +1,797 @@ +/* + * + * Copyright (c) 1998-2004 John Maddock + * Copyright 2011 Garmin Ltd. or its subsidiaries + * + * 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) + * + */ + + /* + * LOCATION: see http://www.boost.org/ for most recent version. + * FILE basic_regex.cpp + * VERSION see + * DESCRIPTION: Declares template class basic_regex. + */ + +#ifndef BOOST_REGEX_V4_BASIC_REGEX_HPP +#define BOOST_REGEX_V4_BASIC_REGEX_HPP + +#include +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +namespace boost{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable : 4251) +#if BOOST_MSVC < 1700 +# pragma warning(disable : 4231) +#endif +#if BOOST_MSVC < 1600 +#pragma warning(disable : 4660) +#endif +#if BOOST_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +namespace BOOST_REGEX_DETAIL_NS{ + +// +// forward declaration, we will need this one later: +// +template +class basic_regex_parser; + +template +void bubble_down_one(I first, I last) +{ + if(first != last) + { + I next = last - 1; + while((next != first) && (*next < *(next-1))) + { + (next-1)->swap(*next); + --next; + } + } +} + +static const int hash_value_mask = 1 << (std::numeric_limits::digits - 1); + +template +inline int hash_value_from_capture_name(Iterator i, Iterator j) +{ + std::size_t r = boost::hash_range(i, j); + r %= ((std::numeric_limits::max)()); + return static_cast(r) | hash_value_mask; +} + +class named_subexpressions +{ +public: + struct name + { + template + name(const charT* i, const charT* j, int idx) + : index(idx) + { + hash = hash_value_from_capture_name(i, j); + } + name(int h, int idx) + : index(idx), hash(h) + { + } + int index; + int hash; + bool operator < (const name& other)const + { + return hash < other.hash; + } + bool operator == (const name& other)const + { + return hash == other.hash; + } + void swap(name& other) + { + std::swap(index, other.index); + std::swap(hash, other.hash); + } + }; + + typedef std::vector::const_iterator const_iterator; + typedef std::pair range_type; + + named_subexpressions(){} + + template + void set_name(const charT* i, const charT* j, int index) + { + m_sub_names.push_back(name(i, j, index)); + bubble_down_one(m_sub_names.begin(), m_sub_names.end()); + } + template + int get_id(const charT* i, const charT* j)const + { + name t(i, j, 0); + typename std::vector::const_iterator pos = std::lower_bound(m_sub_names.begin(), m_sub_names.end(), t); + if((pos != m_sub_names.end()) && (*pos == t)) + { + return pos->index; + } + return -1; + } + template + range_type equal_range(const charT* i, const charT* j)const + { + name t(i, j, 0); + return std::equal_range(m_sub_names.begin(), m_sub_names.end(), t); + } + int get_id(int h)const + { + name t(h, 0); + std::vector::const_iterator pos = std::lower_bound(m_sub_names.begin(), m_sub_names.end(), t); + if((pos != m_sub_names.end()) && (*pos == t)) + { + return pos->index; + } + return -1; + } + range_type equal_range(int h)const + { + name t(h, 0); + return std::equal_range(m_sub_names.begin(), m_sub_names.end(), t); + } +private: + std::vector m_sub_names; +}; + +// +// class regex_data: +// represents the data we wish to expose to the matching algorithms. +// +template +struct regex_data : public named_subexpressions +{ + typedef regex_constants::syntax_option_type flag_type; + typedef std::size_t size_type; + + regex_data(const ::boost::shared_ptr< + ::boost::regex_traits_wrapper >& t) + : m_ptraits(t), m_flags(0), m_status(0), m_expression(0), m_expression_len(0), + m_mark_count(0), m_first_state(0), m_restart_type(0), +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !(defined(BOOST_MSVC) && (BOOST_MSVC < 1900)) + m_startmap{ 0 }, +#endif + m_can_be_null(0), m_word_mask(0), m_has_recursions(false), m_disable_match_any(false) {} + regex_data() + : m_ptraits(new ::boost::regex_traits_wrapper()), m_flags(0), m_status(0), m_expression(0), m_expression_len(0), + m_mark_count(0), m_first_state(0), m_restart_type(0), +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !(defined(BOOST_MSVC) && (BOOST_MSVC < 1900)) + m_startmap{ 0 }, +#endif + m_can_be_null(0), m_word_mask(0), m_has_recursions(false), m_disable_match_any(false) {} + + ::boost::shared_ptr< + ::boost::regex_traits_wrapper + > m_ptraits; // traits class instance + flag_type m_flags; // flags with which we were compiled + int m_status; // error code (0 implies OK). + const charT* m_expression; // the original expression + std::ptrdiff_t m_expression_len; // the length of the original expression + size_type m_mark_count; // the number of marked sub-expressions + BOOST_REGEX_DETAIL_NS::re_syntax_base* m_first_state; // the first state of the machine + unsigned m_restart_type; // search optimisation type + unsigned char m_startmap[1 << CHAR_BIT]; // which characters can start a match + unsigned int m_can_be_null; // whether we can match a null string + BOOST_REGEX_DETAIL_NS::raw_storage m_data; // the buffer in which our states are constructed + typename traits::char_class_type m_word_mask; // mask used to determine if a character is a word character + std::vector< + std::pair< + std::size_t, std::size_t> > m_subs; // Position of sub-expressions within the *string*. + bool m_has_recursions; // whether we have recursive expressions; + bool m_disable_match_any; // when set we need to disable the match_any flag as it causes different/buggy behaviour. +}; +// +// class basic_regex_implementation +// pimpl implementation class for basic_regex. +// +template +class basic_regex_implementation + : public regex_data +{ +public: + typedef regex_constants::syntax_option_type flag_type; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef typename traits::locale_type locale_type; + typedef const charT* const_iterator; + + basic_regex_implementation(){} + basic_regex_implementation(const ::boost::shared_ptr< + ::boost::regex_traits_wrapper >& t) + : regex_data(t) {} + void assign(const charT* arg_first, + const charT* arg_last, + flag_type f) + { + regex_data* pdat = this; + basic_regex_parser parser(pdat); + parser.parse(arg_first, arg_last, f); + } + + locale_type BOOST_REGEX_CALL imbue(locale_type l) + { + return this->m_ptraits->imbue(l); + } + locale_type BOOST_REGEX_CALL getloc()const + { + return this->m_ptraits->getloc(); + } + std::basic_string BOOST_REGEX_CALL str()const + { + std::basic_string result; + if(this->m_status == 0) + result = std::basic_string(this->m_expression, this->m_expression_len); + return result; + } + const_iterator BOOST_REGEX_CALL expression()const + { + return this->m_expression; + } + std::pair BOOST_REGEX_CALL subexpression(std::size_t n)const + { + const std::pair& pi = this->m_subs.at(n); + std::pair p(expression() + pi.first, expression() + pi.second); + return p; + } + // + // begin, end: + const_iterator BOOST_REGEX_CALL begin()const + { + return (this->m_status ? 0 : this->m_expression); + } + const_iterator BOOST_REGEX_CALL end()const + { + return (this->m_status ? 0 : this->m_expression + this->m_expression_len); + } + flag_type BOOST_REGEX_CALL flags()const + { + return this->m_flags; + } + size_type BOOST_REGEX_CALL size()const + { + return this->m_expression_len; + } + int BOOST_REGEX_CALL status()const + { + return this->m_status; + } + size_type BOOST_REGEX_CALL mark_count()const + { + return this->m_mark_count - 1; + } + const BOOST_REGEX_DETAIL_NS::re_syntax_base* get_first_state()const + { + return this->m_first_state; + } + unsigned get_restart_type()const + { + return this->m_restart_type; + } + const unsigned char* get_map()const + { + return this->m_startmap; + } + const ::boost::regex_traits_wrapper& get_traits()const + { + return *(this->m_ptraits); + } + bool can_be_null()const + { + return this->m_can_be_null; + } + const regex_data& get_data()const + { + basic_regex_implementation const* p = this; + return *static_cast*>(p); + } +}; + +} // namespace BOOST_REGEX_DETAIL_NS +// +// class basic_regex: +// represents the compiled +// regular expression: +// + +#ifdef BOOST_REGEX_NO_FWD +template > +#else +template +#endif +class basic_regex : public regbase +{ +public: + // typedefs: + typedef std::size_t traits_size_type; + typedef typename traits::string_type traits_string_type; + typedef charT char_type; + typedef traits traits_type; + + typedef charT value_type; + typedef charT& reference; + typedef const charT& const_reference; + typedef const charT* const_iterator; + typedef const_iterator iterator; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef regex_constants::syntax_option_type flag_type; + // locale_type + // placeholder for actual locale type used by the + // traits class to localise *this. + typedef typename traits::locale_type locale_type; + +public: + explicit basic_regex(){} + explicit basic_regex(const charT* p, flag_type f = regex_constants::normal) + { + assign(p, f); + } + basic_regex(const charT* p1, const charT* p2, flag_type f = regex_constants::normal) + { + assign(p1, p2, f); + } + basic_regex(const charT* p, size_type len, flag_type f) + { + assign(p, len, f); + } + basic_regex(const basic_regex& that) + : m_pimpl(that.m_pimpl) {} + ~basic_regex(){} + basic_regex& BOOST_REGEX_CALL operator=(const basic_regex& that) + { + return assign(that); + } + basic_regex& BOOST_REGEX_CALL operator=(const charT* ptr) + { + return assign(ptr); + } + + // + // assign: + basic_regex& assign(const basic_regex& that) + { + m_pimpl = that.m_pimpl; + return *this; + } + basic_regex& assign(const charT* p, flag_type f = regex_constants::normal) + { + return assign(p, p + traits::length(p), f); + } + basic_regex& assign(const charT* p, size_type len, flag_type f) + { + return assign(p, p + len, f); + } +private: + basic_regex& do_assign(const charT* p1, + const charT* p2, + flag_type f); +public: + basic_regex& assign(const charT* p1, + const charT* p2, + flag_type f = regex_constants::normal) + { + return do_assign(p1, p2, f); + } +#if !defined(BOOST_NO_MEMBER_TEMPLATES) + + template + unsigned int BOOST_REGEX_CALL set_expression(const std::basic_string& p, flag_type f = regex_constants::normal) + { + return set_expression(p.data(), p.data() + p.size(), f); + } + + template + explicit basic_regex(const std::basic_string& p, flag_type f = regex_constants::normal) + { + assign(p, f); + } + + template + basic_regex(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal) + { + typedef typename traits::string_type seq_type; + seq_type a(arg_first, arg_last); + if(!a.empty()) + assign(static_cast(&*a.begin()), static_cast(&*a.begin() + a.size()), f); + else + assign(static_cast(0), static_cast(0), f); + } + + template + basic_regex& BOOST_REGEX_CALL operator=(const std::basic_string& p) + { + return assign(p.data(), p.data() + p.size(), regex_constants::normal); + } + + template + basic_regex& BOOST_REGEX_CALL assign( + const std::basic_string& s, + flag_type f = regex_constants::normal) + { + return assign(s.data(), s.data() + s.size(), f); + } + + template + basic_regex& BOOST_REGEX_CALL assign(InputIterator arg_first, + InputIterator arg_last, + flag_type f = regex_constants::normal) + { + typedef typename traits::string_type seq_type; + seq_type a(arg_first, arg_last); + if(a.size()) + { + const charT* p1 = &*a.begin(); + const charT* p2 = &*a.begin() + a.size(); + return assign(p1, p2, f); + } + return assign(static_cast(0), static_cast(0), f); + } +#else + unsigned int BOOST_REGEX_CALL set_expression(const std::basic_string& p, flag_type f = regex_constants::normal) + { + return set_expression(p.data(), p.data() + p.size(), f); + } + + basic_regex(const std::basic_string& p, flag_type f = regex_constants::normal) + { + assign(p, f); + } + + basic_regex& BOOST_REGEX_CALL operator=(const std::basic_string& p) + { + return assign(p.data(), p.data() + p.size(), regex_constants::normal); + } + + basic_regex& BOOST_REGEX_CALL assign( + const std::basic_string& s, + flag_type f = regex_constants::normal) + { + return assign(s.data(), s.data() + s.size(), f); + } + +#endif + + // + // locale: + locale_type BOOST_REGEX_CALL imbue(locale_type l); + locale_type BOOST_REGEX_CALL getloc()const + { + return m_pimpl.get() ? m_pimpl->getloc() : locale_type(); + } + // + // getflags: + // retained for backwards compatibility only, "flags" + // is now the preferred name: + flag_type BOOST_REGEX_CALL getflags()const + { + return flags(); + } + flag_type BOOST_REGEX_CALL flags()const + { + return m_pimpl.get() ? m_pimpl->flags() : 0; + } + // + // str: + std::basic_string BOOST_REGEX_CALL str()const + { + return m_pimpl.get() ? m_pimpl->str() : std::basic_string(); + } + // + // begin, end, subexpression: + std::pair BOOST_REGEX_CALL subexpression(std::size_t n)const + { + if(!m_pimpl.get()) + boost::throw_exception(std::logic_error("Can't access subexpressions in an invalid regex.")); + return m_pimpl->subexpression(n); + } + const_iterator BOOST_REGEX_CALL begin()const + { + return (m_pimpl.get() ? m_pimpl->begin() : 0); + } + const_iterator BOOST_REGEX_CALL end()const + { + return (m_pimpl.get() ? m_pimpl->end() : 0); + } + // + // swap: + void BOOST_REGEX_CALL swap(basic_regex& that)throw() + { + m_pimpl.swap(that.m_pimpl); + } + // + // size: + size_type BOOST_REGEX_CALL size()const + { + return (m_pimpl.get() ? m_pimpl->size() : 0); + } + // + // max_size: + size_type BOOST_REGEX_CALL max_size()const + { + return UINT_MAX; + } + // + // empty: + bool BOOST_REGEX_CALL empty()const + { + return (m_pimpl.get() ? 0 != m_pimpl->status() : true); + } + + size_type BOOST_REGEX_CALL mark_count()const + { + return (m_pimpl.get() ? m_pimpl->mark_count() : 0); + } + + int status()const + { + return (m_pimpl.get() ? m_pimpl->status() : regex_constants::error_empty); + } + + int BOOST_REGEX_CALL compare(const basic_regex& that) const + { + if(m_pimpl.get() == that.m_pimpl.get()) + return 0; + if(!m_pimpl.get()) + return -1; + if(!that.m_pimpl.get()) + return 1; + if(status() != that.status()) + return status() - that.status(); + if(flags() != that.flags()) + return flags() - that.flags(); + return str().compare(that.str()); + } + bool BOOST_REGEX_CALL operator==(const basic_regex& e)const + { + return compare(e) == 0; + } + bool BOOST_REGEX_CALL operator != (const basic_regex& e)const + { + return compare(e) != 0; + } + bool BOOST_REGEX_CALL operator<(const basic_regex& e)const + { + return compare(e) < 0; + } + bool BOOST_REGEX_CALL operator>(const basic_regex& e)const + { + return compare(e) > 0; + } + bool BOOST_REGEX_CALL operator<=(const basic_regex& e)const + { + return compare(e) <= 0; + } + bool BOOST_REGEX_CALL operator>=(const basic_regex& e)const + { + return compare(e) >= 0; + } + + // + // The following are deprecated as public interfaces + // but are available for compatibility with earlier versions. + const charT* BOOST_REGEX_CALL expression()const + { + return (m_pimpl.get() && !m_pimpl->status() ? m_pimpl->expression() : 0); + } + unsigned int BOOST_REGEX_CALL set_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal) + { + assign(p1, p2, f | regex_constants::no_except); + return status(); + } + unsigned int BOOST_REGEX_CALL set_expression(const charT* p, flag_type f = regex_constants::normal) + { + assign(p, f | regex_constants::no_except); + return status(); + } + unsigned int BOOST_REGEX_CALL error_code()const + { + return status(); + } + // + // private access methods: + // + const BOOST_REGEX_DETAIL_NS::re_syntax_base* get_first_state()const + { + BOOST_REGEX_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_first_state(); + } + unsigned get_restart_type()const + { + BOOST_REGEX_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_restart_type(); + } + const unsigned char* get_map()const + { + BOOST_REGEX_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_map(); + } + const ::boost::regex_traits_wrapper& get_traits()const + { + BOOST_REGEX_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_traits(); + } + bool can_be_null()const + { + BOOST_REGEX_ASSERT(0 != m_pimpl.get()); + return m_pimpl->can_be_null(); + } + const BOOST_REGEX_DETAIL_NS::regex_data& get_data()const + { + BOOST_REGEX_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_data(); + } + boost::shared_ptr get_named_subs()const + { + return m_pimpl; + } + +private: + shared_ptr > m_pimpl; +}; + +// +// out of line members; +// these are the only members that mutate the basic_regex object, +// and are designed to provide the strong exception guarantee +// (in the event of a throw, the state of the object remains unchanged). +// +template +basic_regex& basic_regex::do_assign(const charT* p1, + const charT* p2, + flag_type f) +{ + shared_ptr > temp; + if(!m_pimpl.get()) + { + temp = shared_ptr >(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation()); + } + else + { + temp = shared_ptr >(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation(m_pimpl->m_ptraits)); + } + temp->assign(p1, p2, f); + temp.swap(m_pimpl); + return *this; +} + +template +typename basic_regex::locale_type BOOST_REGEX_CALL basic_regex::imbue(locale_type l) +{ + shared_ptr > temp(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation()); + locale_type result = temp->imbue(l); + temp.swap(m_pimpl); + return result; +} + +// +// non-members: +// +template +void swap(basic_regex& e1, basic_regex& e2) +{ + e1.swap(e2); +} + +#ifndef BOOST_NO_STD_LOCALE +template +std::basic_ostream& + operator << (std::basic_ostream& os, + const basic_regex& e) +{ + return (os << e.str()); +} +#else +template +std::ostream& operator << (std::ostream& os, const basic_regex& e) +{ + return (os << e.str()); +} +#endif + +// +// class reg_expression: +// this is provided for backwards compatibility only, +// it is deprecated, no not use! +// +#ifdef BOOST_REGEX_NO_FWD +template > +#else +template +#endif +class reg_expression : public basic_regex +{ +public: + typedef typename basic_regex::flag_type flag_type; + typedef typename basic_regex::size_type size_type; + explicit reg_expression(){} + explicit reg_expression(const charT* p, flag_type f = regex_constants::normal) + : basic_regex(p, f){} + reg_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal) + : basic_regex(p1, p2, f){} + reg_expression(const charT* p, size_type len, flag_type f) + : basic_regex(p, len, f){} + reg_expression(const reg_expression& that) + : basic_regex(that) {} + ~reg_expression(){} + reg_expression& BOOST_REGEX_CALL operator=(const reg_expression& that) + { + return this->assign(that); + } + +#if !defined(BOOST_NO_MEMBER_TEMPLATES) + template + explicit reg_expression(const std::basic_string& p, flag_type f = regex_constants::normal) + : basic_regex(p, f) + { + } + + template + reg_expression(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal) + : basic_regex(arg_first, arg_last, f) + { + } + + template + reg_expression& BOOST_REGEX_CALL operator=(const std::basic_string& p) + { + this->assign(p); + return *this; + } +#else + explicit reg_expression(const std::basic_string& p, flag_type f = regex_constants::normal) + : basic_regex(p, f) + { + } + + reg_expression& BOOST_REGEX_CALL operator=(const std::basic_string& p) + { + this->assign(p); + return *this; + } +#endif + +}; + +#ifdef BOOST_MSVC +#pragma warning (pop) +#endif + +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif diff --git a/boost/regex/v4/basic_regex_creator.hpp b/boost/regex/v4/basic_regex_creator.hpp new file mode 100644 index 00000000..b9f02ece --- /dev/null +++ b/boost/regex/v4/basic_regex_creator.hpp @@ -0,0 +1,1598 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE basic_regex_creator.cpp + * VERSION see + * DESCRIPTION: Declares template class basic_regex_creator which fills in + * the data members of a regex_data object. + */ + +#ifndef BOOST_REGEX_V4_BASIC_REGEX_CREATOR_HPP +#define BOOST_REGEX_V4_BASIC_REGEX_CREATOR_HPP + +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +# pragma warning(push) +#if BOOST_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +namespace boost{ + +namespace BOOST_REGEX_DETAIL_NS{ + +template +struct digraph : public std::pair +{ + digraph() : std::pair(charT(0), charT(0)){} + digraph(charT c1) : std::pair(c1, charT(0)){} + digraph(charT c1, charT c2) : std::pair(c1, c2) + {} + digraph(const digraph& d) : std::pair(d.first, d.second){} +#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS + digraph& operator=(const digraph&) = default; +#endif + template + digraph(const Seq& s) : std::pair() + { + BOOST_REGEX_ASSERT(s.size() <= 2); + BOOST_REGEX_ASSERT(s.size()); + this->first = s[0]; + this->second = (s.size() > 1) ? s[1] : 0; + } +}; + +template +class basic_char_set +{ +public: + typedef digraph digraph_type; + typedef typename traits::string_type string_type; + typedef typename traits::char_class_type m_type; + + basic_char_set() + { + m_negate = false; + m_has_digraphs = false; + m_classes = 0; + m_negated_classes = 0; + m_empty = true; + } + + void add_single(const digraph_type& s) + { + m_singles.insert(s); + if(s.second) + m_has_digraphs = true; + m_empty = false; + } + void add_range(const digraph_type& first, const digraph_type& end) + { + m_ranges.push_back(first); + m_ranges.push_back(end); + if(first.second) + { + m_has_digraphs = true; + add_single(first); + } + if(end.second) + { + m_has_digraphs = true; + add_single(end); + } + m_empty = false; + } + void add_class(m_type m) + { + m_classes |= m; + m_empty = false; + } + void add_negated_class(m_type m) + { + m_negated_classes |= m; + m_empty = false; + } + void add_equivalent(const digraph_type& s) + { + m_equivalents.insert(s); + if(s.second) + { + m_has_digraphs = true; + add_single(s); + } + m_empty = false; + } + void negate() + { + m_negate = true; + //m_empty = false; + } + + // + // accessor functions: + // + bool has_digraphs()const + { + return m_has_digraphs; + } + bool is_negated()const + { + return m_negate; + } + typedef typename std::vector::const_iterator list_iterator; + typedef typename std::set::const_iterator set_iterator; + set_iterator singles_begin()const + { + return m_singles.begin(); + } + set_iterator singles_end()const + { + return m_singles.end(); + } + list_iterator ranges_begin()const + { + return m_ranges.begin(); + } + list_iterator ranges_end()const + { + return m_ranges.end(); + } + set_iterator equivalents_begin()const + { + return m_equivalents.begin(); + } + set_iterator equivalents_end()const + { + return m_equivalents.end(); + } + m_type classes()const + { + return m_classes; + } + m_type negated_classes()const + { + return m_negated_classes; + } + bool empty()const + { + return m_empty; + } +private: + std::set m_singles; // a list of single characters to match + std::vector m_ranges; // a list of end points of our ranges + bool m_negate; // true if the set is to be negated + bool m_has_digraphs; // true if we have digraphs present + m_type m_classes; // character classes to match + m_type m_negated_classes; // negated character classes to match + bool m_empty; // whether we've added anything yet + std::set m_equivalents; // a list of equivalence classes +}; + +template +class basic_regex_creator +{ +public: + basic_regex_creator(regex_data* data); + std::ptrdiff_t getoffset(void* addr) + { + return getoffset(addr, m_pdata->m_data.data()); + } + std::ptrdiff_t getoffset(const void* addr, const void* base) + { + return static_cast(addr) - static_cast(base); + } + re_syntax_base* getaddress(std::ptrdiff_t off) + { + return getaddress(off, m_pdata->m_data.data()); + } + re_syntax_base* getaddress(std::ptrdiff_t off, void* base) + { + return static_cast(static_cast(static_cast(base) + off)); + } + void init(unsigned l_flags) + { + m_pdata->m_flags = l_flags; + m_icase = l_flags & regex_constants::icase; + } + regbase::flag_type flags() + { + return m_pdata->m_flags; + } + void flags(regbase::flag_type f) + { + m_pdata->m_flags = f; + if(m_icase != static_cast(f & regbase::icase)) + { + m_icase = static_cast(f & regbase::icase); + } + } + re_syntax_base* append_state(syntax_element_type t, std::size_t s = sizeof(re_syntax_base)); + re_syntax_base* insert_state(std::ptrdiff_t pos, syntax_element_type t, std::size_t s = sizeof(re_syntax_base)); + re_literal* append_literal(charT c); + re_syntax_base* append_set(const basic_char_set& char_set); + re_syntax_base* append_set(const basic_char_set& char_set, mpl::false_*); + re_syntax_base* append_set(const basic_char_set& char_set, mpl::true_*); + void finalize(const charT* p1, const charT* p2); +protected: + regex_data* m_pdata; // pointer to the basic_regex_data struct we are filling in + const ::boost::regex_traits_wrapper& + m_traits; // convenience reference to traits class + re_syntax_base* m_last_state; // the last state we added + bool m_icase; // true for case insensitive matches + unsigned m_repeater_id; // the state_id of the next repeater + bool m_has_backrefs; // true if there are actually any backrefs + indexed_bit_flag m_backrefs; // bitmask of permitted backrefs + boost::uintmax_t m_bad_repeats; // bitmask of repeats we can't deduce a startmap for; + bool m_has_recursions; // set when we have recursive expressions to fixup + std::vector m_recursion_checks; // notes which recursions we've followed while analysing this expression + typename traits::char_class_type m_word_mask; // mask used to determine if a character is a word character + typename traits::char_class_type m_mask_space; // mask used to determine if a character is a word character + typename traits::char_class_type m_lower_mask; // mask used to determine if a character is a lowercase character + typename traits::char_class_type m_upper_mask; // mask used to determine if a character is an uppercase character + typename traits::char_class_type m_alpha_mask; // mask used to determine if a character is an alphabetic character +private: + basic_regex_creator& operator=(const basic_regex_creator&); + basic_regex_creator(const basic_regex_creator&); + + void fixup_pointers(re_syntax_base* state); + void fixup_recursions(re_syntax_base* state); + void create_startmaps(re_syntax_base* state); + int calculate_backstep(re_syntax_base* state); + void create_startmap(re_syntax_base* state, unsigned char* l_map, unsigned int* pnull, unsigned char mask); + unsigned get_restart_type(re_syntax_base* state); + void set_all_masks(unsigned char* bits, unsigned char); + bool is_bad_repeat(re_syntax_base* pt); + void set_bad_repeat(re_syntax_base* pt); + syntax_element_type get_repeat_type(re_syntax_base* state); + void probe_leading_repeat(re_syntax_base* state); +}; + +template +basic_regex_creator::basic_regex_creator(regex_data* data) + : m_pdata(data), m_traits(*(data->m_ptraits)), m_last_state(0), m_icase(false), m_repeater_id(0), + m_has_backrefs(false), m_bad_repeats(0), m_has_recursions(false), m_word_mask(0), m_mask_space(0), m_lower_mask(0), m_upper_mask(0), m_alpha_mask(0) +{ + m_pdata->m_data.clear(); + m_pdata->m_status = ::boost::regex_constants::error_ok; + static const charT w = 'w'; + static const charT s = 's'; + static const charT l[5] = { 'l', 'o', 'w', 'e', 'r', }; + static const charT u[5] = { 'u', 'p', 'p', 'e', 'r', }; + static const charT a[5] = { 'a', 'l', 'p', 'h', 'a', }; + m_word_mask = m_traits.lookup_classname(&w, &w +1); + m_mask_space = m_traits.lookup_classname(&s, &s +1); + m_lower_mask = m_traits.lookup_classname(l, l + 5); + m_upper_mask = m_traits.lookup_classname(u, u + 5); + m_alpha_mask = m_traits.lookup_classname(a, a + 5); + m_pdata->m_word_mask = m_word_mask; + BOOST_REGEX_ASSERT(m_word_mask != 0); + BOOST_REGEX_ASSERT(m_mask_space != 0); + BOOST_REGEX_ASSERT(m_lower_mask != 0); + BOOST_REGEX_ASSERT(m_upper_mask != 0); + BOOST_REGEX_ASSERT(m_alpha_mask != 0); +} + +template +re_syntax_base* basic_regex_creator::append_state(syntax_element_type t, std::size_t s) +{ + // if the state is a backref then make a note of it: + if(t == syntax_element_backref) + this->m_has_backrefs = true; + // append a new state, start by aligning our last one: + m_pdata->m_data.align(); + // set the offset to the next state in our last one: + if(m_last_state) + m_last_state->next.i = m_pdata->m_data.size() - getoffset(m_last_state); + // now actually extend our data: + m_last_state = static_cast(m_pdata->m_data.extend(s)); + // fill in boilerplate options in the new state: + m_last_state->next.i = 0; + m_last_state->type = t; + return m_last_state; +} + +template +re_syntax_base* basic_regex_creator::insert_state(std::ptrdiff_t pos, syntax_element_type t, std::size_t s) +{ + // append a new state, start by aligning our last one: + m_pdata->m_data.align(); + // set the offset to the next state in our last one: + if(m_last_state) + m_last_state->next.i = m_pdata->m_data.size() - getoffset(m_last_state); + // remember the last state position: + std::ptrdiff_t off = getoffset(m_last_state) + s; + // now actually insert our data: + re_syntax_base* new_state = static_cast(m_pdata->m_data.insert(pos, s)); + // fill in boilerplate options in the new state: + new_state->next.i = s; + new_state->type = t; + m_last_state = getaddress(off); + return new_state; +} + +template +re_literal* basic_regex_creator::append_literal(charT c) +{ + re_literal* result; + // start by seeing if we have an existing re_literal we can extend: + if((0 == m_last_state) || (m_last_state->type != syntax_element_literal)) + { + // no existing re_literal, create a new one: + result = static_cast(append_state(syntax_element_literal, sizeof(re_literal) + sizeof(charT))); + result->length = 1; + *static_cast(static_cast(result+1)) = m_traits.translate(c, m_icase); + } + else + { + // we have an existing re_literal, extend it: + std::ptrdiff_t off = getoffset(m_last_state); + m_pdata->m_data.extend(sizeof(charT)); + m_last_state = result = static_cast(getaddress(off)); + charT* characters = static_cast(static_cast(result+1)); + characters[result->length] = m_traits.translate(c, m_icase); + result->length += 1; + } + return result; +} + +template +inline re_syntax_base* basic_regex_creator::append_set( + const basic_char_set& char_set) +{ + typedef mpl::bool_< (sizeof(charT) == 1) > truth_type; + return char_set.has_digraphs() + ? append_set(char_set, static_cast(0)) + : append_set(char_set, static_cast(0)); +} + +template +re_syntax_base* basic_regex_creator::append_set( + const basic_char_set& char_set, mpl::false_*) +{ + typedef typename traits::string_type string_type; + typedef typename basic_char_set::list_iterator item_iterator; + typedef typename basic_char_set::set_iterator set_iterator; + typedef typename traits::char_class_type m_type; + + re_set_long* result = static_cast*>(append_state(syntax_element_long_set, sizeof(re_set_long))); + // + // fill in the basics: + // + result->csingles = static_cast(::boost::BOOST_REGEX_DETAIL_NS::distance(char_set.singles_begin(), char_set.singles_end())); + result->cranges = static_cast(::boost::BOOST_REGEX_DETAIL_NS::distance(char_set.ranges_begin(), char_set.ranges_end())) / 2; + result->cequivalents = static_cast(::boost::BOOST_REGEX_DETAIL_NS::distance(char_set.equivalents_begin(), char_set.equivalents_end())); + result->cclasses = char_set.classes(); + result->cnclasses = char_set.negated_classes(); + if(flags() & regbase::icase) + { + // adjust classes as needed: + if(((result->cclasses & m_lower_mask) == m_lower_mask) || ((result->cclasses & m_upper_mask) == m_upper_mask)) + result->cclasses |= m_alpha_mask; + if(((result->cnclasses & m_lower_mask) == m_lower_mask) || ((result->cnclasses & m_upper_mask) == m_upper_mask)) + result->cnclasses |= m_alpha_mask; + } + + result->isnot = char_set.is_negated(); + result->singleton = !char_set.has_digraphs(); + // + // remember where the state is for later: + // + std::ptrdiff_t offset = getoffset(result); + // + // now extend with all the singles: + // + item_iterator first, last; + set_iterator sfirst, slast; + sfirst = char_set.singles_begin(); + slast = char_set.singles_end(); + while(sfirst != slast) + { + charT* p = static_cast(this->m_pdata->m_data.extend(sizeof(charT) * (sfirst->first == static_cast(0) ? 1 : sfirst->second ? 3 : 2))); + p[0] = m_traits.translate(sfirst->first, m_icase); + if(sfirst->first == static_cast(0)) + { + p[0] = 0; + } + else if(sfirst->second) + { + p[1] = m_traits.translate(sfirst->second, m_icase); + p[2] = 0; + } + else + p[1] = 0; + ++sfirst; + } + // + // now extend with all the ranges: + // + first = char_set.ranges_begin(); + last = char_set.ranges_end(); + while(first != last) + { + // first grab the endpoints of the range: + digraph c1 = *first; + c1.first = this->m_traits.translate(c1.first, this->m_icase); + c1.second = this->m_traits.translate(c1.second, this->m_icase); + ++first; + digraph c2 = *first; + c2.first = this->m_traits.translate(c2.first, this->m_icase); + c2.second = this->m_traits.translate(c2.second, this->m_icase); + ++first; + string_type s1, s2; + // different actions now depending upon whether collation is turned on: + if(flags() & regex_constants::collate) + { + // we need to transform our range into sort keys: + charT a1[3] = { c1.first, c1.second, charT(0), }; + charT a2[3] = { c2.first, c2.second, charT(0), }; + s1 = this->m_traits.transform(a1, (a1[1] ? a1+2 : a1+1)); + s2 = this->m_traits.transform(a2, (a2[1] ? a2+2 : a2+1)); + if(s1.empty()) + s1 = string_type(1, charT(0)); + if(s2.empty()) + s2 = string_type(1, charT(0)); + } + else + { + if(c1.second) + { + s1.insert(s1.end(), c1.first); + s1.insert(s1.end(), c1.second); + } + else + s1 = string_type(1, c1.first); + if(c2.second) + { + s2.insert(s2.end(), c2.first); + s2.insert(s2.end(), c2.second); + } + else + s2.insert(s2.end(), c2.first); + } + if(s1 > s2) + { + // Oops error: + return 0; + } + charT* p = static_cast(this->m_pdata->m_data.extend(sizeof(charT) * (s1.size() + s2.size() + 2) ) ); + BOOST_REGEX_DETAIL_NS::copy(s1.begin(), s1.end(), p); + p[s1.size()] = charT(0); + p += s1.size() + 1; + BOOST_REGEX_DETAIL_NS::copy(s2.begin(), s2.end(), p); + p[s2.size()] = charT(0); + } + // + // now process the equivalence classes: + // + sfirst = char_set.equivalents_begin(); + slast = char_set.equivalents_end(); + while(sfirst != slast) + { + string_type s; + if(sfirst->second) + { + charT cs[3] = { sfirst->first, sfirst->second, charT(0), }; + s = m_traits.transform_primary(cs, cs+2); + } + else + s = m_traits.transform_primary(&sfirst->first, &sfirst->first+1); + if(s.empty()) + return 0; // invalid or unsupported equivalence class + charT* p = static_cast(this->m_pdata->m_data.extend(sizeof(charT) * (s.size()+1) ) ); + BOOST_REGEX_DETAIL_NS::copy(s.begin(), s.end(), p); + p[s.size()] = charT(0); + ++sfirst; + } + // + // finally reset the address of our last state: + // + m_last_state = result = static_cast*>(getaddress(offset)); + return result; +} + +template +inline bool char_less(T t1, T t2) +{ + return t1 < t2; +} +inline bool char_less(char t1, char t2) +{ + return static_cast(t1) < static_cast(t2); +} +inline bool char_less(signed char t1, signed char t2) +{ + return static_cast(t1) < static_cast(t2); +} + +template +re_syntax_base* basic_regex_creator::append_set( + const basic_char_set& char_set, mpl::true_*) +{ + typedef typename traits::string_type string_type; + typedef typename basic_char_set::list_iterator item_iterator; + typedef typename basic_char_set::set_iterator set_iterator; + + re_set* result = static_cast(append_state(syntax_element_set, sizeof(re_set))); + bool negate = char_set.is_negated(); + std::memset(result->_map, 0, sizeof(result->_map)); + // + // handle singles first: + // + item_iterator first, last; + set_iterator sfirst, slast; + sfirst = char_set.singles_begin(); + slast = char_set.singles_end(); + while(sfirst != slast) + { + for(unsigned int i = 0; i < (1 << CHAR_BIT); ++i) + { + if(this->m_traits.translate(static_cast(i), this->m_icase) + == this->m_traits.translate(sfirst->first, this->m_icase)) + result->_map[i] = true; + } + ++sfirst; + } + // + // OK now handle ranges: + // + first = char_set.ranges_begin(); + last = char_set.ranges_end(); + while(first != last) + { + // first grab the endpoints of the range: + charT c1 = this->m_traits.translate(first->first, this->m_icase); + ++first; + charT c2 = this->m_traits.translate(first->first, this->m_icase); + ++first; + // different actions now depending upon whether collation is turned on: + if(flags() & regex_constants::collate) + { + // we need to transform our range into sort keys: + charT c3[2] = { c1, charT(0), }; + string_type s1 = this->m_traits.transform(c3, c3+1); + c3[0] = c2; + string_type s2 = this->m_traits.transform(c3, c3+1); + if(s1 > s2) + { + // Oops error: + return 0; + } + BOOST_REGEX_ASSERT(c3[1] == charT(0)); + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + c3[0] = static_cast(i); + string_type s3 = this->m_traits.transform(c3, c3 +1); + if((s1 <= s3) && (s3 <= s2)) + result->_map[i] = true; + } + } + else + { + if(char_less(c2, c1)) + { + // Oops error: + return 0; + } + // everything in range matches: + std::memset(result->_map + static_cast(c1), true, static_cast(1u) + static_cast(static_cast(c2) - static_cast(c1))); + } + } + // + // and now the classes: + // + typedef typename traits::char_class_type m_type; + m_type m = char_set.classes(); + if(flags() & regbase::icase) + { + // adjust m as needed: + if(((m & m_lower_mask) == m_lower_mask) || ((m & m_upper_mask) == m_upper_mask)) + m |= m_alpha_mask; + } + if(m != 0) + { + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + if(this->m_traits.isctype(static_cast(i), m)) + result->_map[i] = true; + } + } + // + // and now the negated classes: + // + m = char_set.negated_classes(); + if(flags() & regbase::icase) + { + // adjust m as needed: + if(((m & m_lower_mask) == m_lower_mask) || ((m & m_upper_mask) == m_upper_mask)) + m |= m_alpha_mask; + } + if(m != 0) + { + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + if(0 == this->m_traits.isctype(static_cast(i), m)) + result->_map[i] = true; + } + } + // + // now process the equivalence classes: + // + sfirst = char_set.equivalents_begin(); + slast = char_set.equivalents_end(); + while(sfirst != slast) + { + string_type s; + BOOST_REGEX_ASSERT(static_cast(0) == sfirst->second); + s = m_traits.transform_primary(&sfirst->first, &sfirst->first+1); + if(s.empty()) + return 0; // invalid or unsupported equivalence class + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + charT c[2] = { (static_cast(i)), charT(0), }; + string_type s2 = this->m_traits.transform_primary(c, c+1); + if(s == s2) + result->_map[i] = true; + } + ++sfirst; + } + if(negate) + { + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + result->_map[i] = !(result->_map[i]); + } + } + return result; +} + +template +void basic_regex_creator::finalize(const charT* p1, const charT* p2) +{ + if(this->m_pdata->m_status) + return; + // we've added all the states we need, now finish things off. + // start by adding a terminating state: + append_state(syntax_element_match); + // extend storage to store original expression: + std::ptrdiff_t len = p2 - p1; + m_pdata->m_expression_len = len; + charT* ps = static_cast(m_pdata->m_data.extend(sizeof(charT) * (1 + (p2 - p1)))); + m_pdata->m_expression = ps; + BOOST_REGEX_DETAIL_NS::copy(p1, p2, ps); + ps[p2 - p1] = 0; + // fill in our other data... + // successful parsing implies a zero status: + m_pdata->m_status = 0; + // get the first state of the machine: + m_pdata->m_first_state = static_cast(m_pdata->m_data.data()); + // fixup pointers in the machine: + fixup_pointers(m_pdata->m_first_state); + if(m_has_recursions) + { + m_pdata->m_has_recursions = true; + fixup_recursions(m_pdata->m_first_state); + if(this->m_pdata->m_status) + return; + } + else + m_pdata->m_has_recursions = false; + // create nested startmaps: + create_startmaps(m_pdata->m_first_state); + // create main startmap: + std::memset(m_pdata->m_startmap, 0, sizeof(m_pdata->m_startmap)); + m_pdata->m_can_be_null = 0; + + m_bad_repeats = 0; + if(m_has_recursions) + m_recursion_checks.assign(1 + m_pdata->m_mark_count, 0u); + create_startmap(m_pdata->m_first_state, m_pdata->m_startmap, &(m_pdata->m_can_be_null), mask_all); + // get the restart type: + m_pdata->m_restart_type = get_restart_type(m_pdata->m_first_state); + // optimise a leading repeat if there is one: + probe_leading_repeat(m_pdata->m_first_state); +} + +template +void basic_regex_creator::fixup_pointers(re_syntax_base* state) +{ + while(state) + { + switch(state->type) + { + case syntax_element_recurse: + m_has_recursions = true; + if(state->next.i) + state->next.p = getaddress(state->next.i, state); + else + state->next.p = 0; + break; + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + // set the state_id of this repeat: + static_cast(state)->state_id = m_repeater_id++; + BOOST_FALLTHROUGH; + case syntax_element_alt: + std::memset(static_cast(state)->_map, 0, sizeof(static_cast(state)->_map)); + static_cast(state)->can_be_null = 0; + BOOST_FALLTHROUGH; + case syntax_element_jump: + static_cast(state)->alt.p = getaddress(static_cast(state)->alt.i, state); + BOOST_FALLTHROUGH; + default: + if(state->next.i) + state->next.p = getaddress(state->next.i, state); + else + state->next.p = 0; + } + state = state->next.p; + } +} + +template +void basic_regex_creator::fixup_recursions(re_syntax_base* state) +{ + re_syntax_base* base = state; + while(state) + { + switch(state->type) + { + case syntax_element_assert_backref: + { + // just check that the index is valid: + int idx = static_cast(state)->index; + if(idx < 0) + { + idx = -idx-1; + if(idx >= hash_value_mask) + { + idx = m_pdata->get_id(idx); + if(idx <= 0) + { + // check of sub-expression that doesn't exist: + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = boost::regex_constants::error_bad_pattern; + // + // clear the expression, we should be empty: + // + this->m_pdata->m_expression = 0; + this->m_pdata->m_expression_len = 0; + // + // and throw if required: + // + if(0 == (this->flags() & regex_constants::no_except)) + { + std::string message = "Encountered a forward reference to a marked sub-expression that does not exist."; + boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0); + e.raise(); + } + } + } + } + } + break; + case syntax_element_recurse: + { + bool ok = false; + re_syntax_base* p = base; + std::ptrdiff_t idx = static_cast(state)->alt.i; + if(idx >= hash_value_mask) + { + // + // There may be more than one capture group with this hash, just do what Perl + // does and recurse to the leftmost: + // + idx = m_pdata->get_id(static_cast(idx)); + } + if(idx < 0) + { + ok = false; + } + else + { + while(p) + { + if((p->type == syntax_element_startmark) && (static_cast(p)->index == idx)) + { + // + // We've found the target of the recursion, set the jump target: + // + static_cast(state)->alt.p = p; + ok = true; + // + // Now scan the target for nested repeats: + // + p = p->next.p; + int next_rep_id = 0; + while(p) + { + switch(p->type) + { + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + next_rep_id = static_cast(p)->state_id; + break; + case syntax_element_endmark: + if(static_cast(p)->index == idx) + next_rep_id = -1; + break; + default: + break; + } + if(next_rep_id) + break; + p = p->next.p; + } + if(next_rep_id > 0) + { + static_cast(state)->state_id = next_rep_id - 1; + } + + break; + } + p = p->next.p; + } + } + if(!ok) + { + // recursion to sub-expression that doesn't exist: + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = boost::regex_constants::error_bad_pattern; + // + // clear the expression, we should be empty: + // + this->m_pdata->m_expression = 0; + this->m_pdata->m_expression_len = 0; + // + // and throw if required: + // + if(0 == (this->flags() & regex_constants::no_except)) + { + std::string message = "Encountered a forward reference to a recursive sub-expression that does not exist."; + boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0); + e.raise(); + } + } + } + break; + default: + break; + } + state = state->next.p; + } +} + +template +void basic_regex_creator::create_startmaps(re_syntax_base* state) +{ + // non-recursive implementation: + // create the last map in the machine first, so that earlier maps + // can make use of the result... + // + // This was originally a recursive implementation, but that caused stack + // overflows with complex expressions on small stacks (think COM+). + + // start by saving the case setting: + bool l_icase = m_icase; + std::vector > v; + + while(state) + { + switch(state->type) + { + case syntax_element_toggle_case: + // we need to track case changes here: + m_icase = static_cast(state)->icase; + state = state->next.p; + continue; + case syntax_element_alt: + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + // just push the state onto our stack for now: + v.push_back(std::pair(m_icase, state)); + state = state->next.p; + break; + case syntax_element_backstep: + // we need to calculate how big the backstep is: + static_cast(state)->index + = this->calculate_backstep(state->next.p); + if(static_cast(state)->index < 0) + { + // Oops error: + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = boost::regex_constants::error_bad_pattern; + // + // clear the expression, we should be empty: + // + this->m_pdata->m_expression = 0; + this->m_pdata->m_expression_len = 0; + // + // and throw if required: + // + if(0 == (this->flags() & regex_constants::no_except)) + { + std::string message = "Invalid lookbehind assertion encountered in the regular expression."; + boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0); + e.raise(); + } + } + BOOST_FALLTHROUGH; + default: + state = state->next.p; + } + } + + // now work through our list, building all the maps as we go: + while(!v.empty()) + { + // Initialize m_recursion_checks if we need it: + if(m_has_recursions) + m_recursion_checks.assign(1 + m_pdata->m_mark_count, 0u); + + const std::pair& p = v.back(); + m_icase = p.first; + state = p.second; + v.pop_back(); + + // Build maps: + m_bad_repeats = 0; + create_startmap(state->next.p, static_cast(state)->_map, &static_cast(state)->can_be_null, mask_take); + m_bad_repeats = 0; + + if(m_has_recursions) + m_recursion_checks.assign(1 + m_pdata->m_mark_count, 0u); + create_startmap(static_cast(state)->alt.p, static_cast(state)->_map, &static_cast(state)->can_be_null, mask_skip); + // adjust the type of the state to allow for faster matching: + state->type = this->get_repeat_type(state); + } + // restore case sensitivity: + m_icase = l_icase; +} + +template +int basic_regex_creator::calculate_backstep(re_syntax_base* state) +{ + typedef typename traits::char_class_type m_type; + int result = 0; + while(state) + { + switch(state->type) + { + case syntax_element_startmark: + if((static_cast(state)->index == -1) + || (static_cast(state)->index == -2)) + { + state = static_cast(state->next.p)->alt.p->next.p; + continue; + } + else if(static_cast(state)->index == -3) + { + state = state->next.p->next.p; + continue; + } + break; + case syntax_element_endmark: + if((static_cast(state)->index == -1) + || (static_cast(state)->index == -2)) + return result; + break; + case syntax_element_literal: + result += static_cast(state)->length; + break; + case syntax_element_wild: + case syntax_element_set: + result += 1; + break; + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_backref: + case syntax_element_rep: + case syntax_element_combining: + case syntax_element_long_set_rep: + case syntax_element_backstep: + { + re_repeat* rep = static_cast(state); + // adjust the type of the state to allow for faster matching: + state->type = this->get_repeat_type(state); + if((state->type == syntax_element_dot_rep) + || (state->type == syntax_element_char_rep) + || (state->type == syntax_element_short_set_rep)) + { + if(rep->max != rep->min) + return -1; + result += static_cast(rep->min); + state = rep->alt.p; + continue; + } + else if(state->type == syntax_element_long_set_rep) + { + BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_long_set); + if(static_cast*>(rep->next.p)->singleton == 0) + return -1; + if(rep->max != rep->min) + return -1; + result += static_cast(rep->min); + state = rep->alt.p; + continue; + } + } + return -1; + case syntax_element_long_set: + if(static_cast*>(state)->singleton == 0) + return -1; + result += 1; + break; + case syntax_element_jump: + state = static_cast(state)->alt.p; + continue; + case syntax_element_alt: + { + int r1 = calculate_backstep(state->next.p); + int r2 = calculate_backstep(static_cast(state)->alt.p); + if((r1 < 0) || (r1 != r2)) + return -1; + return result + r1; + } + default: + break; + } + state = state->next.p; + } + return -1; +} + +struct recursion_saver +{ + std::vector saved_state; + std::vector* state; + recursion_saver(std::vector* p) : saved_state(*p), state(p) {} + ~recursion_saver() + { + state->swap(saved_state); + } +}; + +template +void basic_regex_creator::create_startmap(re_syntax_base* state, unsigned char* l_map, unsigned int* pnull, unsigned char mask) +{ + recursion_saver saved_recursions(&m_recursion_checks); + int not_last_jump = 1; + re_syntax_base* recursion_start = 0; + int recursion_sub = 0; + re_syntax_base* recursion_restart = 0; + + // track case sensitivity: + bool l_icase = m_icase; + + while(state) + { + switch(state->type) + { + case syntax_element_toggle_case: + l_icase = static_cast(state)->icase; + state = state->next.p; + break; + case syntax_element_literal: + { + // don't set anything in *pnull, set each element in l_map + // that could match the first character in the literal: + if(l_map) + { + l_map[0] |= mask_init; + charT first_char = *static_cast(static_cast(static_cast(state) + 1)); + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + if(m_traits.translate(static_cast(i), l_icase) == first_char) + l_map[i] |= mask; + } + } + return; + } + case syntax_element_end_line: + { + // next character must be a line separator (if there is one): + if(l_map) + { + l_map[0] |= mask_init; + l_map[static_cast('\n')] |= mask; + l_map[static_cast('\r')] |= mask; + l_map[static_cast('\f')] |= mask; + l_map[0x85] |= mask; + } + // now figure out if we can match a NULL string at this point: + if(pnull) + create_startmap(state->next.p, 0, pnull, mask); + return; + } + case syntax_element_recurse: + { + BOOST_REGEX_ASSERT(static_cast(state)->alt.p->type == syntax_element_startmark); + recursion_sub = static_cast(static_cast(state)->alt.p)->index; + if(m_recursion_checks[recursion_sub] & 1u) + { + // Infinite recursion!! + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = boost::regex_constants::error_bad_pattern; + // + // clear the expression, we should be empty: + // + this->m_pdata->m_expression = 0; + this->m_pdata->m_expression_len = 0; + // + // and throw if required: + // + if(0 == (this->flags() & regex_constants::no_except)) + { + std::string message = "Encountered an infinite recursion."; + boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0); + e.raise(); + } + } + else if(recursion_start == 0) + { + recursion_start = state; + recursion_restart = state->next.p; + state = static_cast(state)->alt.p; + m_recursion_checks[recursion_sub] |= 1u; + break; + } + m_recursion_checks[recursion_sub] |= 1u; + // can't handle nested recursion here... + BOOST_FALLTHROUGH; + } + case syntax_element_backref: + // can be null, and any character can match: + if(pnull) + *pnull |= mask; + BOOST_FALLTHROUGH; + case syntax_element_wild: + { + // can't be null, any character can match: + set_all_masks(l_map, mask); + return; + } + case syntax_element_accept: + case syntax_element_match: + { + // must be null, any character can match: + set_all_masks(l_map, mask); + if(pnull) + *pnull |= mask; + return; + } + case syntax_element_word_start: + { + // recurse, then AND with all the word characters: + create_startmap(state->next.p, l_map, pnull, mask); + if(l_map) + { + l_map[0] |= mask_init; + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + if(!m_traits.isctype(static_cast(i), m_word_mask)) + l_map[i] &= static_cast(~mask); + } + } + return; + } + case syntax_element_word_end: + { + // recurse, then AND with all the word characters: + create_startmap(state->next.p, l_map, pnull, mask); + if(l_map) + { + l_map[0] |= mask_init; + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + if(m_traits.isctype(static_cast(i), m_word_mask)) + l_map[i] &= static_cast(~mask); + } + } + return; + } + case syntax_element_buffer_end: + { + // we *must be null* : + if(pnull) + *pnull |= mask; + return; + } + case syntax_element_long_set: + if(l_map) + { + typedef typename traits::char_class_type m_type; + if(static_cast*>(state)->singleton) + { + l_map[0] |= mask_init; + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + charT c = static_cast(i); + if(&c != re_is_set_member(&c, &c + 1, static_cast*>(state), *m_pdata, l_icase)) + l_map[i] |= mask; + } + } + else + set_all_masks(l_map, mask); + } + return; + case syntax_element_set: + if(l_map) + { + l_map[0] |= mask_init; + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + if(static_cast(state)->_map[ + static_cast(m_traits.translate(static_cast(i), l_icase))]) + l_map[i] |= mask; + } + } + return; + case syntax_element_jump: + // take the jump: + state = static_cast(state)->alt.p; + not_last_jump = -1; + break; + case syntax_element_alt: + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + { + re_alt* rep = static_cast(state); + if(rep->_map[0] & mask_init) + { + if(l_map) + { + // copy previous results: + l_map[0] |= mask_init; + for(unsigned int i = 0; i <= UCHAR_MAX; ++i) + { + if(rep->_map[i] & mask_any) + l_map[i] |= mask; + } + } + if(pnull) + { + if(rep->can_be_null & mask_any) + *pnull |= mask; + } + } + else + { + // we haven't created a startmap for this alternative yet + // so take the union of the two options: + if(is_bad_repeat(state)) + { + set_all_masks(l_map, mask); + if(pnull) + *pnull |= mask; + return; + } + set_bad_repeat(state); + create_startmap(state->next.p, l_map, pnull, mask); + if((state->type == syntax_element_alt) + || (static_cast(state)->min == 0) + || (not_last_jump == 0)) + create_startmap(rep->alt.p, l_map, pnull, mask); + } + } + return; + case syntax_element_soft_buffer_end: + // match newline or null: + if(l_map) + { + l_map[0] |= mask_init; + l_map[static_cast('\n')] |= mask; + l_map[static_cast('\r')] |= mask; + } + if(pnull) + *pnull |= mask; + return; + case syntax_element_endmark: + // need to handle independent subs as a special case: + if(static_cast(state)->index < 0) + { + // can be null, any character can match: + set_all_masks(l_map, mask); + if(pnull) + *pnull |= mask; + return; + } + else if(recursion_start && (recursion_sub != 0) && (recursion_sub == static_cast(state)->index)) + { + // recursion termination: + recursion_start = 0; + state = recursion_restart; + break; + } + + // + // Normally we just go to the next state... but if this sub-expression is + // the target of a recursion, then we might be ending a recursion, in which + // case we should check whatever follows that recursion, as well as whatever + // follows this state: + // + if(m_pdata->m_has_recursions && static_cast(state)->index) + { + bool ok = false; + re_syntax_base* p = m_pdata->m_first_state; + while(p) + { + if(p->type == syntax_element_recurse) + { + re_brace* p2 = static_cast(static_cast(p)->alt.p); + if((p2->type == syntax_element_startmark) && (p2->index == static_cast(state)->index)) + { + ok = true; + break; + } + } + p = p->next.p; + } + if(ok && ((m_recursion_checks[static_cast(state)->index] & 2u) == 0)) + { + m_recursion_checks[static_cast(state)->index] |= 2u; + create_startmap(p->next.p, l_map, pnull, mask); + } + } + state = state->next.p; + break; + + case syntax_element_commit: + set_all_masks(l_map, mask); + // Continue scanning so we can figure out whether we can be null: + state = state->next.p; + break; + case syntax_element_startmark: + // need to handle independent subs as a special case: + if(static_cast(state)->index == -3) + { + state = state->next.p->next.p; + break; + } + BOOST_FALLTHROUGH; + default: + state = state->next.p; + } + ++not_last_jump; + } +} + +template +unsigned basic_regex_creator::get_restart_type(re_syntax_base* state) +{ + // + // find out how the machine starts, so we can optimise the search: + // + while(state) + { + switch(state->type) + { + case syntax_element_startmark: + case syntax_element_endmark: + state = state->next.p; + continue; + case syntax_element_start_line: + return regbase::restart_line; + case syntax_element_word_start: + return regbase::restart_word; + case syntax_element_buffer_start: + return regbase::restart_buf; + case syntax_element_restart_continue: + return regbase::restart_continue; + default: + state = 0; + continue; + } + } + return regbase::restart_any; +} + +template +void basic_regex_creator::set_all_masks(unsigned char* bits, unsigned char mask) +{ + // + // set mask in all of bits elements, + // if bits[0] has mask_init not set then we can + // optimise this to a call to memset: + // + if(bits) + { + if(bits[0] == 0) + (std::memset)(bits, mask, 1u << CHAR_BIT); + else + { + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + bits[i] |= mask; + } + bits[0] |= mask_init; + } +} + +template +bool basic_regex_creator::is_bad_repeat(re_syntax_base* pt) +{ + switch(pt->type) + { + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + { + unsigned state_id = static_cast(pt)->state_id; + if(state_id >= sizeof(m_bad_repeats) * CHAR_BIT) + return true; // run out of bits, assume we can't traverse this one. + static const boost::uintmax_t one = 1uL; + return m_bad_repeats & (one << state_id); + } + default: + return false; + } +} + +template +void basic_regex_creator::set_bad_repeat(re_syntax_base* pt) +{ + switch(pt->type) + { + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + { + unsigned state_id = static_cast(pt)->state_id; + static const boost::uintmax_t one = 1uL; + if(state_id <= sizeof(m_bad_repeats) * CHAR_BIT) + m_bad_repeats |= (one << state_id); + } + break; + default: + break; + } +} + +template +syntax_element_type basic_regex_creator::get_repeat_type(re_syntax_base* state) +{ + typedef typename traits::char_class_type m_type; + if(state->type == syntax_element_rep) + { + // check to see if we are repeating a single state: + if(state->next.p->next.p->next.p == static_cast(state)->alt.p) + { + switch(state->next.p->type) + { + case BOOST_REGEX_DETAIL_NS::syntax_element_wild: + return BOOST_REGEX_DETAIL_NS::syntax_element_dot_rep; + case BOOST_REGEX_DETAIL_NS::syntax_element_literal: + return BOOST_REGEX_DETAIL_NS::syntax_element_char_rep; + case BOOST_REGEX_DETAIL_NS::syntax_element_set: + return BOOST_REGEX_DETAIL_NS::syntax_element_short_set_rep; + case BOOST_REGEX_DETAIL_NS::syntax_element_long_set: + if(static_cast*>(state->next.p)->singleton) + return BOOST_REGEX_DETAIL_NS::syntax_element_long_set_rep; + break; + default: + break; + } + } + } + return state->type; +} + +template +void basic_regex_creator::probe_leading_repeat(re_syntax_base* state) +{ + // enumerate our states, and see if we have a leading repeat + // for which failed search restarts can be optimized; + do + { + switch(state->type) + { + case syntax_element_startmark: + if(static_cast(state)->index >= 0) + { + state = state->next.p; + continue; + } +#ifdef BOOST_MSVC +# pragma warning(push) +#pragma warning(disable:6011) +#endif + if((static_cast(state)->index == -1) + || (static_cast(state)->index == -2)) + { + // skip past the zero width assertion: + state = static_cast(state->next.p)->alt.p->next.p; + continue; + } +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + if(static_cast(state)->index == -3) + { + // Have to skip the leading jump state: + state = state->next.p->next.p; + continue; + } + return; + case syntax_element_endmark: + case syntax_element_start_line: + case syntax_element_end_line: + case syntax_element_word_boundary: + case syntax_element_within_word: + case syntax_element_word_start: + case syntax_element_word_end: + case syntax_element_buffer_start: + case syntax_element_buffer_end: + case syntax_element_restart_continue: + state = state->next.p; + break; + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + if(this->m_has_backrefs == 0) + static_cast(state)->leading = true; + BOOST_FALLTHROUGH; + default: + return; + } + }while(state); +} + +} // namespace BOOST_REGEX_DETAIL_NS + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif diff --git a/boost/regex/v4/basic_regex_parser.hpp b/boost/regex/v4/basic_regex_parser.hpp new file mode 100644 index 00000000..1b7121f0 --- /dev/null +++ b/boost/regex/v4/basic_regex_parser.hpp @@ -0,0 +1,3174 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE basic_regex_parser.cpp + * VERSION see + * DESCRIPTION: Declares template class basic_regex_parser. + */ + +#ifndef BOOST_REGEX_V4_BASIC_REGEX_PARSER_HPP +#define BOOST_REGEX_V4_BASIC_REGEX_PARSER_HPP + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#if BOOST_MSVC >= 1800 +#pragma warning(disable: 26812) +#endif +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4244) +#if BOOST_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +inline boost::intmax_t umax(mpl::false_ const&) +{ + // Get out clause here, just in case numeric_limits is unspecialized: + return std::numeric_limits::is_specialized ? (std::numeric_limits::max)() : INT_MAX; +} +inline boost::intmax_t umax(mpl::true_ const&) +{ + return (std::numeric_limits::max)(); +} + +inline boost::intmax_t umax() +{ + return umax(mpl::bool_::digits >= std::numeric_limits::digits>()); +} + +template +class basic_regex_parser : public basic_regex_creator +{ +public: + basic_regex_parser(regex_data* data); + void parse(const charT* p1, const charT* p2, unsigned flags); + void fail(regex_constants::error_type error_code, std::ptrdiff_t position); + void fail(regex_constants::error_type error_code, std::ptrdiff_t position, std::string message, std::ptrdiff_t start_pos); + void fail(regex_constants::error_type error_code, std::ptrdiff_t position, const std::string& message) + { + fail(error_code, position, message, position); + } + + bool parse_all(); + bool parse_basic(); + bool parse_extended(); + bool parse_literal(); + bool parse_open_paren(); + bool parse_basic_escape(); + bool parse_extended_escape(); + bool parse_match_any(); + bool parse_repeat(std::size_t low = 0, std::size_t high = (std::numeric_limits::max)()); + bool parse_repeat_range(bool isbasic); + bool parse_alt(); + bool parse_set(); + bool parse_backref(); + void parse_set_literal(basic_char_set& char_set); + bool parse_inner_set(basic_char_set& char_set); + bool parse_QE(); + bool parse_perl_extension(); + bool parse_perl_verb(); + bool match_verb(const char*); + bool add_emacs_code(bool negate); + bool unwind_alts(std::ptrdiff_t last_paren_start); + digraph get_next_set_literal(basic_char_set& char_set); + charT unescape_character(); + regex_constants::syntax_option_type parse_options(); + +private: + typedef bool (basic_regex_parser::*parser_proc_type)(); + typedef typename traits::string_type string_type; + typedef typename traits::char_class_type char_class_type; + parser_proc_type m_parser_proc; // the main parser to use + const charT* m_base; // the start of the string being parsed + const charT* m_end; // the end of the string being parsed + const charT* m_position; // our current parser position + unsigned m_mark_count; // how many sub-expressions we have + int m_mark_reset; // used to indicate that we're inside a (?|...) block. + unsigned m_max_mark; // largest mark count seen inside a (?|...) block. + std::ptrdiff_t m_paren_start; // where the last seen ')' began (where repeats are inserted). + std::ptrdiff_t m_alt_insert_point; // where to insert the next alternative + bool m_has_case_change; // true if somewhere in the current block the case has changed + unsigned m_recursion_count; // How many times we've called parse_all. +#if defined(BOOST_MSVC) && defined(_M_IX86) + // This is an ugly warning suppression workaround (for warnings *inside* std::vector + // that can not otherwise be suppressed)... + BOOST_STATIC_ASSERT(sizeof(long) >= sizeof(void*)); + std::vector m_alt_jumps; // list of alternative in the current scope. +#else + std::vector m_alt_jumps; // list of alternative in the current scope. +#endif + + basic_regex_parser& operator=(const basic_regex_parser&); + basic_regex_parser(const basic_regex_parser&); +}; + +template +basic_regex_parser::basic_regex_parser(regex_data* data) + : basic_regex_creator(data), m_parser_proc(), m_base(0), m_end(0), m_position(0), + m_mark_count(0), m_mark_reset(-1), m_max_mark(0), m_paren_start(0), m_alt_insert_point(0), m_has_case_change(false), m_recursion_count(0) +{ +} + +template +void basic_regex_parser::parse(const charT* p1, const charT* p2, unsigned l_flags) +{ + // pass l_flags on to base class: + this->init(l_flags); + // set up pointers: + m_position = m_base = p1; + m_end = p2; + // empty strings are errors: + if((p1 == p2) && + ( + ((l_flags & regbase::main_option_type) != regbase::perl_syntax_group) + || (l_flags & regbase::no_empty_expressions) + ) + ) + { + fail(regex_constants::error_empty, 0); + return; + } + // select which parser to use: + switch(l_flags & regbase::main_option_type) + { + case regbase::perl_syntax_group: + { + m_parser_proc = &basic_regex_parser::parse_extended; + // + // Add a leading paren with index zero to give recursions a target: + // + re_brace* br = static_cast(this->append_state(syntax_element_startmark, sizeof(re_brace))); + br->index = 0; + br->icase = this->flags() & regbase::icase; + break; + } + case regbase::basic_syntax_group: + m_parser_proc = &basic_regex_parser::parse_basic; + break; + case regbase::literal: + m_parser_proc = &basic_regex_parser::parse_literal; + break; + default: + // Oops, someone has managed to set more than one of the main option flags, + // so this must be an error: + fail(regex_constants::error_unknown, 0, "An invalid combination of regular expression syntax flags was used."); + return; + } + + // parse all our characters: + bool result = parse_all(); + // + // Unwind our alternatives: + // + unwind_alts(-1); + // reset l_flags as a global scope (?imsx) may have altered them: + this->flags(l_flags); + // if we haven't gobbled up all the characters then we must + // have had an unexpected ')' : + if(!result) + { + fail(regex_constants::error_paren, ::boost::BOOST_REGEX_DETAIL_NS::distance(m_base, m_position), "Found a closing ) with no corresponding opening parenthesis."); + return; + } + // if an error has been set then give up now: + if(this->m_pdata->m_status) + return; + // fill in our sub-expression count: + this->m_pdata->m_mark_count = 1u + (std::size_t)m_mark_count; + this->finalize(p1, p2); +} + +template +void basic_regex_parser::fail(regex_constants::error_type error_code, std::ptrdiff_t position) +{ + // get the error message: + std::string message = this->m_pdata->m_ptraits->error_string(error_code); + fail(error_code, position, message); +} + +template +void basic_regex_parser::fail(regex_constants::error_type error_code, std::ptrdiff_t position, std::string message, std::ptrdiff_t start_pos) +{ + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = error_code; + m_position = m_end; // don't bother parsing anything else + +#ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS + // + // Augment error message with the regular expression text: + // + if(start_pos == position) + start_pos = (std::max)(static_cast(0), position - static_cast(10)); + std::ptrdiff_t end_pos = (std::min)(position + static_cast(10), static_cast(m_end - m_base)); + if(error_code != regex_constants::error_empty) + { + if((start_pos != 0) || (end_pos != (m_end - m_base))) + message += " The error occurred while parsing the regular expression fragment: '"; + else + message += " The error occurred while parsing the regular expression: '"; + if(start_pos != end_pos) + { + message += std::string(m_base + start_pos, m_base + position); + message += ">>>HERE>>>"; + message += std::string(m_base + position, m_base + end_pos); + } + message += "'."; + } +#endif + +#ifndef BOOST_NO_EXCEPTIONS + if(0 == (this->flags() & regex_constants::no_except)) + { + boost::regex_error e(message, error_code, position); + e.raise(); + } +#else + (void)position; // suppress warnings. +#endif +} + +template +bool basic_regex_parser::parse_all() +{ + if (++m_recursion_count > 400) + { + // exceeded internal limits + fail(boost::regex_constants::error_complexity, m_position - m_base, "Exceeded nested brace limit."); + } + bool result = true; + while(result && (m_position != m_end)) + { + result = (this->*m_parser_proc)(); + } + --m_recursion_count; + return result; +} + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4702) +#endif +template +bool basic_regex_parser::parse_basic() +{ + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_escape: + return parse_basic_escape(); + case regex_constants::syntax_dot: + return parse_match_any(); + case regex_constants::syntax_caret: + ++m_position; + this->append_state(syntax_element_start_line); + break; + case regex_constants::syntax_dollar: + ++m_position; + this->append_state(syntax_element_end_line); + break; + case regex_constants::syntax_star: + if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line)) + return parse_literal(); + else + { + ++m_position; + return parse_repeat(); + } + case regex_constants::syntax_plus: + if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line) || !(this->flags() & regbase::emacs_ex)) + return parse_literal(); + else + { + ++m_position; + return parse_repeat(1); + } + case regex_constants::syntax_question: + if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line) || !(this->flags() & regbase::emacs_ex)) + return parse_literal(); + else + { + ++m_position; + return parse_repeat(0, 1); + } + case regex_constants::syntax_open_set: + return parse_set(); + case regex_constants::syntax_newline: + if(this->flags() & regbase::newline_alt) + return parse_alt(); + else + return parse_literal(); + default: + return parse_literal(); + } + return true; +} + +#ifdef BOOST_MSVC +# pragma warning(push) +#if BOOST_MSVC >= 1800 +#pragma warning(disable:26812) +#endif +#endif +template +bool basic_regex_parser::parse_extended() +{ + bool result = true; + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_open_mark: + return parse_open_paren(); + case regex_constants::syntax_close_mark: + return false; + case regex_constants::syntax_escape: + return parse_extended_escape(); + case regex_constants::syntax_dot: + return parse_match_any(); + case regex_constants::syntax_caret: + ++m_position; + this->append_state( + (this->flags() & regex_constants::no_mod_m ? syntax_element_buffer_start : syntax_element_start_line)); + break; + case regex_constants::syntax_dollar: + ++m_position; + this->append_state( + (this->flags() & regex_constants::no_mod_m ? syntax_element_buffer_end : syntax_element_end_line)); + break; + case regex_constants::syntax_star: + if(m_position == this->m_base) + { + fail(regex_constants::error_badrepeat, 0, "The repeat operator \"*\" cannot start a regular expression."); + return false; + } + ++m_position; + return parse_repeat(); + case regex_constants::syntax_question: + if(m_position == this->m_base) + { + fail(regex_constants::error_badrepeat, 0, "The repeat operator \"?\" cannot start a regular expression."); + return false; + } + ++m_position; + return parse_repeat(0,1); + case regex_constants::syntax_plus: + if(m_position == this->m_base) + { + fail(regex_constants::error_badrepeat, 0, "The repeat operator \"+\" cannot start a regular expression."); + return false; + } + ++m_position; + return parse_repeat(1); + case regex_constants::syntax_open_brace: + ++m_position; + return parse_repeat_range(false); + case regex_constants::syntax_close_brace: + if((this->flags() & regbase::no_perl_ex) == regbase::no_perl_ex) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, "Found a closing repetition operator } with no corresponding {."); + return false; + } + result = parse_literal(); + break; + case regex_constants::syntax_or: + return parse_alt(); + case regex_constants::syntax_open_set: + return parse_set(); + case regex_constants::syntax_newline: + if(this->flags() & regbase::newline_alt) + return parse_alt(); + else + return parse_literal(); + case regex_constants::syntax_hash: + // + // If we have a mod_x flag set, then skip until + // we get to a newline character: + // + if((this->flags() + & (regbase::no_perl_ex|regbase::mod_x)) + == regbase::mod_x) + { + while((m_position != m_end) && !is_separator(*m_position++)){} + return true; + } + BOOST_FALLTHROUGH; + default: + result = parse_literal(); + break; + } + return result; +} +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +template +bool basic_regex_parser::parse_literal() +{ + // append this as a literal provided it's not a space character + // or the perl option regbase::mod_x is not set: + if( + ((this->flags() + & (regbase::main_option_type|regbase::mod_x|regbase::no_perl_ex)) + != regbase::mod_x) + || !this->m_traits.isctype(*m_position, this->m_mask_space)) + this->append_literal(*m_position); + ++m_position; + return true; +} + +template +bool basic_regex_parser::parse_open_paren() +{ + // + // skip the '(' and error check: + // + if(++m_position == m_end) + { + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + // + // begin by checking for a perl-style (?...) extension: + // + if( + ((this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) == 0) + || ((this->flags() & (regbase::main_option_type | regbase::emacs_ex)) == (regbase::basic_syntax_group|regbase::emacs_ex)) + ) + { + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_question) + return parse_perl_extension(); + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_star) + return parse_perl_verb(); + } + // + // update our mark count, and append the required state: + // + unsigned markid = 0; + if(0 == (this->flags() & regbase::nosubs)) + { + markid = ++m_mark_count; +#ifndef BOOST_NO_STD_DISTANCE + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.push_back(std::pair(std::distance(m_base, m_position) - 1, 0)); +#else + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.push_back(std::pair((m_position - m_base) - 1, 0)); +#endif + } + re_brace* pb = static_cast(this->append_state(syntax_element_startmark, sizeof(re_brace))); + pb->index = markid; + pb->icase = this->flags() & regbase::icase; + std::ptrdiff_t last_paren_start = this->getoffset(pb); + // back up insertion point for alternations, and set new point: + std::ptrdiff_t last_alt_point = m_alt_insert_point; + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + // + // back up the current flags in case we have a nested (?imsx) group: + // + regex_constants::syntax_option_type opts = this->flags(); + bool old_case_change = m_has_case_change; + m_has_case_change = false; // no changes to this scope as yet... + // + // Back up branch reset data in case we have a nested (?|...) + // + int mark_reset = m_mark_reset; + m_mark_reset = -1; + // + // now recursively add more states, this will terminate when we get to a + // matching ')' : + // + parse_all(); + // + // Unwind pushed alternatives: + // + if(0 == unwind_alts(last_paren_start)) + return false; + // + // restore flags: + // + if(m_has_case_change) + { + // the case has changed in one or more of the alternatives + // within the scoped (...) block: we have to add a state + // to reset the case sensitivity: + static_cast( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = opts & regbase::icase; + } + this->flags(opts); + m_has_case_change = old_case_change; + // + // restore branch reset: + // + m_mark_reset = mark_reset; + // + // we either have a ')' or we have run out of characters prematurely: + // + if(m_position == m_end) + { + this->fail(regex_constants::error_paren, ::boost::BOOST_REGEX_DETAIL_NS::distance(m_base, m_end)); + return false; + } + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + return false; +#ifndef BOOST_NO_STD_DISTANCE + if(markid && (this->flags() & regbase::save_subexpression_location)) + this->m_pdata->m_subs.at(markid - 1).second = std::distance(m_base, m_position); +#else + if(markid && (this->flags() & regbase::save_subexpression_location)) + this->m_pdata->m_subs.at(markid - 1).second = (m_position - m_base); +#endif + ++m_position; + // + // append closing parenthesis state: + // + pb = static_cast(this->append_state(syntax_element_endmark, sizeof(re_brace))); + pb->index = markid; + pb->icase = this->flags() & regbase::icase; + this->m_paren_start = last_paren_start; + // + // restore the alternate insertion point: + // + this->m_alt_insert_point = last_alt_point; + // + // allow backrefs to this mark: + // + if(markid > 0) + this->m_backrefs.set(markid); + + return true; +} + +template +bool basic_regex_parser::parse_basic_escape() +{ + if(++m_position == m_end) + { + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + bool result = true; + switch(this->m_traits.escape_syntax_type(*m_position)) + { + case regex_constants::syntax_open_mark: + return parse_open_paren(); + case regex_constants::syntax_close_mark: + return false; + case regex_constants::syntax_plus: + if(this->flags() & regex_constants::bk_plus_qm) + { + ++m_position; + return parse_repeat(1); + } + else + return parse_literal(); + case regex_constants::syntax_question: + if(this->flags() & regex_constants::bk_plus_qm) + { + ++m_position; + return parse_repeat(0, 1); + } + else + return parse_literal(); + case regex_constants::syntax_open_brace: + if(this->flags() & regbase::no_intervals) + return parse_literal(); + ++m_position; + return parse_repeat_range(true); + case regex_constants::syntax_close_brace: + if(this->flags() & regbase::no_intervals) + return parse_literal(); + fail(regex_constants::error_brace, this->m_position - this->m_base, "Found a closing repetition operator } with no corresponding {."); + return false; + case regex_constants::syntax_or: + if(this->flags() & regbase::bk_vbar) + return parse_alt(); + else + result = parse_literal(); + break; + case regex_constants::syntax_digit: + return parse_backref(); + case regex_constants::escape_type_start_buffer: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_buffer_start); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_end_buffer: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_buffer_end); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_word_assert: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_word_boundary); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_not_word_assert: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_within_word); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_left_word: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_word_start); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_right_word: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_word_end); + } + else + result = parse_literal(); + break; + default: + if(this->flags() & regbase::emacs_ex) + { + bool negate = true; + switch(*m_position) + { + case 'w': + negate = false; + BOOST_FALLTHROUGH; + case 'W': + { + basic_char_set char_set; + if(negate) + char_set.negate(); + char_set.add_class(this->m_word_mask); + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + ++m_position; + return true; + } + case 's': + negate = false; + BOOST_FALLTHROUGH; + case 'S': + return add_emacs_code(negate); + case 'c': + case 'C': + // not supported yet: + fail(regex_constants::error_escape, m_position - m_base, "The \\c and \\C escape sequences are not supported by POSIX basic regular expressions: try the Perl syntax instead."); + return false; + default: + break; + } + } + result = parse_literal(); + break; + } + return result; +} + +template +bool basic_regex_parser::parse_extended_escape() +{ + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base, "Incomplete escape sequence found."); + return false; + } + bool negate = false; // in case this is a character class escape: \w \d etc + switch(this->m_traits.escape_syntax_type(*m_position)) + { + case regex_constants::escape_type_not_class: + negate = true; + BOOST_FALLTHROUGH; + case regex_constants::escape_type_class: + { +escape_type_class_jump: + typedef typename traits::char_class_type m_type; + m_type m = this->m_traits.lookup_classname(m_position, m_position+1); + if(m != 0) + { + basic_char_set char_set; + if(negate) + char_set.negate(); + char_set.add_class(m); + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + ++m_position; + return true; + } + // + // not a class, just a regular unknown escape: + // + this->append_literal(unescape_character()); + break; + } + case regex_constants::syntax_digit: + return parse_backref(); + case regex_constants::escape_type_left_word: + ++m_position; + this->append_state(syntax_element_word_start); + break; + case regex_constants::escape_type_right_word: + ++m_position; + this->append_state(syntax_element_word_end); + break; + case regex_constants::escape_type_start_buffer: + ++m_position; + this->append_state(syntax_element_buffer_start); + break; + case regex_constants::escape_type_end_buffer: + ++m_position; + this->append_state(syntax_element_buffer_end); + break; + case regex_constants::escape_type_word_assert: + ++m_position; + this->append_state(syntax_element_word_boundary); + break; + case regex_constants::escape_type_not_word_assert: + ++m_position; + this->append_state(syntax_element_within_word); + break; + case regex_constants::escape_type_Z: + ++m_position; + this->append_state(syntax_element_soft_buffer_end); + break; + case regex_constants::escape_type_Q: + return parse_QE(); + case regex_constants::escape_type_C: + return parse_match_any(); + case regex_constants::escape_type_X: + ++m_position; + this->append_state(syntax_element_combining); + break; + case regex_constants::escape_type_G: + ++m_position; + this->append_state(syntax_element_restart_continue); + break; + case regex_constants::escape_type_not_property: + negate = true; + BOOST_FALLTHROUGH; + case regex_constants::escape_type_property: + { + ++m_position; + char_class_type m; + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base, "Incomplete property escape found."); + return false; + } + // maybe have \p{ddd} + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace) + { + const charT* base = m_position; + // skip forward until we find enclosing brace: + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace)) + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base, "Closing } missing from property escape sequence."); + return false; + } + m = this->m_traits.lookup_classname(++base, m_position++); + } + else + { + m = this->m_traits.lookup_classname(m_position, m_position+1); + ++m_position; + } + if(m != 0) + { + basic_char_set char_set; + if(negate) + char_set.negate(); + char_set.add_class(m); + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + return true; + } + fail(regex_constants::error_ctype, m_position - m_base, "Escape sequence was neither a valid property nor a valid character class name."); + return false; + } + case regex_constants::escape_type_reset_start_mark: + if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + { + re_brace* pb = static_cast(this->append_state(syntax_element_startmark, sizeof(re_brace))); + pb->index = -5; + pb->icase = this->flags() & regbase::icase; + this->m_pdata->m_data.align(); + ++m_position; + return true; + } + goto escape_type_class_jump; + case regex_constants::escape_type_line_ending: + if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + { + const charT* e = get_escape_R_string(); + const charT* old_position = m_position; + const charT* old_end = m_end; + const charT* old_base = m_base; + m_position = e; + m_base = e; + m_end = e + traits::length(e); + bool r = parse_all(); + m_position = ++old_position; + m_end = old_end; + m_base = old_base; + return r; + } + goto escape_type_class_jump; + case regex_constants::escape_type_extended_backref: + if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + { + bool have_brace = false; + bool negative = false; + static const char incomplete_message[] = "Incomplete \\g escape found."; + if(++m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base, incomplete_message); + return false; + } + // maybe have \g{ddd} + regex_constants::syntax_type syn = this->m_traits.syntax_type(*m_position); + regex_constants::syntax_type syn_end = 0; + if((syn == regex_constants::syntax_open_brace) + || (syn == regex_constants::escape_type_left_word) + || (syn == regex_constants::escape_type_end_buffer)) + { + if(++m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base, incomplete_message); + return false; + } + have_brace = true; + switch(syn) + { + case regex_constants::syntax_open_brace: + syn_end = regex_constants::syntax_close_brace; + break; + case regex_constants::escape_type_left_word: + syn_end = regex_constants::escape_type_right_word; + break; + default: + syn_end = regex_constants::escape_type_end_buffer; + break; + } + } + negative = (*m_position == static_cast('-')); + if((negative) && (++m_position == m_end)) + { + fail(regex_constants::error_escape, m_position - m_base, incomplete_message); + return false; + } + const charT* pc = m_position; + boost::intmax_t i = this->m_traits.toi(pc, m_end, 10); + if((i < 0) && syn_end) + { + // Check for a named capture, get the leftmost one if there is more than one: + const charT* base = m_position; + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != syn_end)) + { + ++m_position; + } + i = hash_value_from_capture_name(base, m_position); + pc = m_position; + } + if(negative) + i = 1 + (static_cast(m_mark_count) - i); + if(((i < hash_value_mask) && (i > 0) && (this->m_backrefs.test(i))) || ((i >= hash_value_mask) && (this->m_pdata->get_id(i) > 0) && (this->m_backrefs.test(this->m_pdata->get_id(i))))) + { + m_position = pc; + re_brace* pb = static_cast(this->append_state(syntax_element_backref, sizeof(re_brace))); + pb->index = i; + pb->icase = this->flags() & regbase::icase; + } + else + { + fail(regex_constants::error_backref, m_position - m_base); + return false; + } + m_position = pc; + if(have_brace) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != syn_end)) + { + fail(regex_constants::error_escape, m_position - m_base, incomplete_message); + return false; + } + ++m_position; + } + return true; + } + goto escape_type_class_jump; + case regex_constants::escape_type_control_v: + if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + goto escape_type_class_jump; + BOOST_FALLTHROUGH; + default: + this->append_literal(unescape_character()); + break; + } + return true; +} + +template +bool basic_regex_parser::parse_match_any() +{ + // + // we have a '.' that can match any character: + // + ++m_position; + static_cast( + this->append_state(syntax_element_wild, sizeof(re_dot)) + )->mask = static_cast(this->flags() & regbase::no_mod_s + ? BOOST_REGEX_DETAIL_NS::force_not_newline + : this->flags() & regbase::mod_s ? + BOOST_REGEX_DETAIL_NS::force_newline : BOOST_REGEX_DETAIL_NS::dont_care); + return true; +} + +template +bool basic_regex_parser::parse_repeat(std::size_t low, std::size_t high) +{ + bool greedy = true; + bool possessive = false; + std::size_t insert_point; + // + // when we get to here we may have a non-greedy ? mark still to come: + // + if((m_position != m_end) + && ( + (0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + || ((regbase::basic_syntax_group|regbase::emacs_ex) == (this->flags() & (regbase::main_option_type | regbase::emacs_ex))) + ) + ) + { + // OK we have a perl or emacs regex, check for a '?': + if ((this->flags() & (regbase::main_option_type | regbase::mod_x | regbase::no_perl_ex)) == regbase::mod_x) + { + // whitespace skip: + while ((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + } + if((m_position != m_end) && (this->m_traits.syntax_type(*m_position) == regex_constants::syntax_question)) + { + greedy = false; + ++m_position; + } + // for perl regexes only check for possessive ++ repeats. + if((m_position != m_end) + && (0 == (this->flags() & regbase::main_option_type)) + && (this->m_traits.syntax_type(*m_position) == regex_constants::syntax_plus)) + { + possessive = true; + ++m_position; + } + } + if(0 == this->m_last_state) + { + fail(regex_constants::error_badrepeat, ::boost::BOOST_REGEX_DETAIL_NS::distance(m_base, m_position), "Nothing to repeat."); + return false; + } + if(this->m_last_state->type == syntax_element_endmark) + { + // insert a repeat before the '(' matching the last ')': + insert_point = this->m_paren_start; + } + else if((this->m_last_state->type == syntax_element_literal) && (static_cast(this->m_last_state)->length > 1)) + { + // the last state was a literal with more than one character, split it in two: + re_literal* lit = static_cast(this->m_last_state); + charT c = (static_cast(static_cast(lit+1)))[lit->length - 1]; + lit->length -= 1; + // now append new state: + lit = static_cast(this->append_state(syntax_element_literal, sizeof(re_literal) + sizeof(charT))); + lit->length = 1; + (static_cast(static_cast(lit+1)))[0] = c; + insert_point = this->getoffset(this->m_last_state); + } + else + { + // repeat the last state whatever it was, need to add some error checking here: + switch(this->m_last_state->type) + { + case syntax_element_start_line: + case syntax_element_end_line: + case syntax_element_word_boundary: + case syntax_element_within_word: + case syntax_element_word_start: + case syntax_element_word_end: + case syntax_element_buffer_start: + case syntax_element_buffer_end: + case syntax_element_alt: + case syntax_element_soft_buffer_end: + case syntax_element_restart_continue: + case syntax_element_jump: + case syntax_element_startmark: + case syntax_element_backstep: + case syntax_element_toggle_case: + // can't legally repeat any of the above: + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + default: + // do nothing... + break; + } + insert_point = this->getoffset(this->m_last_state); + } + // + // OK we now know what to repeat, so insert the repeat around it: + // + re_repeat* rep = static_cast(this->insert_state(insert_point, syntax_element_rep, re_repeater_size)); + rep->min = low; + rep->max = high; + rep->greedy = greedy; + rep->leading = false; + // store our repeater position for later: + std::ptrdiff_t rep_off = this->getoffset(rep); + // and append a back jump to the repeat: + re_jump* jmp = static_cast(this->append_state(syntax_element_jump, sizeof(re_jump))); + jmp->alt.i = rep_off - this->getoffset(jmp); + this->m_pdata->m_data.align(); + // now fill in the alt jump for the repeat: + rep = static_cast(this->getaddress(rep_off)); + rep->alt.i = this->m_pdata->m_data.size() - rep_off; + // + // If the repeat is possessive then bracket the repeat with a (?>...) + // independent sub-expression construct: + // + if(possessive) + { + if(m_position != m_end) + { + // + // Check for illegal following quantifier, we have to do this here, because + // the extra states we insert below circumvents our usual error checking :-( + // + bool contin = false; + do + { + if ((this->flags() & (regbase::main_option_type | regbase::mod_x | regbase::no_perl_ex)) == regbase::mod_x) + { + // whitespace skip: + while ((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + } + if (m_position != m_end) + { + switch (this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_star: + case regex_constants::syntax_plus: + case regex_constants::syntax_question: + case regex_constants::syntax_open_brace: + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + case regex_constants::syntax_open_mark: + // Do we have a comment? If so we need to skip it here... + if ((m_position + 2 < m_end) && this->m_traits.syntax_type(*(m_position + 1)) == regex_constants::syntax_question + && this->m_traits.syntax_type(*(m_position + 2)) == regex_constants::syntax_hash) + { + while ((m_position != m_end) + && (this->m_traits.syntax_type(*m_position++) != regex_constants::syntax_close_mark)) { + } + contin = true; + } + else + contin = false; + break; + default: + contin = false; + } + } + else + contin = false; + } while (contin); + } + re_brace* pb = static_cast(this->insert_state(insert_point, syntax_element_startmark, sizeof(re_brace))); + pb->index = -3; + pb->icase = this->flags() & regbase::icase; + jmp = static_cast(this->insert_state(insert_point + sizeof(re_brace), syntax_element_jump, sizeof(re_jump))); + this->m_pdata->m_data.align(); + jmp->alt.i = this->m_pdata->m_data.size() - this->getoffset(jmp); + pb = static_cast(this->append_state(syntax_element_endmark, sizeof(re_brace))); + pb->index = -3; + pb->icase = this->flags() & regbase::icase; + } + return true; +} + +template +bool basic_regex_parser::parse_repeat_range(bool isbasic) +{ + static const char incomplete_message[] = "Missing } in quantified repetition."; + // + // parse a repeat-range: + // + std::size_t min, max; + boost::intmax_t v; + // skip whitespace: + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + if(this->m_position == this->m_end) + { + if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + // Treat the opening '{' as a literal character, rewind to start of error: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position; + return parse_literal(); + } + // get min: + v = this->m_traits.toi(m_position, m_end, 10); + // skip whitespace: + if((v < 0) || (v > umax())) + { + if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + // Treat the opening '{' as a literal character, rewind to start of error: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position; + return parse_literal(); + } + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + if(this->m_position == this->m_end) + { + if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + // Treat the opening '{' as a literal character, rewind to start of error: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position; + return parse_literal(); + } + min = static_cast(v); + // see if we have a comma: + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_comma) + { + // move on and error check: + ++m_position; + // skip whitespace: + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + if(this->m_position == this->m_end) + { + if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + // Treat the opening '{' as a literal character, rewind to start of error: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position; + return parse_literal(); + } + // get the value if any: + v = this->m_traits.toi(m_position, m_end, 10); + max = ((v >= 0) && (v < umax())) ? (std::size_t)v : (std::numeric_limits::max)(); + } + else + { + // no comma, max = min: + max = min; + } + // skip whitespace: + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + // OK now check trailing }: + if(this->m_position == this->m_end) + { + if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + // Treat the opening '{' as a literal character, rewind to start of error: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position; + return parse_literal(); + } + if(isbasic) + { + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_escape) + { + ++m_position; + if(this->m_position == this->m_end) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + } + else + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + } + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_brace) + ++m_position; + else + { + // Treat the opening '{' as a literal character, rewind to start of error: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position; + return parse_literal(); + } + // + // finally go and add the repeat, unless error: + // + if(min > max) + { + // Backtrack to error location: + m_position -= 2; + while(this->m_traits.isctype(*m_position, this->m_word_mask)) --m_position; + ++m_position; + fail(regex_constants::error_badbrace, m_position - m_base); + return false; + } + return parse_repeat(min, max); +} + +template +bool basic_regex_parser::parse_alt() +{ + // + // error check: if there have been no previous states, + // or if the last state was a '(' then error: + // + if( + ((this->m_last_state == 0) || (this->m_last_state->type == syntax_element_startmark)) + && + !( + ((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) + && + ((this->flags() & regbase::no_empty_expressions) == 0) + ) + ) + { + fail(regex_constants::error_empty, this->m_position - this->m_base, "A regular expression cannot start with the alternation operator |."); + return false; + } + // + // Reset mark count if required: + // + if(m_max_mark < m_mark_count) + m_max_mark = m_mark_count; + if(m_mark_reset >= 0) + m_mark_count = m_mark_reset; + + ++m_position; + // + // we need to append a trailing jump: + // + re_syntax_base* pj = this->append_state(BOOST_REGEX_DETAIL_NS::syntax_element_jump, sizeof(re_jump)); + std::ptrdiff_t jump_offset = this->getoffset(pj); + // + // now insert the alternative: + // + re_alt* palt = static_cast(this->insert_state(this->m_alt_insert_point, syntax_element_alt, re_alt_size)); + jump_offset += re_alt_size; + this->m_pdata->m_data.align(); + palt->alt.i = this->m_pdata->m_data.size() - this->getoffset(palt); + // + // update m_alt_insert_point so that the next alternate gets + // inserted at the start of the second of the two we've just created: + // + this->m_alt_insert_point = this->m_pdata->m_data.size(); + // + // the start of this alternative must have a case changes state + // if the current block has messed around with case changes: + // + if(m_has_case_change) + { + static_cast( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = this->m_icase; + } + // + // push the alternative onto our stack, a recursive + // implementation here is easier to understand (and faster + // as it happens), but causes all kinds of stack overflow problems + // on programs with small stacks (COM+). + // + m_alt_jumps.push_back(jump_offset); + return true; +} + +template +bool basic_regex_parser::parse_set() +{ + static const char incomplete_message[] = "Character set declaration starting with [ terminated prematurely - either no ] was found or the set had no content."; + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + basic_char_set char_set; + + const charT* base = m_position; // where the '[' was + const charT* item_base = m_position; // where the '[' or '^' was + + while(m_position != m_end) + { + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_caret: + if(m_position == base) + { + char_set.negate(); + ++m_position; + item_base = m_position; + } + else + parse_set_literal(char_set); + break; + case regex_constants::syntax_close_set: + if(m_position == item_base) + { + parse_set_literal(char_set); + break; + } + else + { + ++m_position; + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + } + return true; + case regex_constants::syntax_open_set: + if(parse_inner_set(char_set)) + break; + return true; + case regex_constants::syntax_escape: + { + // + // look ahead and see if this is a character class shortcut + // \d \w \s etc... + // + ++m_position; + if(this->m_traits.escape_syntax_type(*m_position) + == regex_constants::escape_type_class) + { + char_class_type m = this->m_traits.lookup_classname(m_position, m_position+1); + if(m != 0) + { + char_set.add_class(m); + ++m_position; + break; + } + } + else if(this->m_traits.escape_syntax_type(*m_position) + == regex_constants::escape_type_not_class) + { + // negated character class: + char_class_type m = this->m_traits.lookup_classname(m_position, m_position+1); + if(m != 0) + { + char_set.add_negated_class(m); + ++m_position; + break; + } + } + // not a character class, just a regular escape: + --m_position; + parse_set_literal(char_set); + break; + } + default: + parse_set_literal(char_set); + break; + } + } + return m_position != m_end; +} + +template +bool basic_regex_parser::parse_inner_set(basic_char_set& char_set) +{ + static const char incomplete_message[] = "Character class declaration starting with [ terminated prematurely - either no ] was found or the set had no content."; + // + // we have either a character class [:name:] + // a collating element [.name.] + // or an equivalence class [=name=] + // + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_dot: + // + // a collating element is treated as a literal: + // + --m_position; + parse_set_literal(char_set); + return true; + case regex_constants::syntax_colon: + { + // check that character classes are actually enabled: + if((this->flags() & (regbase::main_option_type | regbase::no_char_classes)) + == (regbase::basic_syntax_group | regbase::no_char_classes)) + { + --m_position; + parse_set_literal(char_set); + return true; + } + // skip the ':' + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + const charT* name_first = m_position; + // skip at least one character, then find the matching ':]' + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_colon)) + ++m_position; + const charT* name_last = m_position; + if(m_end == m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + if((m_end == ++m_position) + || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + // + // check for negated class: + // + bool negated = false; + if(this->m_traits.syntax_type(*name_first) == regex_constants::syntax_caret) + { + ++name_first; + negated = true; + } + typedef typename traits::char_class_type m_type; + m_type m = this->m_traits.lookup_classname(name_first, name_last); + if(m == 0) + { + if(char_set.empty() && (name_last - name_first == 1)) + { + // maybe a special case: + ++m_position; + if( (m_position != m_end) + && (this->m_traits.syntax_type(*m_position) + == regex_constants::syntax_close_set)) + { + if(this->m_traits.escape_syntax_type(*name_first) + == regex_constants::escape_type_left_word) + { + ++m_position; + this->append_state(syntax_element_word_start); + return false; + } + if(this->m_traits.escape_syntax_type(*name_first) + == regex_constants::escape_type_right_word) + { + ++m_position; + this->append_state(syntax_element_word_end); + return false; + } + } + } + fail(regex_constants::error_ctype, name_first - m_base); + return false; + } + if(!negated) + char_set.add_class(m); + else + char_set.add_negated_class(m); + ++m_position; + break; + } + case regex_constants::syntax_equal: + { + // skip the '=' + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + const charT* name_first = m_position; + // skip at least one character, then find the matching '=]' + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal)) + ++m_position; + const charT* name_last = m_position; + if(m_end == m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + if((m_end == ++m_position) + || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + string_type m = this->m_traits.lookup_collatename(name_first, name_last); + if(m.empty() || (m.size() > 2)) + { + fail(regex_constants::error_collate, name_first - m_base); + return false; + } + digraph d; + d.first = m[0]; + if(m.size() > 1) + d.second = m[1]; + else + d.second = 0; + char_set.add_equivalent(d); + ++m_position; + break; + } + default: + --m_position; + parse_set_literal(char_set); + break; + } + return true; +} + +template +void basic_regex_parser::parse_set_literal(basic_char_set& char_set) +{ + digraph start_range(get_next_set_literal(char_set)); + if(m_end == m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return; + } + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_dash) + { + // we have a range: + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return; + } + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set) + { + digraph end_range = get_next_set_literal(char_set); + char_set.add_range(start_range, end_range); + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_dash) + { + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return; + } + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_set) + { + // trailing - : + --m_position; + return; + } + fail(regex_constants::error_range, m_position - m_base); + return; + } + return; + } + --m_position; + } + char_set.add_single(start_range); +} + +template +digraph basic_regex_parser::get_next_set_literal(basic_char_set& char_set) +{ + digraph result; + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_dash: + if(!char_set.empty()) + { + // see if we are at the end of the set: + if((++m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)) + { + fail(regex_constants::error_range, m_position - m_base); + return result; + } + --m_position; + } + result.first = *m_position++; + return result; + case regex_constants::syntax_escape: + // check to see if escapes are supported first: + if(this->flags() & regex_constants::no_escape_in_lists) + { + result = *m_position++; + break; + } + ++m_position; + result = unescape_character(); + break; + case regex_constants::syntax_open_set: + { + if(m_end == ++m_position) + { + fail(regex_constants::error_collate, m_position - m_base); + return result; + } + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_dot) + { + --m_position; + result.first = *m_position; + ++m_position; + return result; + } + if(m_end == ++m_position) + { + fail(regex_constants::error_collate, m_position - m_base); + return result; + } + const charT* name_first = m_position; + // skip at least one character, then find the matching ':]' + if(m_end == ++m_position) + { + fail(regex_constants::error_collate, name_first - m_base); + return result; + } + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_dot)) + ++m_position; + const charT* name_last = m_position; + if(m_end == m_position) + { + fail(regex_constants::error_collate, name_first - m_base); + return result; + } + if((m_end == ++m_position) + || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)) + { + fail(regex_constants::error_collate, name_first - m_base); + return result; + } + ++m_position; + string_type s = this->m_traits.lookup_collatename(name_first, name_last); + if(s.empty() || (s.size() > 2)) + { + fail(regex_constants::error_collate, name_first - m_base); + return result; + } + result.first = s[0]; + if(s.size() > 1) + result.second = s[1]; + else + result.second = 0; + return result; + } + default: + result = *m_position++; + } + return result; +} + +// +// does a value fit in the specified charT type? +// +template +bool valid_value(charT, boost::intmax_t v, const mpl::true_&) +{ + return (v >> (sizeof(charT) * CHAR_BIT)) == 0; +} +template +bool valid_value(charT, boost::intmax_t, const mpl::false_&) +{ + return true; // v will alsways fit in a charT +} +template +bool valid_value(charT c, boost::intmax_t v) +{ + return valid_value(c, v, mpl::bool_<(sizeof(charT) < sizeof(boost::intmax_t))>()); +} + +template +charT basic_regex_parser::unescape_character() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + charT result(0); + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base, "Escape sequence terminated prematurely."); + return false; + } + switch(this->m_traits.escape_syntax_type(*m_position)) + { + case regex_constants::escape_type_control_a: + result = charT('\a'); + break; + case regex_constants::escape_type_e: + result = charT(27); + break; + case regex_constants::escape_type_control_f: + result = charT('\f'); + break; + case regex_constants::escape_type_control_n: + result = charT('\n'); + break; + case regex_constants::escape_type_control_r: + result = charT('\r'); + break; + case regex_constants::escape_type_control_t: + result = charT('\t'); + break; + case regex_constants::escape_type_control_v: + result = charT('\v'); + break; + case regex_constants::escape_type_word_assert: + result = charT('\b'); + break; + case regex_constants::escape_type_ascii_control: + ++m_position; + if(m_position == m_end) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base, "ASCII escape sequence terminated prematurely."); + return result; + } + result = static_cast(*m_position % 32); + break; + case regex_constants::escape_type_hex: + ++m_position; + if(m_position == m_end) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base, "Hexadecimal escape sequence terminated prematurely."); + return result; + } + // maybe have \x{ddd} + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace) + { + ++m_position; + if(m_position == m_end) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base, "Missing } in hexadecimal escape sequence."); + return result; + } + boost::intmax_t i = this->m_traits.toi(m_position, m_end, 16); + if((m_position == m_end) + || (i < 0) + || ((std::numeric_limits::is_specialized) && (i > (boost::intmax_t)(std::numeric_limits::max)())) + || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace)) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_badbrace, m_position - m_base, "Hexadecimal escape sequence was invalid."); + return result; + } + ++m_position; + result = charT(i); + } + else + { + std::ptrdiff_t len = (std::min)(static_cast(2), static_cast(m_end - m_position)); + boost::intmax_t i = this->m_traits.toi(m_position, m_position + len, 16); + if((i < 0) + || !valid_value(charT(0), i)) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base, "Escape sequence did not encode a valid character."); + return result; + } + result = charT(i); + } + return result; + case regex_constants::syntax_digit: + { + // an octal escape sequence, the first character must be a zero + // followed by up to 3 octal digits: + std::ptrdiff_t len = (std::min)(::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end), static_cast(4)); + const charT* bp = m_position; + boost::intmax_t val = this->m_traits.toi(bp, bp + 1, 8); + if(val != 0) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + // Oops not an octal escape after all: + fail(regex_constants::error_escape, m_position - m_base, "Invalid octal escape sequence."); + return result; + } + val = this->m_traits.toi(m_position, m_position + len, 8); + if((val < 0) || (val > (boost::intmax_t)(std::numeric_limits::max)())) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base, "Octal escape sequence is invalid."); + return result; + } + return static_cast(val); + } + case regex_constants::escape_type_named_char: + { + ++m_position; + if(m_position == m_end) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + // maybe have \N{name} + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace) + { + const charT* base = m_position; + // skip forward until we find enclosing brace: + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace)) + ++m_position; + if(m_position == m_end) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + string_type s = this->m_traits.lookup_collatename(++base, m_position++); + if(s.empty()) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_collate, m_position - m_base); + return false; + } + if(s.size() == 1) + { + return s[0]; + } + } + // fall through is a failure: + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + default: + result = *m_position; + break; + } + ++m_position; + return result; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool basic_regex_parser::parse_backref() +{ + BOOST_REGEX_ASSERT(m_position != m_end); + const charT* pc = m_position; + boost::intmax_t i = this->m_traits.toi(pc, pc + 1, 10); + if((i == 0) || (((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) && (this->flags() & regbase::no_bk_refs))) + { + // not a backref at all but an octal escape sequence: + charT c = unescape_character(); + this->append_literal(c); + } + else if((i > 0) && (this->m_backrefs.test(i))) + { + m_position = pc; + re_brace* pb = static_cast(this->append_state(syntax_element_backref, sizeof(re_brace))); + pb->index = i; + pb->icase = this->flags() & regbase::icase; + } + else + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_backref, m_position - m_base); + return false; + } + return true; +} + +template +bool basic_regex_parser::parse_QE() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + // + // parse a \Q...\E sequence: + // + ++m_position; // skip the Q + const charT* start = m_position; + const charT* end; + do + { + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape)) + ++m_position; + if(m_position == m_end) + { + // a \Q...\E sequence may terminate with the end of the expression: + end = m_position; + break; + } + if(++m_position == m_end) // skip the escape + { + fail(regex_constants::error_escape, m_position - m_base, "Unterminated \\Q...\\E sequence."); + return false; + } + // check to see if it's a \E: + if(this->m_traits.escape_syntax_type(*m_position) == regex_constants::escape_type_E) + { + ++m_position; + end = m_position - 2; + break; + } + // otherwise go round again: + }while(true); + // + // now add all the character between the two escapes as literals: + // + while(start != end) + { + this->append_literal(*start); + ++start; + } + return true; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool basic_regex_parser::parse_perl_extension() +{ + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + // + // treat comments as a special case, as these + // are the only ones that don't start with a leading + // startmark state: + // + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_hash) + { + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position++) != regex_constants::syntax_close_mark)) + {} + return true; + } + // + // backup some state, and prepare the way: + // + int markid = 0; + std::ptrdiff_t jump_offset = 0; + re_brace* pb = static_cast(this->append_state(syntax_element_startmark, sizeof(re_brace))); + pb->icase = this->flags() & regbase::icase; + std::ptrdiff_t last_paren_start = this->getoffset(pb); + // back up insertion point for alternations, and set new point: + std::ptrdiff_t last_alt_point = m_alt_insert_point; + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + std::ptrdiff_t expected_alt_point = m_alt_insert_point; + bool restore_flags = true; + regex_constants::syntax_option_type old_flags = this->flags(); + bool old_case_change = m_has_case_change; + m_has_case_change = false; + charT name_delim; + int mark_reset = m_mark_reset; + int max_mark = m_max_mark; + m_mark_reset = -1; + m_max_mark = m_mark_count; + boost::intmax_t v; + // + // select the actual extension used: + // + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_or: + m_mark_reset = m_mark_count; + BOOST_FALLTHROUGH; + case regex_constants::syntax_colon: + // + // a non-capturing mark: + // + pb->index = markid = 0; + ++m_position; + break; + case regex_constants::syntax_digit: + { + // + // a recursive subexpression: + // + v = this->m_traits.toi(m_position, m_end, 10); + if((v < 0) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base, "The recursive sub-expression refers to an invalid marking group, or is unterminated."); + return false; + } +insert_recursion: + pb->index = markid = 0; + re_recurse* pr = static_cast(this->append_state(syntax_element_recurse, sizeof(re_recurse))); + pr->alt.i = v; + pr->state_id = 0; + static_cast( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = this->flags() & regbase::icase; + break; + } + case regex_constants::syntax_plus: + // + // A forward-relative recursive subexpression: + // + ++m_position; + v = this->m_traits.toi(m_position, m_end, 10); + if((v <= 0) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base, "An invalid or unterminated recursive sub-expression."); + return false; + } + if ((std::numeric_limits::max)() - m_mark_count < v) + { + fail(regex_constants::error_perl_extension, m_position - m_base, "An invalid or unterminated recursive sub-expression."); + return false; + } + v += m_mark_count; + goto insert_recursion; + case regex_constants::syntax_dash: + // + // Possibly a backward-relative recursive subexpression: + // + ++m_position; + v = this->m_traits.toi(m_position, m_end, 10); + if(v <= 0) + { + --m_position; + // Oops not a relative recursion at all, but a (?-imsx) group: + goto option_group_jump; + } + v = static_cast(m_mark_count) + 1 - v; + if(v <= 0) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base, "An invalid or unterminated recursive sub-expression."); + return false; + } + goto insert_recursion; + case regex_constants::syntax_equal: + pb->index = markid = -1; + ++m_position; + jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump))); + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + break; + case regex_constants::syntax_not: + pb->index = markid = -2; + ++m_position; + jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump))); + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + break; + case regex_constants::escape_type_left_word: + { + // a lookbehind assertion: + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + regex_constants::syntax_type t = this->m_traits.syntax_type(*m_position); + if(t == regex_constants::syntax_not) + pb->index = markid = -2; + else if(t == regex_constants::syntax_equal) + pb->index = markid = -1; + else + { + // Probably a named capture which also starts (?< : + name_delim = '>'; + --m_position; + goto named_capture_jump; + } + ++m_position; + jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump))); + this->append_state(syntax_element_backstep, sizeof(re_brace)); + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + break; + } + case regex_constants::escape_type_right_word: + // + // an independent sub-expression: + // + pb->index = markid = -3; + ++m_position; + jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump))); + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + break; + case regex_constants::syntax_open_mark: + { + // a conditional expression: + pb->index = markid = -4; + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + v = this->m_traits.toi(m_position, m_end, 10); + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(*m_position == charT('R')) + { + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(*m_position == charT('&')) + { + const charT* base = ++m_position; + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + v = -static_cast(hash_value_from_capture_name(base, m_position)); + } + else + { + v = -this->m_traits.toi(m_position, m_end, 10); + } + re_brace* br = static_cast(this->append_state(syntax_element_assert_backref, sizeof(re_brace))); + br->index = v < 0 ? (v - 1) : 0; + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + } + else if((*m_position == charT('\'')) || (*m_position == charT('<'))) + { + const charT* base = ++m_position; + while((m_position != m_end) && (*m_position != charT('>')) && (*m_position != charT('\''))) + ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + v = static_cast(hash_value_from_capture_name(base, m_position)); + re_brace* br = static_cast(this->append_state(syntax_element_assert_backref, sizeof(re_brace))); + br->index = v; + if(((*m_position != charT('>')) && (*m_position != charT('\''))) || (++m_position == m_end)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base, "Unterminated named capture."); + return false; + } + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + } + else if(*m_position == charT('D')) + { + const char* def = "DEFINE"; + while(*def && (m_position != m_end) && (*m_position == charT(*def))) + ++m_position, ++def; + if((m_position == m_end) || *def) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + re_brace* br = static_cast(this->append_state(syntax_element_assert_backref, sizeof(re_brace))); + br->index = 9999; // special magic value! + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + } + else if(v > 0) + { + re_brace* br = static_cast(this->append_state(syntax_element_assert_backref, sizeof(re_brace))); + br->index = v; + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + } + else + { + // verify that we have a lookahead or lookbehind assert: + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_question) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(this->m_traits.syntax_type(*m_position) == regex_constants::escape_type_left_word) + { + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + m_position -= 3; + } + else + { + if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + m_position -= 2; + } + } + break; + } + case regex_constants::syntax_close_mark: + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + case regex_constants::escape_type_end_buffer: + { + name_delim = *m_position; +named_capture_jump: + markid = 0; + if(0 == (this->flags() & regbase::nosubs)) + { + markid = ++m_mark_count; + #ifndef BOOST_NO_STD_DISTANCE + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.push_back(std::pair(std::distance(m_base, m_position) - 2, 0)); + #else + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.push_back(std::pair((m_position - m_base) - 2, 0)); + #endif + } + pb->index = markid; + const charT* base = ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + while((m_position != m_end) && (*m_position != name_delim)) + ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + this->m_pdata->set_name(base, m_position, markid); + ++m_position; + break; + } + default: + if(*m_position == charT('R')) + { + ++m_position; + v = 0; + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + goto insert_recursion; + } + if(*m_position == charT('&')) + { + ++m_position; + const charT* base = m_position; + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + v = static_cast(hash_value_from_capture_name(base, m_position)); + goto insert_recursion; + } + if(*m_position == charT('P')) + { + ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(*m_position == charT('>')) + { + ++m_position; + const charT* base = m_position; + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + v = static_cast(hash_value_from_capture_name(base, m_position)); + goto insert_recursion; + } + } + // + // lets assume that we have a (?imsx) group and try and parse it: + // +option_group_jump: + regex_constants::syntax_option_type opts = parse_options(); + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + // make a note of whether we have a case change: + m_has_case_change = ((opts & regbase::icase) != (this->flags() & regbase::icase)); + pb->index = markid = 0; + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark) + { + // update flags and carry on as normal: + this->flags(opts); + restore_flags = false; + old_case_change |= m_has_case_change; // defer end of scope by one ')' + } + else if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_colon) + { + // update flags and carry on until the matching ')' is found: + this->flags(opts); + ++m_position; + } + else + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + + // finally append a case change state if we need it: + if(m_has_case_change) + { + static_cast( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = opts & regbase::icase; + } + + } + // + // now recursively add more states, this will terminate when we get to a + // matching ')' : + // + parse_all(); + // + // Unwind alternatives: + // + if(0 == unwind_alts(last_paren_start)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base, "Invalid alternation operators within (?...) block."); + return false; + } + // + // we either have a ')' or we have run out of characters prematurely: + // + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + this->fail(regex_constants::error_paren, ::boost::BOOST_REGEX_DETAIL_NS::distance(m_base, m_end)); + return false; + } + BOOST_REGEX_ASSERT(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark); + ++m_position; + // + // restore the flags: + // + if(restore_flags) + { + // append a case change state if we need it: + if(m_has_case_change) + { + static_cast( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = old_flags & regbase::icase; + } + this->flags(old_flags); + } + // + // set up the jump pointer if we have one: + // + if(jump_offset) + { + this->m_pdata->m_data.align(); + re_jump* jmp = static_cast(this->getaddress(jump_offset)); + jmp->alt.i = this->m_pdata->m_data.size() - this->getoffset(jmp); + if((this->m_last_state == jmp) && (markid != -2)) + { + // Oops... we didn't have anything inside the assertion. + // Note we don't get here for negated forward lookahead as (?!) + // does have some uses. + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base, "Invalid or empty zero width assertion."); + return false; + } + } + // + // verify that if this is conditional expression, that we do have + // an alternative, if not add one: + // + if(markid == -4) + { + re_syntax_base* b = this->getaddress(expected_alt_point); + // Make sure we have exactly one alternative following this state: + if(b->type != syntax_element_alt) + { + re_alt* alt = static_cast(this->insert_state(expected_alt_point, syntax_element_alt, sizeof(re_alt))); + alt->alt.i = this->m_pdata->m_data.size() - this->getoffset(alt); + } + else if(((std::ptrdiff_t)this->m_pdata->m_data.size() > (static_cast(b)->alt.i + this->getoffset(b))) && (static_cast(b)->alt.i > 0) && this->getaddress(static_cast(b)->alt.i, b)->type == syntax_element_alt) + { + // Can't have seen more than one alternative: + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_bad_pattern, m_position - m_base, "More than one alternation operator | was encountered inside a conditional expression."); + return false; + } + else + { + // We must *not* have seen an alternative inside a (DEFINE) block: + b = this->getaddress(b->next.i, b); + if((b->type == syntax_element_assert_backref) && (static_cast(b)->index == 9999)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_bad_pattern, m_position - m_base, "Alternation operators are not allowed inside a DEFINE block."); + return false; + } + } + // check for invalid repetition of next state: + b = this->getaddress(expected_alt_point); + b = this->getaddress(static_cast(b)->next.i, b); + if((b->type != syntax_element_assert_backref) + && (b->type != syntax_element_startmark)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_badrepeat, m_position - m_base, "A repetition operator cannot be applied to a zero-width assertion."); + return false; + } + } + // + // append closing parenthesis state: + // + pb = static_cast(this->append_state(syntax_element_endmark, sizeof(re_brace))); + pb->index = markid; + pb->icase = this->flags() & regbase::icase; + this->m_paren_start = last_paren_start; + // + // restore the alternate insertion point: + // + this->m_alt_insert_point = last_alt_point; + // + // and the case change data: + // + m_has_case_change = old_case_change; + // + // And the mark_reset data: + // + if(m_max_mark > m_mark_count) + { + m_mark_count = m_max_mark; + } + m_mark_reset = mark_reset; + m_max_mark = max_mark; + + + if(markid > 0) + { +#ifndef BOOST_NO_STD_DISTANCE + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.at((std::size_t)markid - 1).second = std::distance(m_base, m_position) - 1; +#else + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.at(markid - 1).second = (m_position - m_base) - 1; +#endif + // + // allow backrefs to this mark: + // + this->m_backrefs.set(markid); + } + return true; +} + +template +bool basic_regex_parser::match_verb(const char* verb) +{ + while(*verb) + { + if(static_cast(*verb) != *m_position) + { + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++verb; + } + return true; +} + +#ifdef BOOST_MSVC +# pragma warning(push) +#if BOOST_MSVC >= 1800 +#pragma warning(disable:26812) +#endif +#endif +template +bool basic_regex_parser::parse_perl_verb() +{ + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + switch(*m_position) + { + case 'F': + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if((this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark) || match_verb("AIL")) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++m_position; + this->append_state(syntax_element_fail); + return true; + } + break; + case 'A': + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(match_verb("CCEPT")) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++m_position; + this->append_state(syntax_element_accept); + return true; + } + break; + case 'C': + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(match_verb("OMMIT")) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++m_position; + static_cast(this->append_state(syntax_element_commit, sizeof(re_commit)))->action = commit_commit; + this->m_pdata->m_disable_match_any = true; + return true; + } + break; + case 'P': + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(match_verb("RUNE")) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++m_position; + static_cast(this->append_state(syntax_element_commit, sizeof(re_commit)))->action = commit_prune; + this->m_pdata->m_disable_match_any = true; + return true; + } + break; + case 'S': + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(match_verb("KIP")) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++m_position; + static_cast(this->append_state(syntax_element_commit, sizeof(re_commit)))->action = commit_skip; + this->m_pdata->m_disable_match_any = true; + return true; + } + break; + case 'T': + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(match_verb("HEN")) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++m_position; + this->append_state(syntax_element_then); + this->m_pdata->m_disable_match_any = true; + return true; + } + break; + } + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; +} +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +template +bool basic_regex_parser::add_emacs_code(bool negate) +{ + // + // parses an emacs style \sx or \Sx construct. + // + if(++m_position == m_end) + { + // Rewind to start of sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + basic_char_set char_set; + if(negate) + char_set.negate(); + + static const charT s_punct[5] = { 'p', 'u', 'n', 'c', 't', }; + + switch(*m_position) + { + case 's': + case ' ': + char_set.add_class(this->m_mask_space); + break; + case 'w': + char_set.add_class(this->m_word_mask); + break; + case '_': + char_set.add_single(digraph(charT('$'))); + char_set.add_single(digraph(charT('&'))); + char_set.add_single(digraph(charT('*'))); + char_set.add_single(digraph(charT('+'))); + char_set.add_single(digraph(charT('-'))); + char_set.add_single(digraph(charT('_'))); + char_set.add_single(digraph(charT('<'))); + char_set.add_single(digraph(charT('>'))); + break; + case '.': + char_set.add_class(this->m_traits.lookup_classname(s_punct, s_punct+5)); + break; + case '(': + char_set.add_single(digraph(charT('('))); + char_set.add_single(digraph(charT('['))); + char_set.add_single(digraph(charT('{'))); + break; + case ')': + char_set.add_single(digraph(charT(')'))); + char_set.add_single(digraph(charT(']'))); + char_set.add_single(digraph(charT('}'))); + break; + case '"': + char_set.add_single(digraph(charT('"'))); + char_set.add_single(digraph(charT('\''))); + char_set.add_single(digraph(charT('`'))); + break; + case '\'': + char_set.add_single(digraph(charT('\''))); + char_set.add_single(digraph(charT(','))); + char_set.add_single(digraph(charT('#'))); + break; + case '<': + char_set.add_single(digraph(charT(';'))); + break; + case '>': + char_set.add_single(digraph(charT('\n'))); + char_set.add_single(digraph(charT('\f'))); + break; + default: + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + ++m_position; + return true; +} + +template +regex_constants::syntax_option_type basic_regex_parser::parse_options() +{ + // we have a (?imsx-imsx) group, convert it into a set of flags: + regex_constants::syntax_option_type f = this->flags(); + bool breakout = false; + do + { + switch(*m_position) + { + case 's': + f |= regex_constants::mod_s; + f &= ~regex_constants::no_mod_s; + break; + case 'm': + f &= ~regex_constants::no_mod_m; + break; + case 'i': + f |= regex_constants::icase; + break; + case 'x': + f |= regex_constants::mod_x; + break; + default: + breakout = true; + continue; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + } + while(!breakout); + + breakout = false; + + if(*m_position == static_cast('-')) + { + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + do + { + switch(*m_position) + { + case 's': + f &= ~regex_constants::mod_s; + f |= regex_constants::no_mod_s; + break; + case 'm': + f |= regex_constants::no_mod_m; + break; + case 'i': + f &= ~regex_constants::icase; + break; + case 'x': + f &= ~regex_constants::mod_x; + break; + default: + breakout = true; + continue; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + } + while(!breakout); + } + return f; +} + +template +bool basic_regex_parser::unwind_alts(std::ptrdiff_t last_paren_start) +{ + // + // If we didn't actually add any states after the last + // alternative then that's an error: + // + if((this->m_alt_insert_point == static_cast(this->m_pdata->m_data.size())) + && (!m_alt_jumps.empty()) && (m_alt_jumps.back() > last_paren_start) + && + !( + ((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) + && + ((this->flags() & regbase::no_empty_expressions) == 0) + ) + ) + { + fail(regex_constants::error_empty, this->m_position - this->m_base, "Can't terminate a sub-expression with an alternation operator |."); + return false; + } + // + // Fix up our alternatives: + // + while((!m_alt_jumps.empty()) && (m_alt_jumps.back() > last_paren_start)) + { + // + // fix up the jump to point to the end of the states + // that we've just added: + // + std::ptrdiff_t jump_offset = m_alt_jumps.back(); + m_alt_jumps.pop_back(); + this->m_pdata->m_data.align(); + re_jump* jmp = static_cast(this->getaddress(jump_offset)); + if (jmp->type != syntax_element_jump) + { + // Something really bad happened, this used to be an assert, + // but we'll make it an error just in case we should ever get here. + fail(regex_constants::error_unknown, this->m_position - this->m_base, "Internal logic failed while compiling the expression, probably you added a repeat to something non-repeatable!"); + return false; + } + jmp->alt.i = this->m_pdata->m_data.size() - jump_offset; + } + return true; +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace BOOST_REGEX_DETAIL_NS +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif diff --git a/boost/regex/v4/c_regex_traits.hpp b/boost/regex/v4/c_regex_traits.hpp new file mode 100644 index 00000000..f966c4d4 --- /dev/null +++ b/boost/regex/v4/c_regex_traits.hpp @@ -0,0 +1,511 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE c_regex_traits.hpp + * VERSION see + * DESCRIPTION: Declares regular expression traits class that wraps the global C locale. + */ + +#ifndef BOOST_C_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_C_REGEX_TRAITS_HPP_INCLUDED + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif +#ifndef BOOST_REGEX_WORKAROUND_HPP +#include +#endif + +#include + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ + using ::strlen; using ::tolower; +} +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103 4244) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +namespace boost{ + + namespace BOOST_REGEX_DETAIL_NS { + + enum + { + char_class_space = 1 << 0, + char_class_print = 1 << 1, + char_class_cntrl = 1 << 2, + char_class_upper = 1 << 3, + char_class_lower = 1 << 4, + char_class_alpha = 1 << 5, + char_class_digit = 1 << 6, + char_class_punct = 1 << 7, + char_class_xdigit = 1 << 8, + char_class_alnum = char_class_alpha | char_class_digit, + char_class_graph = char_class_alnum | char_class_punct, + char_class_blank = 1 << 9, + char_class_word = 1 << 10, + char_class_unicode = 1 << 11, + char_class_horizontal = 1 << 12, + char_class_vertical = 1 << 13 + }; + + } + +template +struct c_regex_traits; + +template<> +struct c_regex_traits +{ + c_regex_traits(){} + typedef char char_type; + typedef std::size_t size_type; + typedef std::string string_type; + struct locale_type{}; + typedef boost::uint32_t char_class_type; + + static size_type length(const char_type* p) + { + return (std::strlen)(p); + } + + char translate(char c) const + { + return c; + } + char translate_nocase(char c) const + { + return static_cast((std::tolower)(static_cast(c))); + } + + static string_type BOOST_REGEX_CALL transform(const char* p1, const char* p2); + static string_type BOOST_REGEX_CALL transform_primary(const char* p1, const char* p2); + + static char_class_type BOOST_REGEX_CALL lookup_classname(const char* p1, const char* p2); + static string_type BOOST_REGEX_CALL lookup_collatename(const char* p1, const char* p2); + + static bool BOOST_REGEX_CALL isctype(char, char_class_type); + static int BOOST_REGEX_CALL value(char, int); + + locale_type imbue(locale_type l) + { return l; } + locale_type getloc()const + { return locale_type(); } + +private: + // this type is not copyable: + c_regex_traits(const c_regex_traits&); + c_regex_traits& operator=(const c_regex_traits&); +}; + +#ifndef BOOST_NO_WREGEX +template<> +struct c_regex_traits +{ + c_regex_traits(){} + typedef wchar_t char_type; + typedef std::size_t size_type; + typedef std::wstring string_type; + struct locale_type{}; + typedef boost::uint32_t char_class_type; + + static size_type length(const char_type* p) + { + return (std::wcslen)(p); + } + + wchar_t translate(wchar_t c) const + { + return c; + } + wchar_t translate_nocase(wchar_t c) const + { + return (std::towlower)(c); + } + + static string_type BOOST_REGEX_CALL transform(const wchar_t* p1, const wchar_t* p2); + static string_type BOOST_REGEX_CALL transform_primary(const wchar_t* p1, const wchar_t* p2); + + static char_class_type BOOST_REGEX_CALL lookup_classname(const wchar_t* p1, const wchar_t* p2); + static string_type BOOST_REGEX_CALL lookup_collatename(const wchar_t* p1, const wchar_t* p2); + + static bool BOOST_REGEX_CALL isctype(wchar_t, char_class_type); + static int BOOST_REGEX_CALL value(wchar_t, int); + + locale_type imbue(locale_type l) + { return l; } + locale_type getloc()const + { return locale_type(); } + +private: + // this type is not copyable: + c_regex_traits(const c_regex_traits&); + c_regex_traits& operator=(const c_regex_traits&); +}; + +#endif // BOOST_NO_WREGEX + +inline c_regex_traits::string_type BOOST_REGEX_CALL c_regex_traits::transform(const char* p1, const char* p2) +{ + std::string result(10, ' '); + std::size_t s = result.size(); + std::size_t r; + std::string src(p1, p2); + while (s < (r = std::strxfrm(&*result.begin(), src.c_str(), s))) + { +#if defined(_CPPLIB_VER) + // + // A bug in VC11 and 12 causes the program to hang if we pass a null-string + // to std::strxfrm, but only for certain locales :-( + // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware). + // + if (r == INT_MAX) + { + result.erase(); + result.insert(result.begin(), static_cast(0)); + return result; + } +#endif + result.append(r - s + 3, ' '); + s = result.size(); + } + result.erase(r); + return result; +} + +inline c_regex_traits::string_type BOOST_REGEX_CALL c_regex_traits::transform_primary(const char* p1, const char* p2) +{ + static char s_delim; + static const int s_collate_type = ::boost::BOOST_REGEX_DETAIL_NS::find_sort_syntax(static_cast*>(0), &s_delim); + std::string result; + // + // What we do here depends upon the format of the sort key returned by + // sort key returned by this->transform: + // + switch (s_collate_type) + { + case ::boost::BOOST_REGEX_DETAIL_NS::sort_C: + case ::boost::BOOST_REGEX_DETAIL_NS::sort_unknown: + // the best we can do is translate to lower case, then get a regular sort key: + { + result.assign(p1, p2); + for (std::string::size_type i = 0; i < result.size(); ++i) + result[i] = static_cast((std::tolower)(static_cast(result[i]))); + result = transform(&*result.begin(), &*result.begin() + result.size()); + break; + } + case ::boost::BOOST_REGEX_DETAIL_NS::sort_fixed: + { + // get a regular sort key, and then truncate it: + result = transform(p1, p2); + result.erase(s_delim); + break; + } + case ::boost::BOOST_REGEX_DETAIL_NS::sort_delim: + // get a regular sort key, and then truncate everything after the delim: + result = transform(p1, p2); + if ((!result.empty()) && (result[0] == s_delim)) + break; + std::size_t i; + for (i = 0; i < result.size(); ++i) + { + if (result[i] == s_delim) + break; + } + result.erase(i); + break; + } + if (result.empty()) + result = std::string(1, char(0)); + return result; +} + +inline c_regex_traits::char_class_type BOOST_REGEX_CALL c_regex_traits::lookup_classname(const char* p1, const char* p2) +{ + using namespace BOOST_REGEX_DETAIL_NS; + static const char_class_type masks[] = + { + 0, + char_class_alnum, + char_class_alpha, + char_class_blank, + char_class_cntrl, + char_class_digit, + char_class_digit, + char_class_graph, + char_class_horizontal, + char_class_lower, + char_class_lower, + char_class_print, + char_class_punct, + char_class_space, + char_class_space, + char_class_upper, + char_class_unicode, + char_class_upper, + char_class_vertical, + char_class_alnum | char_class_word, + char_class_alnum | char_class_word, + char_class_xdigit, + }; + + int idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2); + if (idx < 0) + { + std::string s(p1, p2); + for (std::string::size_type i = 0; i < s.size(); ++i) + s[i] = static_cast((std::tolower)(static_cast(s[i]))); + idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(&*s.begin(), &*s.begin() + s.size()); + } + BOOST_REGEX_ASSERT(std::size_t(idx) + 1u < sizeof(masks) / sizeof(masks[0])); + return masks[idx + 1]; +} + +inline bool BOOST_REGEX_CALL c_regex_traits::isctype(char c, char_class_type mask) +{ + using namespace BOOST_REGEX_DETAIL_NS; + return + ((mask & char_class_space) && (std::isspace)(static_cast(c))) + || ((mask & char_class_print) && (std::isprint)(static_cast(c))) + || ((mask & char_class_cntrl) && (std::iscntrl)(static_cast(c))) + || ((mask & char_class_upper) && (std::isupper)(static_cast(c))) + || ((mask & char_class_lower) && (std::islower)(static_cast(c))) + || ((mask & char_class_alpha) && (std::isalpha)(static_cast(c))) + || ((mask & char_class_digit) && (std::isdigit)(static_cast(c))) + || ((mask & char_class_punct) && (std::ispunct)(static_cast(c))) + || ((mask & char_class_xdigit) && (std::isxdigit)(static_cast(c))) + || ((mask & char_class_blank) && (std::isspace)(static_cast(c)) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c)) + || ((mask & char_class_word) && (c == '_')) + || ((mask & char_class_vertical) && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v'))) + || ((mask & char_class_horizontal) && (std::isspace)(static_cast(c)) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) && (c != '\v')); +} + +inline c_regex_traits::string_type BOOST_REGEX_CALL c_regex_traits::lookup_collatename(const char* p1, const char* p2) +{ + std::string s(p1, p2); + s = ::boost::BOOST_REGEX_DETAIL_NS::lookup_default_collate_name(s); + if (s.empty() && (p2 - p1 == 1)) + s.append(1, *p1); + return s; +} + +inline int BOOST_REGEX_CALL c_regex_traits::value(char c, int radix) +{ + char b[2] = { c, '\0', }; + char* ep; + int result = std::strtol(b, &ep, radix); + if (ep == b) + return -1; + return result; +} + +#ifndef BOOST_NO_WREGEX + +inline c_regex_traits::string_type BOOST_REGEX_CALL c_regex_traits::transform(const wchar_t* p1, const wchar_t* p2) +{ + std::size_t r; + std::size_t s = 10; + std::wstring src(p1, p2); + std::wstring result(s, L' '); + while (s < (r = std::wcsxfrm(&*result.begin(), src.c_str(), s))) + { +#if defined(_CPPLIB_VER) + // + // A bug in VC11 and 12 causes the program to hang if we pass a null-string + // to std::strxfrm, but only for certain locales :-( + // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware). + // + if (r == INT_MAX) + { + result.erase(); + result.insert(result.begin(), static_cast(0)); + return result; + } +#endif + result.append(r - s + 3, L' '); + s = result.size(); + } + result.erase(r); + return result; +} + +inline c_regex_traits::string_type BOOST_REGEX_CALL c_regex_traits::transform_primary(const wchar_t* p1, const wchar_t* p2) +{ + static wchar_t s_delim; + static const int s_collate_type = ::boost::BOOST_REGEX_DETAIL_NS::find_sort_syntax(static_cast*>(0), &s_delim); + std::wstring result; + // + // What we do here depends upon the format of the sort key returned by + // sort key returned by this->transform: + // + switch (s_collate_type) + { + case ::boost::BOOST_REGEX_DETAIL_NS::sort_C: + case ::boost::BOOST_REGEX_DETAIL_NS::sort_unknown: + // the best we can do is translate to lower case, then get a regular sort key: + { + result.assign(p1, p2); + for (std::wstring::size_type i = 0; i < result.size(); ++i) + result[i] = (std::towlower)(result[i]); + result = c_regex_traits::transform(&*result.begin(), &*result.begin() + result.size()); + break; + } + case ::boost::BOOST_REGEX_DETAIL_NS::sort_fixed: + { + // get a regular sort key, and then truncate it: + result = c_regex_traits::transform(&*result.begin(), &*result.begin() + result.size()); + result.erase(s_delim); + break; + } + case ::boost::BOOST_REGEX_DETAIL_NS::sort_delim: + // get a regular sort key, and then truncate everything after the delim: + result = c_regex_traits::transform(&*result.begin(), &*result.begin() + result.size()); + if ((!result.empty()) && (result[0] == s_delim)) + break; + std::size_t i; + for (i = 0; i < result.size(); ++i) + { + if (result[i] == s_delim) + break; + } + result.erase(i); + break; + } + if (result.empty()) + result = std::wstring(1, char(0)); + return result; +} + +inline c_regex_traits::char_class_type BOOST_REGEX_CALL c_regex_traits::lookup_classname(const wchar_t* p1, const wchar_t* p2) +{ + using namespace BOOST_REGEX_DETAIL_NS; + static const char_class_type masks[] = + { + 0, + char_class_alnum, + char_class_alpha, + char_class_blank, + char_class_cntrl, + char_class_digit, + char_class_digit, + char_class_graph, + char_class_horizontal, + char_class_lower, + char_class_lower, + char_class_print, + char_class_punct, + char_class_space, + char_class_space, + char_class_upper, + char_class_unicode, + char_class_upper, + char_class_vertical, + char_class_alnum | char_class_word, + char_class_alnum | char_class_word, + char_class_xdigit, + }; + + int idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2); + if (idx < 0) + { + std::wstring s(p1, p2); + for (std::wstring::size_type i = 0; i < s.size(); ++i) + s[i] = (std::towlower)(s[i]); + idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(&*s.begin(), &*s.begin() + s.size()); + } + BOOST_REGEX_ASSERT(idx + 1 < static_cast(sizeof(masks) / sizeof(masks[0]))); + return masks[idx + 1]; +} + +inline bool BOOST_REGEX_CALL c_regex_traits::isctype(wchar_t c, char_class_type mask) +{ + using namespace BOOST_REGEX_DETAIL_NS; + return + ((mask & char_class_space) && (std::iswspace)(c)) + || ((mask & char_class_print) && (std::iswprint)(c)) + || ((mask & char_class_cntrl) && (std::iswcntrl)(c)) + || ((mask & char_class_upper) && (std::iswupper)(c)) + || ((mask & char_class_lower) && (std::iswlower)(c)) + || ((mask & char_class_alpha) && (std::iswalpha)(c)) + || ((mask & char_class_digit) && (std::iswdigit)(c)) + || ((mask & char_class_punct) && (std::iswpunct)(c)) + || ((mask & char_class_xdigit) && (std::iswxdigit)(c)) + || ((mask & char_class_blank) && (std::iswspace)(c) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c)) + || ((mask & char_class_word) && (c == '_')) + || ((mask & char_class_unicode) && (c & ~static_cast(0xff))) + || ((mask & char_class_vertical) && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == L'\v'))) + || ((mask & char_class_horizontal) && (std::iswspace)(c) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) && (c != L'\v')); +} + +inline c_regex_traits::string_type BOOST_REGEX_CALL c_regex_traits::lookup_collatename(const wchar_t* p1, const wchar_t* p2) +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4244) +#endif + std::string name(p1, p2); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + name = ::boost::BOOST_REGEX_DETAIL_NS::lookup_default_collate_name(name); + if (!name.empty()) + return string_type(name.begin(), name.end()); + if (p2 - p1 == 1) + return string_type(1, *p1); + return string_type(); +} + +inline int BOOST_REGEX_CALL c_regex_traits::value(wchar_t c, int radix) +{ +#ifdef BOOST_BORLANDC + // workaround for broken wcstol: + if ((std::iswxdigit)(c) == 0) + return -1; +#endif + wchar_t b[2] = { c, '\0', }; + wchar_t* ep; + int result = std::wcstol(b, &ep, radix); + if (ep == b) + return -1; + return result; +} + +#endif + +} + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif + + + diff --git a/boost/regex/v4/char_regex_traits.hpp b/boost/regex/v4/char_regex_traits.hpp new file mode 100644 index 00000000..e8a501ca --- /dev/null +++ b/boost/regex/v4/char_regex_traits.hpp @@ -0,0 +1,81 @@ +/* + * + * Copyright (c) 2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE char_regex_traits.cpp + * VERSION see + * DESCRIPTION: Declares deprecated traits classes char_regex_traits<>. + */ + + +#ifndef BOOST_REGEX_V4_CHAR_REGEX_TRAITS_HPP +#define BOOST_REGEX_V4_CHAR_REGEX_TRAITS_HPP + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +namespace boost{ + +namespace deprecated{ +// +// class char_regex_traits_i +// provides case insensitive traits classes (deprecated): +template +class char_regex_traits_i : public regex_traits {}; + +template<> +class char_regex_traits_i : public regex_traits +{ +public: + typedef char char_type; + typedef unsigned char uchar_type; + typedef unsigned int size_type; + typedef regex_traits base_type; + +}; + +#ifndef BOOST_NO_WREGEX +template<> +class char_regex_traits_i : public regex_traits +{ +public: + typedef wchar_t char_type; + typedef unsigned short uchar_type; + typedef unsigned int size_type; + typedef regex_traits base_type; + +}; +#endif +} // namespace deprecated +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // include + diff --git a/boost/regex/v4/cpp_regex_traits.hpp b/boost/regex/v4/cpp_regex_traits.hpp new file mode 100644 index 00000000..98b25151 --- /dev/null +++ b/boost/regex/v4/cpp_regex_traits.hpp @@ -0,0 +1,1237 @@ +/* + * + * Copyright (c) 2004 John Maddock + * Copyright 2011 Garmin Ltd. or its subsidiaries + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE cpp_regex_traits.hpp + * VERSION see + * DESCRIPTION: Declares regular expression traits class cpp_regex_traits. + */ + +#ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED + +#include +#include +#include + +#ifndef BOOST_NO_STD_LOCALE + +#ifndef BOOST_RE_PAT_EXCEPT_HPP +#include +#endif +#ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED +#include +#endif +#ifdef BOOST_HAS_THREADS +#include +#endif +#ifndef BOOST_REGEX_PRIMARY_TRANSFORM +#include +#endif +#ifndef BOOST_REGEX_OBJECT_CACHE_HPP +#include +#endif + +#include +#include +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4786 4251) +#endif + +namespace boost{ + +// +// forward declaration is needed by some compilers: +// +template +class cpp_regex_traits; + +namespace BOOST_REGEX_DETAIL_NS{ + +// +// class parser_buf: +// acts as a stream buffer which wraps around a pair of pointers: +// +template > +class parser_buf : public ::std::basic_streambuf +{ + typedef ::std::basic_streambuf base_type; + typedef typename base_type::int_type int_type; + typedef typename base_type::char_type char_type; + typedef typename base_type::pos_type pos_type; + typedef ::std::streamsize streamsize; + typedef typename base_type::off_type off_type; +public: + parser_buf() : base_type() { setbuf(0, 0); } + const charT* getnext() { return this->gptr(); } +protected: + std::basic_streambuf* setbuf(char_type* s, streamsize n) BOOST_OVERRIDE; + typename parser_buf::pos_type seekpos(pos_type sp, ::std::ios_base::openmode which) BOOST_OVERRIDE; + typename parser_buf::pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) BOOST_OVERRIDE; +private: + parser_buf& operator=(const parser_buf&); + parser_buf(const parser_buf&); +}; + +template +std::basic_streambuf* +parser_buf::setbuf(char_type* s, streamsize n) +{ + this->setg(s, s, s + n); + return this; +} + +template +typename parser_buf::pos_type +parser_buf::seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) +{ + typedef typename boost::int_t::least cast_type; + + if(which & ::std::ios_base::out) + return pos_type(off_type(-1)); + std::ptrdiff_t size = this->egptr() - this->eback(); + std::ptrdiff_t pos = this->gptr() - this->eback(); + charT* g = this->eback(); + switch(static_cast(way)) + { + case ::std::ios_base::beg: + if((off < 0) || (off > size)) + return pos_type(off_type(-1)); + else + this->setg(g, g + off, g + size); + break; + case ::std::ios_base::end: + if((off < 0) || (off > size)) + return pos_type(off_type(-1)); + else + this->setg(g, g + size - off, g + size); + break; + case ::std::ios_base::cur: + { + std::ptrdiff_t newpos = static_cast(pos + off); + if((newpos < 0) || (newpos > size)) + return pos_type(off_type(-1)); + else + this->setg(g, g + newpos, g + size); + break; + } + default: ; + } +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4244) +#endif + return static_cast(this->gptr() - this->eback()); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +typename parser_buf::pos_type +parser_buf::seekpos(pos_type sp, ::std::ios_base::openmode which) +{ + if(which & ::std::ios_base::out) + return pos_type(off_type(-1)); + off_type size = static_cast(this->egptr() - this->eback()); + charT* g = this->eback(); + if(off_type(sp) <= size) + { + this->setg(g, g + off_type(sp), g + size); + } + return pos_type(off_type(-1)); +} + +// +// class cpp_regex_traits_base: +// acts as a container for locale and the facets we are using. +// +template +struct cpp_regex_traits_base +{ + cpp_regex_traits_base(const std::locale& l) + { (void)imbue(l); } + std::locale imbue(const std::locale& l); + + std::locale m_locale; + std::ctype const* m_pctype; +#ifndef BOOST_NO_STD_MESSAGES + std::messages const* m_pmessages; +#endif + std::collate const* m_pcollate; + + bool operator<(const cpp_regex_traits_base& b)const + { + if(m_pctype == b.m_pctype) + { +#ifndef BOOST_NO_STD_MESSAGES + if(m_pmessages == b.m_pmessages) + { + return m_pcollate < b.m_pcollate; + } + return m_pmessages < b.m_pmessages; +#else + return m_pcollate < b.m_pcollate; +#endif + } + return m_pctype < b.m_pctype; + } + bool operator==(const cpp_regex_traits_base& b)const + { + return (m_pctype == b.m_pctype) +#ifndef BOOST_NO_STD_MESSAGES + && (m_pmessages == b.m_pmessages) +#endif + && (m_pcollate == b.m_pcollate); + } +}; + +template +std::locale cpp_regex_traits_base::imbue(const std::locale& l) +{ + std::locale result(m_locale); + m_locale = l; + m_pctype = &BOOST_USE_FACET(std::ctype, l); +#ifndef BOOST_NO_STD_MESSAGES + m_pmessages = BOOST_HAS_FACET(std::messages, l) ? &BOOST_USE_FACET(std::messages, l) : 0; +#endif + m_pcollate = &BOOST_USE_FACET(std::collate, l); + return result; +} + +// +// class cpp_regex_traits_char_layer: +// implements methods that require specialization for narrow characters: +// +template +class cpp_regex_traits_char_layer : public cpp_regex_traits_base +{ + typedef std::basic_string string_type; + typedef std::map map_type; + typedef typename map_type::const_iterator map_iterator_type; +public: + cpp_regex_traits_char_layer(const std::locale& l) + : cpp_regex_traits_base(l) + { + init(); + } + cpp_regex_traits_char_layer(const cpp_regex_traits_base& b) + : cpp_regex_traits_base(b) + { + init(); + } + void init(); + + regex_constants::syntax_type syntax_type(charT c)const + { + map_iterator_type i = m_char_map.find(c); + return ((i == m_char_map.end()) ? 0 : i->second); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + map_iterator_type i = m_char_map.find(c); + if(i == m_char_map.end()) + { + if(this->m_pctype->is(std::ctype_base::lower, c)) return regex_constants::escape_type_class; + if(this->m_pctype->is(std::ctype_base::upper, c)) return regex_constants::escape_type_not_class; + return 0; + } + return i->second; + } + +private: + string_type get_default_message(regex_constants::syntax_type); + // TODO: use a hash table when available! + map_type m_char_map; +}; + +template +void cpp_regex_traits_char_layer::init() +{ + // we need to start by initialising our syntax map so we know which + // character is used for which purpose: +#ifndef BOOST_NO_STD_MESSAGES +#ifndef __IBMCPP__ + typename std::messages::catalog cat = static_cast::catalog>(-1); +#else + typename std::messages::catalog cat = reinterpret_cast::catalog>(-1); +#endif + std::string cat_name(cpp_regex_traits::get_catalog_name()); + if((!cat_name.empty()) && (this->m_pmessages != 0)) + { + cat = this->m_pmessages->open( + cat_name, + this->m_locale); + if((int)cat < 0) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if((int)cat >= 0) + { +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + string_type mss = this->m_pmessages->get(cat, 0, i, get_default_message(i)); + for(typename string_type::size_type j = 0; j < mss.size(); ++j) + { + m_char_map[mss[j]] = i; + } + } + this->m_pmessages->close(cat); +#ifndef BOOST_NO_EXCEPTIONS + } + catch(...) + { + if(this->m_pmessages) + this->m_pmessages->close(cat); + throw; + } +#endif + } + else + { +#endif + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + const char* ptr = get_default_syntax(i); + while(ptr && *ptr) + { + m_char_map[this->m_pctype->widen(*ptr)] = i; + ++ptr; + } + } +#ifndef BOOST_NO_STD_MESSAGES + } +#endif +} + +template +typename cpp_regex_traits_char_layer::string_type + cpp_regex_traits_char_layer::get_default_message(regex_constants::syntax_type i) +{ + const char* ptr = get_default_syntax(i); + string_type result; + while(ptr && *ptr) + { + result.append(1, this->m_pctype->widen(*ptr)); + ++ptr; + } + return result; +} + +// +// specialized version for narrow characters: +// +template <> +class cpp_regex_traits_char_layer : public cpp_regex_traits_base +{ + typedef std::string string_type; +public: + cpp_regex_traits_char_layer(const std::locale& l) + : cpp_regex_traits_base(l) + { + init(); + } + cpp_regex_traits_char_layer(const cpp_regex_traits_base& l) + : cpp_regex_traits_base(l) + { + init(); + } + + regex_constants::syntax_type syntax_type(char c)const + { + return m_char_map[static_cast(c)]; + } + regex_constants::escape_syntax_type escape_syntax_type(char c) const + { + return m_char_map[static_cast(c)]; + } + +private: + regex_constants::syntax_type m_char_map[1u << CHAR_BIT]; + void init(); +}; + +#ifdef BOOST_REGEX_BUGGY_CTYPE_FACET +enum +{ + char_class_space=1<<0, + char_class_print=1<<1, + char_class_cntrl=1<<2, + char_class_upper=1<<3, + char_class_lower=1<<4, + char_class_alpha=1<<5, + char_class_digit=1<<6, + char_class_punct=1<<7, + char_class_xdigit=1<<8, + char_class_alnum=char_class_alpha|char_class_digit, + char_class_graph=char_class_alnum|char_class_punct, + char_class_blank=1<<9, + char_class_word=1<<10, + char_class_unicode=1<<11, + char_class_horizontal_space=1<<12, + char_class_vertical_space=1<<13 +}; + +#endif + +// +// class cpp_regex_traits_implementation: +// provides pimpl implementation for cpp_regex_traits. +// +template +class cpp_regex_traits_implementation : public cpp_regex_traits_char_layer +{ +public: + typedef typename cpp_regex_traits::char_class_type char_class_type; + typedef typename std::ctype::mask native_mask_type; + typedef typename boost::make_unsigned::type unsigned_native_mask_type; +#ifndef BOOST_REGEX_BUGGY_CTYPE_FACET + BOOST_STATIC_CONSTANT(char_class_type, mask_blank = 1u << 24); + BOOST_STATIC_CONSTANT(char_class_type, mask_word = 1u << 25); + BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 1u << 26); + BOOST_STATIC_CONSTANT(char_class_type, mask_horizontal = 1u << 27); + BOOST_STATIC_CONSTANT(char_class_type, mask_vertical = 1u << 28); +#endif + + typedef std::basic_string string_type; + typedef charT char_type; + //cpp_regex_traits_implementation(); + cpp_regex_traits_implementation(const std::locale& l) + : cpp_regex_traits_char_layer(l) + { + init(); + } + cpp_regex_traits_implementation(const cpp_regex_traits_base& l) + : cpp_regex_traits_char_layer(l) + { + init(); + } + std::string error_string(regex_constants::error_type n) const + { + if(!m_error_strings.empty()) + { + std::map::const_iterator p = m_error_strings.find(n); + return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second; + } + return get_default_error_string(n); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + char_class_type result = lookup_classname_imp(p1, p2); + if(result == 0) + { + string_type temp(p1, p2); + this->m_pctype->tolower(&*temp.begin(), &*temp.begin() + temp.size()); + result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size()); + } + return result; + } + string_type lookup_collatename(const charT* p1, const charT* p2) const; + string_type transform_primary(const charT* p1, const charT* p2) const; + string_type transform(const charT* p1, const charT* p2) const; +private: + std::map m_error_strings; // error messages indexed by numberic ID + std::map m_custom_class_names; // character class names + std::map m_custom_collate_names; // collating element names + unsigned m_collate_type; // the form of the collation string + charT m_collate_delim; // the collation group delimiter + // + // helpers: + // + char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const; + void init(); +#ifdef BOOST_REGEX_BUGGY_CTYPE_FACET +public: + bool isctype(charT c, char_class_type m)const; +#endif +}; + +#ifndef BOOST_REGEX_BUGGY_CTYPE_FACET +#if !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) + +template +typename cpp_regex_traits_implementation::char_class_type const cpp_regex_traits_implementation::mask_blank; +template +typename cpp_regex_traits_implementation::char_class_type const cpp_regex_traits_implementation::mask_word; +template +typename cpp_regex_traits_implementation::char_class_type const cpp_regex_traits_implementation::mask_unicode; +template +typename cpp_regex_traits_implementation::char_class_type const cpp_regex_traits_implementation::mask_vertical; +template +typename cpp_regex_traits_implementation::char_class_type const cpp_regex_traits_implementation::mask_horizontal; + +#endif +#endif + +template +typename cpp_regex_traits_implementation::string_type + cpp_regex_traits_implementation::transform_primary(const charT* p1, const charT* p2) const +{ + // + // PRECONDITIONS: + // + // A bug in gcc 3.2 (and maybe other versions as well) treats + // p1 as a null terminated string, for efficiency reasons + // we work around this elsewhere, but just assert here that + // we adhere to gcc's (buggy) preconditions... + // + BOOST_REGEX_ASSERT(*p2 == 0); + string_type result; +#if defined(_CPPLIB_VER) + // + // A bug in VC11 and 12 causes the program to hang if we pass a null-string + // to std::collate::transform, but only for certain locales :-( + // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware). + // + if(*p1 == 0) + { + return string_type(1, charT(0)); + } +#endif + // + // swallowing all exceptions here is a bad idea + // however at least one std lib will always throw + // std::bad_alloc for certain arguments... + // +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + // + // What we do here depends upon the format of the sort key returned by + // sort key returned by this->transform: + // + switch(m_collate_type) + { + case sort_C: + case sort_unknown: + // the best we can do is translate to lower case, then get a regular sort key: + { + result.assign(p1, p2); + this->m_pctype->tolower(&*result.begin(), &*result.begin() + result.size()); + result = this->m_pcollate->transform(&*result.begin(), &*result.begin() + result.size()); + break; + } + case sort_fixed: + { + // get a regular sort key, and then truncate it: + result.assign(this->m_pcollate->transform(p1, p2)); + result.erase(this->m_collate_delim); + break; + } + case sort_delim: + // get a regular sort key, and then truncate everything after the delim: + result.assign(this->m_pcollate->transform(p1, p2)); + std::size_t i; + for(i = 0; i < result.size(); ++i) + { + if(result[i] == m_collate_delim) + break; + } + result.erase(i); + break; + } +#ifndef BOOST_NO_EXCEPTIONS + }catch(...){} +#endif + while((!result.empty()) && (charT(0) == *result.rbegin())) + result.erase(result.size() - 1); + if(result.empty()) + { + // character is ignorable at the primary level: + result = string_type(1, charT(0)); + } + return result; +} + +template +typename cpp_regex_traits_implementation::string_type + cpp_regex_traits_implementation::transform(const charT* p1, const charT* p2) const +{ + // + // PRECONDITIONS: + // + // A bug in gcc 3.2 (and maybe other versions as well) treats + // p1 as a null terminated string, for efficiency reasons + // we work around this elsewhere, but just assert here that + // we adhere to gcc's (buggy) preconditions... + // + BOOST_REGEX_ASSERT(*p2 == 0); + // + // swallowing all exceptions here is a bad idea + // however at least one std lib will always throw + // std::bad_alloc for certain arguments... + // + string_type result, result2; +#if defined(_CPPLIB_VER) + // + // A bug in VC11 and 12 causes the program to hang if we pass a null-string + // to std::collate::transform, but only for certain locales :-( + // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware). + // + if(*p1 == 0) + { + return result; + } +#endif +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + result = this->m_pcollate->transform(p1, p2); + // + // Borland's STLPort version returns a NULL-terminated + // string that has garbage at the end - each call to + // std::collate::transform returns a different string! + // So as a workaround, we'll truncate the string at the first NULL + // which _seems_ to work.... +#if BOOST_WORKAROUND(BOOST_BORLANDC, < 0x580) + result.erase(result.find(charT(0))); +#else + // + // some implementations (Dinkumware) append unnecessary trailing \0's: + while((!result.empty()) && (charT(0) == *result.rbegin())) + result.erase(result.size() - 1); +#endif + // + // We may have NULL's used as separators between sections of the collate string, + // an example would be Boost.Locale. We have no way to detect this case via + // #defines since this can be used with any compiler/platform combination. + // Unfortunately our state machine (which was devised when all implementations + // used underlying C language API's) can't cope with that case. One workaround + // is to replace each character with 2, fortunately this code isn't used that + // much as this is now slower than before :-( + // + typedef typename make_unsigned::type uchar_type; + result2.reserve(result.size() * 2 + 2); + for(unsigned i = 0; i < result.size(); ++i) + { + if(static_cast(result[i]) == (std::numeric_limits::max)()) + { + result2.append(1, charT((std::numeric_limits::max)())).append(1, charT('b')); + } + else + { + result2.append(1, static_cast(1 + static_cast(result[i]))).append(1, charT('b') - 1); + } + } + BOOST_REGEX_ASSERT(std::find(result2.begin(), result2.end(), charT(0)) == result2.end()); +#ifndef BOOST_NO_EXCEPTIONS + } + catch(...) + { + } +#endif + return result2; +} + + +template +typename cpp_regex_traits_implementation::string_type + cpp_regex_traits_implementation::lookup_collatename(const charT* p1, const charT* p2) const +{ + typedef typename std::map::const_iterator iter_type; + if(!m_custom_collate_names.empty()) + { + iter_type pos = m_custom_collate_names.find(string_type(p1, p2)); + if(pos != m_custom_collate_names.end()) + return pos->second; + } +#if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\ + && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0551) + std::string name(p1, p2); +#else + std::string name; + const charT* p0 = p1; + while(p0 != p2) + name.append(1, char(*p0++)); +#endif + name = lookup_default_collate_name(name); +#if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\ + && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0551) + if(!name.empty()) + return string_type(name.begin(), name.end()); +#else + if(!name.empty()) + { + string_type result; + typedef std::string::const_iterator iter; + iter b = name.begin(); + iter e = name.end(); + while(b != e) + result.append(1, charT(*b++)); + return result; + } +#endif + if(p2 - p1 == 1) + return string_type(1, *p1); + return string_type(); +} + +template +void cpp_regex_traits_implementation::init() +{ +#ifndef BOOST_NO_STD_MESSAGES +#ifndef __IBMCPP__ + typename std::messages::catalog cat = static_cast::catalog>(-1); +#else + typename std::messages::catalog cat = reinterpret_cast::catalog>(-1); +#endif + std::string cat_name(cpp_regex_traits::get_catalog_name()); + if((!cat_name.empty()) && (this->m_pmessages != 0)) + { + cat = this->m_pmessages->open( + cat_name, + this->m_locale); + if((int)cat < 0) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if((int)cat >= 0) + { + // + // Error messages: + // + for(boost::regex_constants::error_type i = static_cast(0); + i <= boost::regex_constants::error_unknown; + i = static_cast(i + 1)) + { + const char* p = get_default_error_string(i); + string_type default_message; + while(*p) + { + default_message.append(1, this->m_pctype->widen(*p)); + ++p; + } + string_type s = this->m_pmessages->get(cat, 0, i+200, default_message); + std::string result; + for(std::string::size_type j = 0; j < s.size(); ++j) + { + result.append(1, this->m_pctype->narrow(s[j], 0)); + } + m_error_strings[i] = result; + } + // + // Custom class names: + // +#ifndef BOOST_REGEX_BUGGY_CTYPE_FACET + static const char_class_type masks[16] = + { + static_cast(std::ctype::alnum), + static_cast(std::ctype::alpha), + static_cast(std::ctype::cntrl), + static_cast(std::ctype::digit), + static_cast(std::ctype::graph), + cpp_regex_traits_implementation::mask_horizontal, + static_cast(std::ctype::lower), + static_cast(std::ctype::print), + static_cast(std::ctype::punct), + static_cast(std::ctype::space), + static_cast(std::ctype::upper), + cpp_regex_traits_implementation::mask_vertical, + static_cast(std::ctype::xdigit), + cpp_regex_traits_implementation::mask_blank, + cpp_regex_traits_implementation::mask_word, + cpp_regex_traits_implementation::mask_unicode, + }; +#else + static const char_class_type masks[16] = + { + ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_alpha, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_cntrl, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_graph, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_horizontal_space, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_print, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_punct, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_space, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_vertical_space, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_xdigit, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_blank, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_word, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_unicode, + }; +#endif + static const string_type null_string; + for(unsigned int j = 0; j <= 13; ++j) + { + string_type s(this->m_pmessages->get(cat, 0, j+300, null_string)); + if(!s.empty()) + this->m_custom_class_names[s] = masks[j]; + } + } +#endif + // + // get the collation format used by m_pcollate: + // + m_collate_type = BOOST_REGEX_DETAIL_NS::find_sort_syntax(this, &m_collate_delim); +} + +template +typename cpp_regex_traits_implementation::char_class_type + cpp_regex_traits_implementation::lookup_classname_imp(const charT* p1, const charT* p2) const +{ +#ifndef BOOST_REGEX_BUGGY_CTYPE_FACET + static const char_class_type masks[22] = + { + 0, + static_cast(std::ctype::alnum), + static_cast(std::ctype::alpha), + cpp_regex_traits_implementation::mask_blank, + static_cast(std::ctype::cntrl), + static_cast(std::ctype::digit), + static_cast(std::ctype::digit), + static_cast(std::ctype::graph), + cpp_regex_traits_implementation::mask_horizontal, + static_cast(std::ctype::lower), + static_cast(std::ctype::lower), + static_cast(std::ctype::print), + static_cast(std::ctype::punct), + static_cast(std::ctype::space), + static_cast(std::ctype::space), + static_cast(std::ctype::upper), + cpp_regex_traits_implementation::mask_unicode, + static_cast(std::ctype::upper), + cpp_regex_traits_implementation::mask_vertical, + static_cast(std::ctype::alnum) | cpp_regex_traits_implementation::mask_word, + static_cast(std::ctype::alnum) | cpp_regex_traits_implementation::mask_word, + static_cast(std::ctype::xdigit), + }; +#else + static const char_class_type masks[22] = + { + 0, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_alpha, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_blank, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_cntrl, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_graph, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_horizontal_space, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_print, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_punct, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_space, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_space, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_unicode, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_vertical_space, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum | ::boost::BOOST_REGEX_DETAIL_NS::char_class_word, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_alnum | ::boost::BOOST_REGEX_DETAIL_NS::char_class_word, + ::boost::BOOST_REGEX_DETAIL_NS::char_class_xdigit, + }; +#endif + if(!m_custom_class_names.empty()) + { + typedef typename std::map, char_class_type>::const_iterator map_iter; + map_iter pos = m_custom_class_names.find(string_type(p1, p2)); + if(pos != m_custom_class_names.end()) + return pos->second; + } + std::size_t state_id = 1 + BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2); + BOOST_REGEX_ASSERT(state_id < sizeof(masks) / sizeof(masks[0])); + return masks[state_id]; +} + +#ifdef BOOST_REGEX_BUGGY_CTYPE_FACET +template +bool cpp_regex_traits_implementation::isctype(const charT c, char_class_type mask) const +{ + return + ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_space) && (this->m_pctype->is(std::ctype::space, c))) + || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_print) && (this->m_pctype->is(std::ctype::print, c))) + || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_cntrl) && (this->m_pctype->is(std::ctype::cntrl, c))) + || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_upper) && (this->m_pctype->is(std::ctype::upper, c))) + || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_lower) && (this->m_pctype->is(std::ctype::lower, c))) + || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_alpha) && (this->m_pctype->is(std::ctype::alpha, c))) + || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_digit) && (this->m_pctype->is(std::ctype::digit, c))) + || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_punct) && (this->m_pctype->is(std::ctype::punct, c))) + || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_xdigit) && (this->m_pctype->is(std::ctype::xdigit, c))) + || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_blank) && (this->m_pctype->is(std::ctype::space, c)) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c)) + || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_word) && (c == '_')) + || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_unicode) && ::boost::BOOST_REGEX_DETAIL_NS::is_extended(c)) + || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_vertical_space) && (is_separator(c) || (c == '\v'))) + || ((mask & ::boost::BOOST_REGEX_DETAIL_NS::char_class_horizontal_space) && this->m_pctype->is(std::ctype::space, c) && !(is_separator(c) || (c == '\v'))); +} +#endif + + +template +inline boost::shared_ptr > create_cpp_regex_traits(const std::locale& l) +{ + cpp_regex_traits_base key(l); + return ::boost::object_cache, cpp_regex_traits_implementation >::get(key, 5); +} + +} // BOOST_REGEX_DETAIL_NS + +template +class cpp_regex_traits +{ +private: + typedef std::ctype ctype_type; +public: + typedef charT char_type; + typedef std::size_t size_type; + typedef std::basic_string string_type; + typedef std::locale locale_type; + typedef boost::uint_least32_t char_class_type; + + struct boost_extensions_tag{}; + + cpp_regex_traits() + : m_pimpl(BOOST_REGEX_DETAIL_NS::create_cpp_regex_traits(std::locale())) + { } + static size_type length(const char_type* p) + { + return std::char_traits::length(p); + } + regex_constants::syntax_type syntax_type(charT c)const + { + return m_pimpl->syntax_type(c); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + return m_pimpl->escape_syntax_type(c); + } + charT translate(charT c) const + { + return c; + } + charT translate_nocase(charT c) const + { + return m_pimpl->m_pctype->tolower(c); + } + charT translate(charT c, bool icase) const + { + return icase ? m_pimpl->m_pctype->tolower(c) : c; + } + charT tolower(charT c) const + { + return m_pimpl->m_pctype->tolower(c); + } + charT toupper(charT c) const + { + return m_pimpl->m_pctype->toupper(c); + } + string_type transform(const charT* p1, const charT* p2) const + { + return m_pimpl->transform(p1, p2); + } + string_type transform_primary(const charT* p1, const charT* p2) const + { + return m_pimpl->transform_primary(p1, p2); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_classname(p1, p2); + } + string_type lookup_collatename(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_collatename(p1, p2); + } + bool isctype(charT c, char_class_type f) const + { +#ifndef BOOST_REGEX_BUGGY_CTYPE_FACET + typedef typename std::ctype::mask ctype_mask; + + static const ctype_mask mask_base = + static_cast( + std::ctype::alnum + | std::ctype::alpha + | std::ctype::cntrl + | std::ctype::digit + | std::ctype::graph + | std::ctype::lower + | std::ctype::print + | std::ctype::punct + | std::ctype::space + | std::ctype::upper + | std::ctype::xdigit); + + if((f & mask_base) + && (m_pimpl->m_pctype->is( + static_cast(f & mask_base), c))) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation::mask_unicode) && BOOST_REGEX_DETAIL_NS::is_extended(c)) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation::mask_word) && (c == '_')) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation::mask_blank) + && m_pimpl->m_pctype->is(std::ctype::space, c) + && !BOOST_REGEX_DETAIL_NS::is_separator(c)) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation::mask_vertical) + && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v'))) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation::mask_horizontal) + && this->isctype(c, std::ctype::space) && !this->isctype(c, BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation::mask_vertical)) + return true; +#ifdef __CYGWIN__ + // + // Cygwin has a buggy ctype facet, see https://www.cygwin.com/ml/cygwin/2012-08/msg00178.html: + // + else if((f & std::ctype::xdigit) == std::ctype::xdigit) + { + if((c >= 'a') && (c <= 'f')) + return true; + if((c >= 'A') && (c <= 'F')) + return true; + } +#endif + return false; +#else + return m_pimpl->isctype(c, f); +#endif + } + boost::intmax_t toi(const charT*& p1, const charT* p2, int radix)const; + int value(charT c, int radix)const + { + const charT* pc = &c; + return (int)toi(pc, pc + 1, radix); + } + locale_type imbue(locale_type l) + { + std::locale result(getloc()); + m_pimpl = BOOST_REGEX_DETAIL_NS::create_cpp_regex_traits(l); + return result; + } + locale_type getloc()const + { + return m_pimpl->m_locale; + } + std::string error_string(regex_constants::error_type n) const + { + return m_pimpl->error_string(n); + } + + // + // extension: + // set the name of the message catalog in use (defaults to "boost_regex"). + // + static std::string catalog_name(const std::string& name); + static std::string get_catalog_name(); + +private: + boost::shared_ptr > m_pimpl; + // + // catalog name handler: + // + static std::string& get_catalog_name_inst(); + +#ifdef BOOST_HAS_THREADS + static static_mutex& get_mutex_inst(); +#endif +}; + + +template +boost::intmax_t cpp_regex_traits::toi(const charT*& first, const charT* last, int radix)const +{ + BOOST_REGEX_DETAIL_NS::parser_buf sbuf; // buffer for parsing numbers. + std::basic_istream is(&sbuf); // stream for parsing numbers. + + // we do NOT want to parse any thousands separators inside the stream: + last = std::find(first, last, BOOST_USE_FACET(std::numpunct, is.getloc()).thousands_sep()); + + sbuf.pubsetbuf(const_cast(static_cast(first)), static_cast(last-first)); + is.clear(); + if(std::abs(radix) == 16) is >> std::hex; + else if(std::abs(radix) == 8) is >> std::oct; + else is >> std::dec; + boost::intmax_t val; + if(is >> val) + { + first = first + ((last - first) - sbuf.in_avail()); + return val; + } + else + return -1; +} + +template +std::string cpp_regex_traits::catalog_name(const std::string& name) +{ +#ifdef BOOST_HAS_THREADS + static_mutex::scoped_lock lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + get_catalog_name_inst() = name; + return result; +} + +template +std::string& cpp_regex_traits::get_catalog_name_inst() +{ + static std::string s_name; + return s_name; +} + +template +std::string cpp_regex_traits::get_catalog_name() +{ +#ifdef BOOST_HAS_THREADS + static_mutex::scoped_lock lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + return result; +} + +#ifdef BOOST_HAS_THREADS +template +static_mutex& cpp_regex_traits::get_mutex_inst() +{ + static static_mutex s_mutex = BOOST_STATIC_MUTEX_INIT; + return s_mutex; +} +#endif + +namespace BOOST_REGEX_DETAIL_NS { + + inline void cpp_regex_traits_char_layer::init() + { + // we need to start by initialising our syntax map so we know which + // character is used for which purpose: + std::memset(m_char_map, 0, sizeof(m_char_map)); +#ifndef BOOST_NO_STD_MESSAGES +#ifndef __IBMCPP__ + std::messages::catalog cat = static_cast::catalog>(-1); +#else + std::messages::catalog cat = reinterpret_cast::catalog>(-1); +#endif + std::string cat_name(cpp_regex_traits::get_catalog_name()); + if ((!cat_name.empty()) && (m_pmessages != 0)) + { + cat = this->m_pmessages->open( + cat_name, + this->m_locale); + if ((int)cat < 0) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if ((int)cat >= 0) + { +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + string_type mss = this->m_pmessages->get(cat, 0, i, get_default_syntax(i)); + for (string_type::size_type j = 0; j < mss.size(); ++j) + { + m_char_map[static_cast(mss[j])] = i; + } + } + this->m_pmessages->close(cat); +#ifndef BOOST_NO_EXCEPTIONS + } + catch (...) + { + this->m_pmessages->close(cat); + throw; + } +#endif + } + else + { +#endif + for (regex_constants::syntax_type j = 1; j < regex_constants::syntax_max; ++j) + { + const char* ptr = get_default_syntax(j); + while (ptr && *ptr) + { + m_char_map[static_cast(*ptr)] = j; + ++ptr; + } + } +#ifndef BOOST_NO_STD_MESSAGES + } +#endif + // + // finish off by calculating our escape types: + // + unsigned char i = 'A'; + do + { + if (m_char_map[i] == 0) + { + if (this->m_pctype->is(std::ctype_base::lower, i)) + m_char_map[i] = regex_constants::escape_type_class; + else if (this->m_pctype->is(std::ctype_base::upper, i)) + m_char_map[i] = regex_constants::escape_type_not_class; + } + } while (0xFF != i++); + } + +} // namespace detail + + +} // boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif + +#endif diff --git a/boost/regex/v4/cregex.hpp b/boost/regex/v4/cregex.hpp new file mode 100644 index 00000000..dec49c9b --- /dev/null +++ b/boost/regex/v4/cregex.hpp @@ -0,0 +1,213 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE cregex.cpp + * VERSION see + * DESCRIPTION: Declares POSIX API functions + * + boost::RegEx high level wrapper. + */ + +#ifndef BOOST_RE_CREGEX_HPP_INCLUDED +#define BOOST_RE_CREGEX_HPP_INCLUDED + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif +#include +#include + +#ifdef __cplusplus +#include +#else +#include +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +/* include these defs only for POSIX compatablity */ +#ifdef __cplusplus +namespace boost{ +extern "C" { +#endif + +#if defined(__cplusplus) && !defined(BOOST_NO_STDC_NAMESPACE) +typedef std::ptrdiff_t regoff_t; +typedef std::size_t regsize_t; +#else +typedef ptrdiff_t regoff_t; +typedef size_t regsize_t; +#endif + +typedef struct +{ + unsigned int re_magic; +#ifdef __cplusplus + std::size_t re_nsub; /* number of parenthesized subexpressions */ +#else + size_t re_nsub; +#endif + const char* re_endp; /* end pointer for REG_PEND */ + void* guts; /* none of your business :-) */ + match_flag_type eflags; /* none of your business :-) */ +} regex_tA; + +#ifndef BOOST_NO_WREGEX +typedef struct +{ + unsigned int re_magic; +#ifdef __cplusplus + std::size_t re_nsub; /* number of parenthesized subexpressions */ +#else + size_t re_nsub; +#endif + const wchar_t* re_endp; /* end pointer for REG_PEND */ + void* guts; /* none of your business :-) */ + match_flag_type eflags; /* none of your business :-) */ +} regex_tW; +#endif + +typedef struct +{ + regoff_t rm_so; /* start of match */ + regoff_t rm_eo; /* end of match */ +} regmatch_t; + +/* regcomp() flags */ +typedef enum{ + REG_BASIC = 0000, + REG_EXTENDED = 0001, + REG_ICASE = 0002, + REG_NOSUB = 0004, + REG_NEWLINE = 0010, + REG_NOSPEC = 0020, + REG_PEND = 0040, + REG_DUMP = 0200, + REG_NOCOLLATE = 0400, + REG_ESCAPE_IN_LISTS = 01000, + REG_NEWLINE_ALT = 02000, + REG_PERLEX = 04000, + + REG_PERL = REG_EXTENDED | REG_NOCOLLATE | REG_ESCAPE_IN_LISTS | REG_PERLEX, + REG_AWK = REG_EXTENDED | REG_ESCAPE_IN_LISTS, + REG_GREP = REG_BASIC | REG_NEWLINE_ALT, + REG_EGREP = REG_EXTENDED | REG_NEWLINE_ALT, + + REG_ASSERT = 15, + REG_INVARG = 16, + REG_ATOI = 255, /* convert name to number (!) */ + REG_ITOA = 0400 /* convert number to name (!) */ +} reg_comp_flags; + +/* regexec() flags */ +typedef enum{ + REG_NOTBOL = 00001, + REG_NOTEOL = 00002, + REG_STARTEND = 00004 +} reg_exec_flags; + +/* + * POSIX error codes: + */ +typedef unsigned reg_error_t; +typedef reg_error_t reg_errcode_t; /* backwards compatibility */ + +static const reg_error_t REG_NOERROR = 0; /* Success. */ +static const reg_error_t REG_NOMATCH = 1; /* Didn't find a match (for regexec). */ + + /* POSIX regcomp return error codes. (In the order listed in the + standard.) */ +static const reg_error_t REG_BADPAT = 2; /* Invalid pattern. */ +static const reg_error_t REG_ECOLLATE = 3; /* Undefined collating element. */ +static const reg_error_t REG_ECTYPE = 4; /* Invalid character class name. */ +static const reg_error_t REG_EESCAPE = 5; /* Trailing backslash. */ +static const reg_error_t REG_ESUBREG = 6; /* Invalid back reference. */ +static const reg_error_t REG_EBRACK = 7; /* Unmatched left bracket. */ +static const reg_error_t REG_EPAREN = 8; /* Parenthesis imbalance. */ +static const reg_error_t REG_EBRACE = 9; /* Unmatched \{. */ +static const reg_error_t REG_BADBR = 10; /* Invalid contents of \{\}. */ +static const reg_error_t REG_ERANGE = 11; /* Invalid range end. */ +static const reg_error_t REG_ESPACE = 12; /* Ran out of memory. */ +static const reg_error_t REG_BADRPT = 13; /* No preceding re for repetition op. */ +static const reg_error_t REG_EEND = 14; /* unexpected end of expression */ +static const reg_error_t REG_ESIZE = 15; /* expression too big */ +static const reg_error_t REG_ERPAREN = 8; /* = REG_EPAREN : unmatched right parenthesis */ +static const reg_error_t REG_EMPTY = 17; /* empty expression */ +static const reg_error_t REG_E_MEMORY = 15; /* = REG_ESIZE : out of memory */ +static const reg_error_t REG_ECOMPLEXITY = 18; /* complexity too high */ +static const reg_error_t REG_ESTACK = 19; /* out of stack space */ +static const reg_error_t REG_E_PERL = 20; /* Perl (?...) error */ +static const reg_error_t REG_E_UNKNOWN = 21; /* unknown error */ +static const reg_error_t REG_ENOSYS = 21; /* = REG_E_UNKNOWN : Reserved. */ + +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompA(regex_tA*, const char*, int); +BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int, const regex_tA*, char*, regsize_t); +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecA(const regex_tA*, const char*, regsize_t, regmatch_t*, int); +BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeA(regex_tA*); + +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompW(regex_tW*, const wchar_t*, int); +BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int, const regex_tW*, wchar_t*, regsize_t); +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecW(const regex_tW*, const wchar_t*, regsize_t, regmatch_t*, int); +BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeW(regex_tW*); +#endif + +#ifdef UNICODE +#define regcomp regcompW +#define regerror regerrorW +#define regexec regexecW +#define regfree regfreeW +#define regex_t regex_tW +#else +#define regcomp regcompA +#define regerror regerrorA +#define regexec regexecA +#define regfree regfreeA +#define regex_t regex_tA +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef __cplusplus +} /* extern "C" */ +} /* namespace */ +#endif + +#endif /* include guard */ + + + + + + + + + + diff --git a/boost/regex/v4/error_type.hpp b/boost/regex/v4/error_type.hpp new file mode 100644 index 00000000..afcc71e3 --- /dev/null +++ b/boost/regex/v4/error_type.hpp @@ -0,0 +1,59 @@ +/* + * + * Copyright (c) 2003-2005 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE error_type.hpp + * VERSION see + * DESCRIPTION: Declares regular expression error type enumerator. + */ + +#ifndef BOOST_REGEX_ERROR_TYPE_HPP +#define BOOST_REGEX_ERROR_TYPE_HPP + +#ifdef __cplusplus +namespace boost{ +#endif + +#ifdef __cplusplus +namespace regex_constants{ + +enum error_type{ + + error_ok = 0, /* not used */ + error_no_match = 1, /* not used */ + error_bad_pattern = 2, + error_collate = 3, + error_ctype = 4, + error_escape = 5, + error_backref = 6, + error_brack = 7, + error_paren = 8, + error_brace = 9, + error_badbrace = 10, + error_range = 11, + error_space = 12, + error_badrepeat = 13, + error_end = 14, /* not used */ + error_size = 15, + error_right_paren = 16, /* not used */ + error_empty = 17, + error_complexity = 18, + error_stack = 19, + error_perl_extension = 20, + error_unknown = 21 +}; + +} +} +#endif /* __cplusplus */ + +#endif diff --git a/boost/regex/v4/indexed_bit_flag.hpp b/boost/regex/v4/indexed_bit_flag.hpp new file mode 100644 index 00000000..c9d32c59 --- /dev/null +++ b/boost/regex/v4/indexed_bit_flag.hpp @@ -0,0 +1,54 @@ +/* + * + * Copyright (c) 2020 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE basic_regex_parser.cpp + * VERSION see + * DESCRIPTION: Declares template class basic_regex_parser. + */ + +#include +#include + +#ifndef BOOST_REGEX_V4_INDEXED_BIT_FLAG_HPP +#define BOOST_REGEX_V4_INDEXED_BIT_FLAG_HPP + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +class indexed_bit_flag +{ + boost::uint64_t low_mask; + std::set mask_set; +public: + indexed_bit_flag() : low_mask(0) {} + void set(std::size_t i) + { + if (i < std::numeric_limits::digits - 1) + low_mask |= static_cast(1u) << i; + else + mask_set.insert(i); + } + bool test(std::size_t i) + { + if (i < std::numeric_limits::digits - 1) + return low_mask & static_cast(1u) << i ? true : false; + else + return mask_set.find(i) != mask_set.end(); + } +}; + +} // namespace BOOST_REGEX_DETAIL_NS +} // namespace boost + + +#endif diff --git a/boost/regex/v4/iterator_category.hpp b/boost/regex/v4/iterator_category.hpp new file mode 100644 index 00000000..9e401423 --- /dev/null +++ b/boost/regex/v4/iterator_category.hpp @@ -0,0 +1,91 @@ +/* + * + * Copyright (c) 2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_match.hpp + * VERSION see + * DESCRIPTION: Iterator traits for selecting an iterator type as + * an integral constant expression. + */ + + +#ifndef BOOST_REGEX_ITERATOR_CATEGORY_HPP +#define BOOST_REGEX_ITERATOR_CATEGORY_HPP + +#include +#include +#include + +namespace boost{ +namespace detail{ + +template +struct is_random_imp +{ +#ifndef BOOST_NO_STD_ITERATOR_TRAITS +private: + typedef typename std::iterator_traits::iterator_category cat; +public: + BOOST_STATIC_CONSTANT(bool, value = (::boost::is_convertible::value)); +#else + BOOST_STATIC_CONSTANT(bool, value = false); +#endif +}; + +template +struct is_random_pointer_imp +{ + BOOST_STATIC_CONSTANT(bool, value = true); +}; + +template +struct is_random_imp_selector +{ + template + struct rebind + { + typedef is_random_imp type; + }; +}; + +template <> +struct is_random_imp_selector +{ + template + struct rebind + { + typedef is_random_pointer_imp type; + }; +}; + +} + +template +struct is_random_access_iterator +{ +private: + typedef detail::is_random_imp_selector< ::boost::is_pointer::value> selector; + typedef typename selector::template rebind bound_type; + typedef typename bound_type::type answer; +public: + BOOST_STATIC_CONSTANT(bool, value = answer::value); +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +template +const bool is_random_access_iterator::value; +#endif + +} + +#endif + diff --git a/boost/regex/v4/iterator_traits.hpp b/boost/regex/v4/iterator_traits.hpp new file mode 100644 index 00000000..ae45ecb8 --- /dev/null +++ b/boost/regex/v4/iterator_traits.hpp @@ -0,0 +1,135 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE iterator_traits.cpp + * VERSION see + * DESCRIPTION: Declares iterator traits workarounds. + */ + +#ifndef BOOST_REGEX_V4_ITERATOR_TRAITS_HPP +#define BOOST_REGEX_V4_ITERATOR_TRAITS_HPP + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +#if defined(BOOST_NO_STD_ITERATOR_TRAITS) + +template +struct regex_iterator_traits +{ + typedef typename T::iterator_category iterator_category; + typedef typename T::value_type value_type; +#if !defined(BOOST_NO_STD_ITERATOR) + typedef typename T::difference_type difference_type; + typedef typename T::pointer pointer; + typedef typename T::reference reference; +#else + typedef std::ptrdiff_t difference_type; + typedef value_type* pointer; + typedef value_type& reference; +#endif +}; + +template +struct pointer_iterator_traits +{ + typedef std::ptrdiff_t difference_type; + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef std::random_access_iterator_tag iterator_category; +}; +template +struct const_pointer_iterator_traits +{ + typedef std::ptrdiff_t difference_type; + typedef T value_type; + typedef const T* pointer; + typedef const T& reference; + typedef std::random_access_iterator_tag iterator_category; +}; + +template<> +struct regex_iterator_traits : pointer_iterator_traits{}; +template<> +struct regex_iterator_traits : const_pointer_iterator_traits{}; +template<> +struct regex_iterator_traits : pointer_iterator_traits{}; +template<> +struct regex_iterator_traits : const_pointer_iterator_traits{}; +// +// the follwoing are needed for ICU support: +// +template<> +struct regex_iterator_traits : pointer_iterator_traits{}; +template<> +struct regex_iterator_traits : const_pointer_iterator_traits{}; +template<> +struct regex_iterator_traits : pointer_iterator_traits{}; +template<> +struct regex_iterator_traits : const_pointer_iterator_traits{}; + +#ifdef BOOST_REGEX_HAS_OTHER_WCHAR_T +template<> +struct regex_iterator_traits : pointer_iterator_traits{}; +template<> +struct regex_iterator_traits : const_pointer_iterator_traits{}; +#endif + +#if defined(__SGI_STL_PORT) && defined(__STL_DEBUG) +template<> +struct regex_iterator_traits : pointer_iterator_traits{}; +template<> +struct regex_iterator_traits : const_pointer_iterator_traits{}; +#ifndef BOOST_NO_STD_WSTRING +template<> +struct regex_iterator_traits : pointer_iterator_traits{}; +template<> +struct regex_iterator_traits : const_pointer_iterator_traits{}; +#endif // BOOST_NO_WSTRING +#endif // stport + +#else + +template +struct regex_iterator_traits : public std::iterator_traits {}; + +#endif + +} // namespace BOOST_REGEX_DETAIL_NS +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif + diff --git a/boost/regex/v4/match_flags.hpp b/boost/regex/v4/match_flags.hpp new file mode 100644 index 00000000..5dc72655 --- /dev/null +++ b/boost/regex/v4/match_flags.hpp @@ -0,0 +1,161 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE match_flags.hpp + * VERSION see + * DESCRIPTION: Declares match_flags type. + */ + +#ifndef BOOST_REGEX_V4_MATCH_FLAGS +#define BOOST_REGEX_V4_MATCH_FLAGS + +#ifdef __cplusplus +# include +#endif + +#ifdef __cplusplus +namespace boost{ + namespace regex_constants{ +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#if BOOST_MSVC >= 1800 +#pragma warning(disable : 26812) +#endif +#endif + +typedef enum _match_flags +{ + match_default = 0, + match_not_bol = 1, /* first is not start of line */ + match_not_eol = match_not_bol << 1, /* last is not end of line */ + match_not_bob = match_not_eol << 1, /* first is not start of buffer */ + match_not_eob = match_not_bob << 1, /* last is not end of buffer */ + match_not_bow = match_not_eob << 1, /* first is not start of word */ + match_not_eow = match_not_bow << 1, /* last is not end of word */ + match_not_dot_newline = match_not_eow << 1, /* \n is not matched by '.' */ + match_not_dot_null = match_not_dot_newline << 1, /* '\0' is not matched by '.' */ + match_prev_avail = match_not_dot_null << 1, /* *--first is a valid expression */ + match_init = match_prev_avail << 1, /* internal use */ + match_any = match_init << 1, /* don't care what we match */ + match_not_null = match_any << 1, /* string can't be null */ + match_continuous = match_not_null << 1, /* each grep match must continue from */ + /* uninterrupted from the previous one */ + match_partial = match_continuous << 1, /* find partial matches */ + + match_stop = match_partial << 1, /* stop after first match (grep) V3 only */ + match_not_initial_null = match_stop, /* don't match initial null, V4 only */ + match_all = match_stop << 1, /* must find the whole of input even if match_any is set */ + match_perl = match_all << 1, /* Use perl matching rules */ + match_posix = match_perl << 1, /* Use POSIX matching rules */ + match_nosubs = match_posix << 1, /* don't trap marked subs */ + match_extra = match_nosubs << 1, /* include full capture information for repeated captures */ + match_single_line = match_extra << 1, /* treat text as single line and ignore any \n's when matching ^ and $. */ + match_unused1 = match_single_line << 1, /* unused */ + match_unused2 = match_unused1 << 1, /* unused */ + match_unused3 = match_unused2 << 1, /* unused */ + match_max = match_unused3, + + format_perl = 0, /* perl style replacement */ + format_default = 0, /* ditto. */ + format_sed = match_max << 1, /* sed style replacement. */ + format_all = format_sed << 1, /* enable all extensions to syntax. */ + format_no_copy = format_all << 1, /* don't copy non-matching segments. */ + format_first_only = format_no_copy << 1, /* Only replace first occurrence. */ + format_is_if = format_first_only << 1, /* internal use only. */ + format_literal = format_is_if << 1, /* treat string as a literal */ + + match_not_any = match_not_bol | match_not_eol | match_not_bob + | match_not_eob | match_not_bow | match_not_eow | match_not_dot_newline + | match_not_dot_null | match_prev_avail | match_init | match_not_null + | match_continuous | match_partial | match_stop | match_not_initial_null + | match_stop | match_all | match_perl | match_posix | match_nosubs + | match_extra | match_single_line | match_unused1 | match_unused2 + | match_unused3 | match_max | format_perl | format_default | format_sed + | format_all | format_no_copy | format_first_only | format_is_if + | format_literal + + +} match_flags; + +#if defined(BOOST_BORLANDC) || (defined(_MSC_VER) && (_MSC_VER <= 1310)) +typedef unsigned long match_flag_type; +#else +typedef match_flags match_flag_type; + + +#ifdef __cplusplus +inline match_flags operator&(match_flags m1, match_flags m2) +{ return static_cast(static_cast(m1) & static_cast(m2)); } +inline match_flags operator|(match_flags m1, match_flags m2) +{ return static_cast(static_cast(m1) | static_cast(m2)); } +inline match_flags operator^(match_flags m1, match_flags m2) +{ return static_cast(static_cast(m1) ^ static_cast(m2)); } +inline match_flags operator~(match_flags m1) +{ return static_cast(~static_cast(m1)); } +inline match_flags& operator&=(match_flags& m1, match_flags m2) +{ m1 = m1&m2; return m1; } +inline match_flags& operator|=(match_flags& m1, match_flags m2) +{ m1 = m1|m2; return m1; } +inline match_flags& operator^=(match_flags& m1, match_flags m2) +{ m1 = m1^m2; return m1; } +#endif +#endif + +#ifdef __cplusplus +} /* namespace regex_constants */ +/* + * import names into boost for backwards compatibility: + */ +using regex_constants::match_flag_type; +using regex_constants::match_default; +using regex_constants::match_not_bol; +using regex_constants::match_not_eol; +using regex_constants::match_not_bob; +using regex_constants::match_not_eob; +using regex_constants::match_not_bow; +using regex_constants::match_not_eow; +using regex_constants::match_not_dot_newline; +using regex_constants::match_not_dot_null; +using regex_constants::match_prev_avail; +/* using regex_constants::match_init; */ +using regex_constants::match_any; +using regex_constants::match_not_null; +using regex_constants::match_continuous; +using regex_constants::match_partial; +/*using regex_constants::match_stop; */ +using regex_constants::match_all; +using regex_constants::match_perl; +using regex_constants::match_posix; +using regex_constants::match_nosubs; +using regex_constants::match_extra; +using regex_constants::match_single_line; +/*using regex_constants::match_max; */ +using regex_constants::format_all; +using regex_constants::format_sed; +using regex_constants::format_perl; +using regex_constants::format_default; +using regex_constants::format_no_copy; +using regex_constants::format_first_only; +/*using regex_constants::format_is_if;*/ + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + + +} /* namespace boost */ +#endif /* __cplusplus */ +#endif /* include guard */ + diff --git a/boost/regex/v4/match_results.hpp b/boost/regex/v4/match_results.hpp new file mode 100644 index 00000000..c580e4fc --- /dev/null +++ b/boost/regex/v4/match_results.hpp @@ -0,0 +1,716 @@ +/* + * + * Copyright (c) 1998-2009 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE match_results.cpp + * VERSION see + * DESCRIPTION: Declares template class match_results. + */ + +#ifndef BOOST_REGEX_V4_MATCH_RESULTS_HPP +#define BOOST_REGEX_V4_MATCH_RESULTS_HPP + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +namespace boost{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable : 4251) +#if BOOST_MSVC < 1700 +# pragma warning(disable : 4231) +#endif +# if BOOST_MSVC < 1600 +# pragma warning(disable : 4660) +# endif +#endif + +namespace BOOST_REGEX_DETAIL_NS{ + +class named_subexpressions; + +} + +template +class match_results +{ +private: +#ifndef BOOST_NO_STD_ALLOCATOR + typedef std::vector, Allocator> vector_type; +#else + typedef std::vector > vector_type; +#endif +public: + typedef sub_match value_type; +#ifndef BOOST_NO_CXX11_ALLOCATOR + typedef typename std::allocator_traits::value_type const & const_reference; +#elif !defined(BOOST_NO_STD_ALLOCATOR) && !(defined(BOOST_MSVC) && defined(_STLPORT_VERSION)) + typedef typename Allocator::const_reference const_reference; +#else + typedef const value_type& const_reference; +#endif + typedef const_reference reference; + typedef typename vector_type::const_iterator const_iterator; + typedef const_iterator iterator; + typedef typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits< + BidiIterator>::difference_type difference_type; +#ifdef BOOST_NO_CXX11_ALLOCATOR + typedef typename Allocator::size_type size_type; +#else + typedef typename std::allocator_traits::size_type size_type; +#endif + typedef Allocator allocator_type; + typedef typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits< + BidiIterator>::value_type char_type; + typedef std::basic_string string_type; + typedef BOOST_REGEX_DETAIL_NS::named_subexpressions named_sub_type; + + // construct/copy/destroy: + explicit match_results(const Allocator& a = Allocator()) +#ifndef BOOST_NO_STD_ALLOCATOR + : m_subs(a), m_base(), m_null(), m_last_closed_paren(0), m_is_singular(true) {} +#else + : m_subs(), m_base(), m_null(), m_last_closed_paren(0), m_is_singular(true) { (void)a; } +#endif + // + // IMPORTANT: in the code below, the crazy looking checks around m_is_singular are + // all required because it is illegal to copy a singular iterator. + // See https://svn.boost.org/trac/boost/ticket/3632. + // + match_results(const match_results& m) + : m_subs(m.m_subs), m_base(), m_null(), m_named_subs(m.m_named_subs), m_last_closed_paren(m.m_last_closed_paren), m_is_singular(m.m_is_singular) + { + if(!m_is_singular) + { + m_base = m.m_base; + m_null = m.m_null; + } + } + match_results& operator=(const match_results& m) + { + m_subs = m.m_subs; + m_named_subs = m.m_named_subs; + m_last_closed_paren = m.m_last_closed_paren; + m_is_singular = m.m_is_singular; + if(!m_is_singular) + { + m_base = m.m_base; + m_null = m.m_null; + } + return *this; + } + ~match_results(){} + + // size: + size_type size() const + { return empty() ? 0 : m_subs.size() - 2; } + size_type max_size() const + { return m_subs.max_size(); } + bool empty() const + { return m_subs.size() < 2; } + // element access: + difference_type length(int sub = 0) const + { + if(m_is_singular) + raise_logic_error(); + sub += 2; + if((sub < (int)m_subs.size()) && (sub > 0)) + return m_subs[sub].length(); + return 0; + } + difference_type length(const char_type* sub) const + { + if(m_is_singular) + raise_logic_error(); + const char_type* sub_end = sub; + while(*sub_end) ++sub_end; + return length(named_subexpression_index(sub, sub_end)); + } + template + difference_type length(const charT* sub) const + { + if(m_is_singular) + raise_logic_error(); + const charT* sub_end = sub; + while(*sub_end) ++sub_end; + return length(named_subexpression_index(sub, sub_end)); + } + template + difference_type length(const std::basic_string& sub) const + { + return length(sub.c_str()); + } + difference_type position(size_type sub = 0) const + { + if(m_is_singular) + raise_logic_error(); + sub += 2; + if(sub < m_subs.size()) + { + const sub_match& s = m_subs[sub]; + if(s.matched || (sub == 2)) + { + return ::boost::BOOST_REGEX_DETAIL_NS::distance((BidiIterator)(m_base), (BidiIterator)(s.first)); + } + } + return ~static_cast(0); + } + difference_type position(const char_type* sub) const + { + const char_type* sub_end = sub; + while(*sub_end) ++sub_end; + return position(named_subexpression_index(sub, sub_end)); + } + template + difference_type position(const charT* sub) const + { + const charT* sub_end = sub; + while(*sub_end) ++sub_end; + return position(named_subexpression_index(sub, sub_end)); + } + template + difference_type position(const std::basic_string& sub) const + { + return position(sub.c_str()); + } + string_type str(int sub = 0) const + { + if(m_is_singular) + raise_logic_error(); + sub += 2; + string_type result; + if(sub < (int)m_subs.size() && (sub > 0)) + { + const sub_match& s = m_subs[sub]; + if(s.matched) + { + result = s.str(); + } + } + return result; + } + string_type str(const char_type* sub) const + { + return (*this)[sub].str(); + } + template + string_type str(const std::basic_string& sub) const + { + return (*this)[sub].str(); + } + template + string_type str(const charT* sub) const + { + return (*this)[sub].str(); + } + template + string_type str(const std::basic_string& sub) const + { + return (*this)[sub].str(); + } + const_reference operator[](int sub) const + { + if(m_is_singular && m_subs.empty()) + raise_logic_error(); + sub += 2; + if(sub < (int)m_subs.size() && (sub >= 0)) + { + return m_subs[sub]; + } + return m_null; + } + // + // Named sub-expressions: + // + const_reference named_subexpression(const char_type* i, const char_type* j) const + { + // + // Scan for the leftmost *matched* subexpression with the specified named: + // + if(m_is_singular) + raise_logic_error(); + BOOST_REGEX_DETAIL_NS::named_subexpressions::range_type r = m_named_subs->equal_range(i, j); + while((r.first != r.second) && ((*this)[r.first->index].matched == false)) + ++r.first; + return r.first != r.second ? (*this)[r.first->index] : m_null; + } + template + const_reference named_subexpression(const charT* i, const charT* j) const + { + BOOST_STATIC_ASSERT(sizeof(charT) <= sizeof(char_type)); + if(i == j) + return m_null; + std::vector s; + while(i != j) + s.insert(s.end(), *i++); + return named_subexpression(&*s.begin(), &*s.begin() + s.size()); + } + int named_subexpression_index(const char_type* i, const char_type* j) const + { + // + // Scan for the leftmost *matched* subexpression with the specified named. + // If none found then return the leftmost expression with that name, + // otherwise an invalid index: + // + if(m_is_singular) + raise_logic_error(); + BOOST_REGEX_DETAIL_NS::named_subexpressions::range_type s, r; + s = r = m_named_subs->equal_range(i, j); + while((r.first != r.second) && ((*this)[r.first->index].matched == false)) + ++r.first; + if(r.first == r.second) + r = s; + return r.first != r.second ? r.first->index : -20; + } + template + int named_subexpression_index(const charT* i, const charT* j) const + { + BOOST_STATIC_ASSERT(sizeof(charT) <= sizeof(char_type)); + if(i == j) + return -20; + std::vector s; + while(i != j) + s.insert(s.end(), *i++); + return named_subexpression_index(&*s.begin(), &*s.begin() + s.size()); + } + template + const_reference operator[](const std::basic_string& s) const + { + return named_subexpression(s.c_str(), s.c_str() + s.size()); + } + const_reference operator[](const char_type* p) const + { + const char_type* e = p; + while(*e) ++e; + return named_subexpression(p, e); + } + + template + const_reference operator[](const charT* p) const + { + BOOST_STATIC_ASSERT(sizeof(charT) <= sizeof(char_type)); + if(*p == 0) + return m_null; + std::vector s; + while(*p) + s.insert(s.end(), *p++); + return named_subexpression(&*s.begin(), &*s.begin() + s.size()); + } + template + const_reference operator[](const std::basic_string& ns) const + { + BOOST_STATIC_ASSERT(sizeof(charT) <= sizeof(char_type)); + if(ns.empty()) + return m_null; + std::vector s; + for(unsigned i = 0; i < ns.size(); ++i) + s.insert(s.end(), ns[i]); + return named_subexpression(&*s.begin(), &*s.begin() + s.size()); + } + + const_reference prefix() const + { + if(m_is_singular) + raise_logic_error(); + return (*this)[-1]; + } + + const_reference suffix() const + { + if(m_is_singular) + raise_logic_error(); + return (*this)[-2]; + } + const_iterator begin() const + { + return (m_subs.size() > 2) ? (m_subs.begin() + 2) : m_subs.end(); + } + const_iterator end() const + { + return m_subs.end(); + } + // format: + template + OutputIterator format(OutputIterator out, + Functor fmt, + match_flag_type flags = format_default) const + { + if(m_is_singular) + raise_logic_error(); + typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type, OutputIterator>::type F; + F func(fmt); + return func(*this, out, flags); + } + template + string_type format(Functor fmt, match_flag_type flags = format_default) const + { + if(m_is_singular) + raise_logic_error(); + std::basic_string result; + BOOST_REGEX_DETAIL_NS::string_out_iterator > i(result); + + typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type, BOOST_REGEX_DETAIL_NS::string_out_iterator > >::type F; + F func(fmt); + + func(*this, i, flags); + return result; + } + // format with locale: + template + OutputIterator format(OutputIterator out, + Functor fmt, + match_flag_type flags, + const RegexT& re) const + { + if(m_is_singular) + raise_logic_error(); + typedef ::boost::regex_traits_wrapper traits_type; + typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type, OutputIterator, traits_type>::type F; + F func(fmt); + return func(*this, out, flags, re.get_traits()); + } + template + string_type format(Functor fmt, + match_flag_type flags, + const RegexT& re) const + { + if(m_is_singular) + raise_logic_error(); + typedef ::boost::regex_traits_wrapper traits_type; + std::basic_string result; + BOOST_REGEX_DETAIL_NS::string_out_iterator > i(result); + + typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type, BOOST_REGEX_DETAIL_NS::string_out_iterator >, traits_type >::type F; + F func(fmt); + + func(*this, i, flags, re.get_traits()); + return result; + } + + const_reference get_last_closed_paren()const + { + if(m_is_singular) + raise_logic_error(); + return m_last_closed_paren == 0 ? m_null : (*this)[m_last_closed_paren]; + } + + allocator_type get_allocator() const + { +#ifndef BOOST_NO_STD_ALLOCATOR + return m_subs.get_allocator(); +#else + return allocator_type(); +#endif + } + void swap(match_results& that) + { + std::swap(m_subs, that.m_subs); + std::swap(m_named_subs, that.m_named_subs); + std::swap(m_last_closed_paren, that.m_last_closed_paren); + if(m_is_singular) + { + if(!that.m_is_singular) + { + m_base = that.m_base; + m_null = that.m_null; + } + } + else if(that.m_is_singular) + { + that.m_base = m_base; + that.m_null = m_null; + } + else + { + std::swap(m_base, that.m_base); + std::swap(m_null, that.m_null); + } + std::swap(m_is_singular, that.m_is_singular); + } + bool operator==(const match_results& that)const + { + if(m_is_singular) + { + return that.m_is_singular; + } + else if(that.m_is_singular) + { + return false; + } + return (m_subs == that.m_subs) && (m_base == that.m_base) && (m_last_closed_paren == that.m_last_closed_paren); + } + bool operator!=(const match_results& that)const + { return !(*this == that); } + +#ifdef BOOST_REGEX_MATCH_EXTRA + typedef typename sub_match::capture_sequence_type capture_sequence_type; + + const capture_sequence_type& captures(int i)const + { + if(m_is_singular) + raise_logic_error(); + return (*this)[i].captures(); + } +#endif + + // + // private access functions: + void BOOST_REGEX_CALL set_second(BidiIterator i) + { + BOOST_REGEX_ASSERT(m_subs.size() > 2); + m_subs[2].second = i; + m_subs[2].matched = true; + m_subs[0].first = i; + m_subs[0].matched = (m_subs[0].first != m_subs[0].second); + m_null.first = i; + m_null.second = i; + m_null.matched = false; + m_is_singular = false; + } + + void BOOST_REGEX_CALL set_second(BidiIterator i, size_type pos, bool m = true, bool escape_k = false) + { + if(pos) + m_last_closed_paren = static_cast(pos); + pos += 2; + BOOST_REGEX_ASSERT(m_subs.size() > pos); + m_subs[pos].second = i; + m_subs[pos].matched = m; + if((pos == 2) && !escape_k) + { + m_subs[0].first = i; + m_subs[0].matched = (m_subs[0].first != m_subs[0].second); + m_null.first = i; + m_null.second = i; + m_null.matched = false; + m_is_singular = false; + } + } + void BOOST_REGEX_CALL set_size(size_type n, BidiIterator i, BidiIterator j) + { + value_type v(j); + size_type len = m_subs.size(); + if(len > n + 2) + { + m_subs.erase(m_subs.begin()+n+2, m_subs.end()); + std::fill(m_subs.begin(), m_subs.end(), v); + } + else + { + std::fill(m_subs.begin(), m_subs.end(), v); + if(n+2 != len) + m_subs.insert(m_subs.end(), n+2-len, v); + } + m_subs[1].first = i; + m_last_closed_paren = 0; + } + void BOOST_REGEX_CALL set_base(BidiIterator pos) + { + m_base = pos; + } + BidiIterator base()const + { + return m_base; + } + void BOOST_REGEX_CALL set_first(BidiIterator i) + { + BOOST_REGEX_ASSERT(m_subs.size() > 2); + // set up prefix: + m_subs[1].second = i; + m_subs[1].matched = (m_subs[1].first != i); + // set up $0: + m_subs[2].first = i; + // zero out everything else: + for(size_type n = 3; n < m_subs.size(); ++n) + { + m_subs[n].first = m_subs[n].second = m_subs[0].second; + m_subs[n].matched = false; + } + } + void BOOST_REGEX_CALL set_first(BidiIterator i, size_type pos, bool escape_k = false) + { + BOOST_REGEX_ASSERT(pos+2 < m_subs.size()); + if(pos || escape_k) + { + m_subs[pos+2].first = i; + if(escape_k) + { + m_subs[1].second = i; + m_subs[1].matched = (m_subs[1].first != m_subs[1].second); + } + } + else + set_first(i); + } + void BOOST_REGEX_CALL maybe_assign(const match_results& m); + + void BOOST_REGEX_CALL set_named_subs(boost::shared_ptr subs) + { + m_named_subs = subs; + } + +private: + // + // Error handler called when an uninitialized match_results is accessed: + // + static void raise_logic_error() + { + std::logic_error e("Attempt to access an uninitialized boost::match_results<> class."); + boost::throw_exception(e); + } + + + vector_type m_subs; // subexpressions + BidiIterator m_base; // where the search started from + sub_match m_null; // a null match + boost::shared_ptr m_named_subs; // Shared copy of named subs in the regex object + int m_last_closed_paren; // Last ) to be seen - used for formatting + bool m_is_singular; // True if our stored iterators are singular +}; + +template +void BOOST_REGEX_CALL match_results::maybe_assign(const match_results& m) +{ + if(m_is_singular) + { + *this = m; + return; + } + const_iterator p1, p2; + p1 = begin(); + p2 = m.begin(); + // + // Distances are measured from the start of *this* match, unless this isn't + // a valid match in which case we use the start of the whole sequence. Note that + // no subsequent match-candidate can ever be to the left of the first match found. + // This ensures that when we are using bidirectional iterators, that distances + // measured are as short as possible, and therefore as efficient as possible + // to compute. Finally note that we don't use the "matched" data member to test + // whether a sub-expression is a valid match, because partial matches set this + // to false for sub-expression 0. + // + BidiIterator l_end = this->suffix().second; + BidiIterator l_base = (p1->first == l_end) ? this->prefix().first : (*this)[0].first; + difference_type len1 = 0; + difference_type len2 = 0; + difference_type base1 = 0; + difference_type base2 = 0; + std::size_t i; + for(i = 0; i < size(); ++i, ++p1, ++p2) + { + // + // Leftmost takes priority over longest; handle special cases + // where distances need not be computed first (an optimisation + // for bidirectional iterators: ensure that we don't accidently + // compute the length of the whole sequence, as this can be really + // expensive). + // + if(p1->first == l_end) + { + if(p2->first != l_end) + { + // p2 must be better than p1, and no need to calculate + // actual distances: + base1 = 1; + base2 = 0; + break; + } + else + { + // *p1 and *p2 are either unmatched or match end-of sequence, + // either way no need to calculate distances: + if((p1->matched == false) && (p2->matched == true)) + break; + if((p1->matched == true) && (p2->matched == false)) + return; + continue; + } + } + else if(p2->first == l_end) + { + // p1 better than p2, and no need to calculate distances: + return; + } + base1 = ::boost::BOOST_REGEX_DETAIL_NS::distance(l_base, p1->first); + base2 = ::boost::BOOST_REGEX_DETAIL_NS::distance(l_base, p2->first); + BOOST_REGEX_ASSERT(base1 >= 0); + BOOST_REGEX_ASSERT(base2 >= 0); + if(base1 < base2) return; + if(base2 < base1) break; + + len1 = ::boost::BOOST_REGEX_DETAIL_NS::distance((BidiIterator)p1->first, (BidiIterator)p1->second); + len2 = ::boost::BOOST_REGEX_DETAIL_NS::distance((BidiIterator)p2->first, (BidiIterator)p2->second); + BOOST_REGEX_ASSERT(len1 >= 0); + BOOST_REGEX_ASSERT(len2 >= 0); + if((len1 != len2) || ((p1->matched == false) && (p2->matched == true))) + break; + if((p1->matched == true) && (p2->matched == false)) + return; + } + if(i == size()) + return; + if(base2 < base1) + *this = m; + else if((len2 > len1) || ((p1->matched == false) && (p2->matched == true)) ) + *this = m; +} + +template +void swap(match_results& a, match_results& b) +{ + a.swap(b); +} + +#ifndef BOOST_NO_STD_LOCALE +template +std::basic_ostream& + operator << (std::basic_ostream& os, + const match_results& s) +{ + return (os << s.str()); +} +#else +template +std::ostream& operator << (std::ostream& os, + const match_results& s) +{ + return (os << s.str()); +} +#endif + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif + + diff --git a/boost/regex/v4/mem_block_cache.hpp b/boost/regex/v4/mem_block_cache.hpp new file mode 100644 index 00000000..1996a512 --- /dev/null +++ b/boost/regex/v4/mem_block_cache.hpp @@ -0,0 +1,183 @@ + /* + * Copyright (c) 2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE mem_block_cache.hpp + * VERSION see + * DESCRIPTION: memory block cache used by the non-recursive matcher. + */ + +#ifndef BOOST_REGEX_V4_MEM_BLOCK_CACHE_HPP +#define BOOST_REGEX_V4_MEM_BLOCK_CACHE_HPP + +#include +#ifdef BOOST_HAS_THREADS +#include +#endif + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +#ifndef BOOST_NO_CXX11_HDR_ATOMIC + #include + #if ATOMIC_POINTER_LOCK_FREE == 2 + #define BOOST_REGEX_MEM_BLOCK_CACHE_LOCK_FREE + #define BOOST_REGEX_ATOMIC_POINTER std::atomic + #endif +#endif + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +#ifdef BOOST_REGEX_MEM_BLOCK_CACHE_LOCK_FREE /* lock free implementation */ +struct mem_block_cache +{ + std::atomic cache[BOOST_REGEX_MAX_CACHE_BLOCKS]; + + ~mem_block_cache() + { + for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) { + if (cache[i].load()) ::operator delete(cache[i].load()); + } + } + void* get() + { + for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) { + void* p = cache[i].load(); + if (p != NULL) { + if (cache[i].compare_exchange_strong(p, NULL)) return p; + } + } + return ::operator new(BOOST_REGEX_BLOCKSIZE); + } + void put(void* ptr) + { + for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) { + void* p = cache[i].load(); + if (p == NULL) { + if (cache[i].compare_exchange_strong(p, ptr)) return; + } + } + ::operator delete(ptr); + } + + static mem_block_cache& instance() + { + static mem_block_cache block_cache = { { {nullptr} } }; + return block_cache; + } +}; + + +#else /* lock-based implementation */ + + +struct mem_block_node +{ + mem_block_node* next; +}; + +struct mem_block_cache +{ + // this member has to be statically initialsed: + mem_block_node* next; + unsigned cached_blocks; +#ifdef BOOST_HAS_THREADS + boost::static_mutex mut; +#endif + + ~mem_block_cache() + { + while(next) + { + mem_block_node* old = next; + next = next->next; + ::operator delete(old); + } + } + void* get() + { +#ifdef BOOST_HAS_THREADS + boost::static_mutex::scoped_lock g(mut); +#endif + if(next) + { + mem_block_node* result = next; + next = next->next; + --cached_blocks; + return result; + } + return ::operator new(BOOST_REGEX_BLOCKSIZE); + } + void put(void* p) + { +#ifdef BOOST_HAS_THREADS + boost::static_mutex::scoped_lock g(mut); +#endif + if(cached_blocks >= BOOST_REGEX_MAX_CACHE_BLOCKS) + { + ::operator delete(p); + } + else + { + mem_block_node* old = static_cast(p); + old->next = next; + next = old; + ++cached_blocks; + } + } + static mem_block_cache& instance() + { +#ifdef BOOST_HAS_THREADS + static mem_block_cache block_cache = { 0, 0, BOOST_STATIC_MUTEX_INIT, }; +#else + static mem_block_cache block_cache = { 0, 0, }; +#endif + return block_cache; + } +}; +#endif + +#if BOOST_REGEX_MAX_CACHE_BLOCKS == 0 + +inline void* BOOST_REGEX_CALL get_mem_block() +{ + return ::operator new(BOOST_REGEX_BLOCKSIZE); +} + +inline void BOOST_REGEX_CALL put_mem_block(void* p) +{ + ::operator delete(p); +} + +#else + +inline void* BOOST_REGEX_CALL get_mem_block() +{ + return mem_block_cache::instance().get(); +} + +inline void BOOST_REGEX_CALL put_mem_block(void* p) +{ + mem_block_cache::instance().put(p); +} + +#endif +} +} // namespace boost + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif + diff --git a/boost/regex/v4/object_cache.hpp b/boost/regex/v4/object_cache.hpp new file mode 100644 index 00000000..98ba4c19 --- /dev/null +++ b/boost/regex/v4/object_cache.hpp @@ -0,0 +1,171 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE object_cache.hpp + * VERSION see + * DESCRIPTION: Implements a generic object cache. + */ + +#ifndef BOOST_REGEX_OBJECT_CACHE_HPP +#define BOOST_REGEX_OBJECT_CACHE_HPP + +#include +#include +#include +#include +#include +#include +#ifdef BOOST_HAS_THREADS +#include +#endif + +namespace boost{ + +template +class object_cache +{ +public: + typedef std::pair< ::boost::shared_ptr, Key const*> value_type; + typedef std::list list_type; + typedef typename list_type::iterator list_iterator; + typedef std::map map_type; + typedef typename map_type::iterator map_iterator; + typedef typename list_type::size_type size_type; + static boost::shared_ptr get(const Key& k, size_type l_max_cache_size); + +private: + static boost::shared_ptr do_get(const Key& k, size_type l_max_cache_size); + + struct data + { + list_type cont; + map_type index; + }; + + // Needed by compilers not implementing the resolution to DR45. For reference, + // see http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45. + friend struct data; +}; + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4702) +#endif +template +boost::shared_ptr object_cache::get(const Key& k, size_type l_max_cache_size) +{ +#ifdef BOOST_HAS_THREADS + static boost::static_mutex mut = BOOST_STATIC_MUTEX_INIT; + boost::static_mutex::scoped_lock l(mut); + if (l) + { + return do_get(k, l_max_cache_size); + } + // + // what do we do if the lock fails? + // for now just throw, but we should never really get here... + // + ::boost::throw_exception(std::runtime_error("Error in thread safety code: could not acquire a lock")); +#if defined(BOOST_NO_UNREACHABLE_RETURN_DETECTION) || defined(BOOST_NO_EXCEPTIONS) + return boost::shared_ptr(); +#endif +#else + return do_get(k, l_max_cache_size); +#endif +} +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +template +boost::shared_ptr object_cache::do_get(const Key& k, size_type l_max_cache_size) +{ + typedef typename object_cache::data object_data; + typedef typename map_type::size_type map_size_type; + static object_data s_data; + + // + // see if the object is already in the cache: + // + map_iterator mpos = s_data.index.find(k); + if(mpos != s_data.index.end()) + { + // + // Eureka! + // We have a cached item, bump it up the list and return it: + // + if(--(s_data.cont.end()) != mpos->second) + { + // splice out the item we want to move: + list_type temp; + temp.splice(temp.end(), s_data.cont, mpos->second); + // and now place it at the end of the list: + s_data.cont.splice(s_data.cont.end(), temp, temp.begin()); + BOOST_REGEX_ASSERT(*(s_data.cont.back().second) == k); + // update index with new position: + mpos->second = --(s_data.cont.end()); + BOOST_REGEX_ASSERT(&(mpos->first) == mpos->second->second); + BOOST_REGEX_ASSERT(&(mpos->first) == s_data.cont.back().second); + } + return s_data.cont.back().first; + } + // + // if we get here then the item is not in the cache, + // so create it: + // + boost::shared_ptr result(new Object(k)); + // + // Add it to the list, and index it: + // + s_data.cont.push_back(value_type(result, static_cast(0))); + s_data.index.insert(std::make_pair(k, --(s_data.cont.end()))); + s_data.cont.back().second = &(s_data.index.find(k)->first); + map_size_type s = s_data.index.size(); + BOOST_REGEX_ASSERT(s_data.index[k]->first.get() == result.get()); + BOOST_REGEX_ASSERT(&(s_data.index.find(k)->first) == s_data.cont.back().second); + BOOST_REGEX_ASSERT(s_data.index.find(k)->first == k); + if(s > l_max_cache_size) + { + // + // We have too many items in the list, so we need to start + // popping them off the back of the list, but only if they're + // being held uniquely by us: + // + list_iterator pos = s_data.cont.begin(); + list_iterator last = s_data.cont.end(); + while((pos != last) && (s > l_max_cache_size)) + { + if(pos->first.unique()) + { + list_iterator condemmed(pos); + ++pos; + // now remove the items from our containers, + // then order has to be as follows: + BOOST_REGEX_ASSERT(s_data.index.find(*(condemmed->second)) != s_data.index.end()); + s_data.index.erase(*(condemmed->second)); + s_data.cont.erase(condemmed); + --s; + } + else + ++pos; + } + BOOST_REGEX_ASSERT(s_data.index[k]->first.get() == result.get()); + BOOST_REGEX_ASSERT(&(s_data.index.find(k)->first) == s_data.cont.back().second); + BOOST_REGEX_ASSERT(s_data.index.find(k)->first == k); + } + return result; +} + +} + +#endif diff --git a/boost/regex/v4/pattern_except.hpp b/boost/regex/v4/pattern_except.hpp new file mode 100644 index 00000000..7aba564b --- /dev/null +++ b/boost/regex/v4/pattern_except.hpp @@ -0,0 +1,128 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE pattern_except.hpp + * VERSION see + * DESCRIPTION: Declares pattern-matching exception classes. + */ + +#ifndef BOOST_RE_V4_PAT_EXCEPT_HPP +#define BOOST_RE_V4_PAT_EXCEPT_HPP + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif + +#include +#include +#include +#include + +namespace boost{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable : 4275) +#if BOOST_MSVC >= 1800 +#pragma warning(disable : 26812) +#endif +#endif +class regex_error : public std::runtime_error +{ +public: + explicit regex_error(const std::string& s, regex_constants::error_type err = regex_constants::error_unknown, std::ptrdiff_t pos = 0) + : std::runtime_error(s) + , m_error_code(err) + , m_position(pos) + { + } + explicit regex_error(regex_constants::error_type err) + : std::runtime_error(::boost::BOOST_REGEX_DETAIL_NS::get_default_error_string(err)) + , m_error_code(err) + , m_position(0) + { + } + ~regex_error() BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE {} + regex_constants::error_type code()const + { return m_error_code; } + std::ptrdiff_t position()const + { return m_position; } + void raise()const + { +#ifndef BOOST_NO_EXCEPTIONS +#ifndef BOOST_REGEX_STANDALONE + ::boost::throw_exception(*this); +#else + throw* this; +#endif +#endif + } +private: + regex_constants::error_type m_error_code; + std::ptrdiff_t m_position; +}; + +typedef regex_error bad_pattern; +typedef regex_error bad_expression; + +namespace BOOST_REGEX_DETAIL_NS{ + +template +inline void raise_runtime_error(const E& ex) +{ +#ifndef BOOST_REGEX_STANDALONE + ::boost::throw_exception(ex); +#else + throw ex; +#endif +} + +template +void raise_error(const traits& t, regex_constants::error_type code) +{ + (void)t; // warning suppression + regex_error e(t.error_string(code), code, 0); + ::boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(e); +} + +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace boost + +#endif diff --git a/boost/regex/v4/perl_matcher.hpp b/boost/regex/v4/perl_matcher.hpp new file mode 100644 index 00000000..4bd7d114 --- /dev/null +++ b/boost/regex/v4/perl_matcher.hpp @@ -0,0 +1,645 @@ +/* + * + * Copyright (c) 2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + +#ifndef BOOST_REGEX_MATCHER_HPP +#define BOOST_REGEX_MATCHER_HPP + +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +# pragma warning(push) +#pragma warning(disable : 4251) +#if BOOST_MSVC < 1700 +# pragma warning(disable : 4231) +#endif +# if BOOST_MSVC < 1600 +# pragma warning(disable : 4660) +# endif +#if BOOST_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +// +// error checking API: +// +inline void BOOST_REGEX_CALL verify_options(boost::regex_constants::syntax_option_type, match_flag_type mf) +{ + // + // can't mix match_extra with POSIX matching rules: + // + if ((mf & match_extra) && (mf & match_posix)) + { + std::logic_error msg("Usage Error: Can't mix regular expression captures with POSIX matching rules"); + throw_exception(msg); + } +} +// +// function can_start: +// +template +inline bool can_start(charT c, const unsigned char* map, unsigned char mask) +{ + return ((c < static_cast(0)) ? true : ((c >= static_cast(1 << CHAR_BIT)) ? true : map[c] & mask)); +} +inline bool can_start(char c, const unsigned char* map, unsigned char mask) +{ + return map[(unsigned char)c] & mask; +} +inline bool can_start(signed char c, const unsigned char* map, unsigned char mask) +{ + return map[(unsigned char)c] & mask; +} +inline bool can_start(unsigned char c, const unsigned char* map, unsigned char mask) +{ + return map[c] & mask; +} +inline bool can_start(unsigned short c, const unsigned char* map, unsigned char mask) +{ + return ((c >= (1 << CHAR_BIT)) ? true : map[c] & mask); +} +#if !defined(__hpux) && !defined(__WINSCW__)// WCHAR_MIN not usable in pp-directives. +#if defined(WCHAR_MIN) && (WCHAR_MIN == 0) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) +inline bool can_start(wchar_t c, const unsigned char* map, unsigned char mask) +{ + return ((c >= static_cast(1u << CHAR_BIT)) ? true : map[c] & mask); +} +#endif +#endif +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) +inline bool can_start(unsigned int c, const unsigned char* map, unsigned char mask) +{ + return (((c >= static_cast(1u << CHAR_BIT)) ? true : map[c] & mask)); +} +#endif + + +// +// Unfortunately Rogue Waves standard library appears to have a bug +// in std::basic_string::compare that results in erroneous answers +// in some cases (tested with Borland C++ 5.1, Rogue Wave lib version +// 0x020101) the test case was: +// {39135,0} < {0xff,0} +// which succeeds when it should not. +// +#ifndef _RWSTD_VER +template +inline int string_compare(const std::basic_string& s, const C* p) +{ + if(0 == *p) + { + if(s.empty() || ((s.size() == 1) && (s[0] == 0))) + return 0; + } + return s.compare(p); +} +#else +template +inline int string_compare(const std::basic_string& s, const C* p) +{ + if(0 == *p) + { + if(s.empty() || ((s.size() == 1) && (s[0] == 0))) + return 0; + } + return s.compare(p); +} +inline int string_compare(const std::string& s, const char* p) +{ return std::strcmp(s.c_str(), p); } +# ifndef BOOST_NO_WREGEX +inline int string_compare(const std::wstring& s, const wchar_t* p) +{ return std::wcscmp(s.c_str(), p); } +#endif +#endif +template +inline int string_compare(const Seq& s, const C* p) +{ + std::size_t i = 0; + while((i < s.size()) && (p[i] == s[i])) + { + ++i; + } + return (i == s.size()) ? -(int)p[i] : (int)s[i] - (int)p[i]; +} +# define STR_COMP(s,p) string_compare(s,p) + +template +inline const charT* re_skip_past_null(const charT* p) +{ + while (*p != static_cast(0)) ++p; + return ++p; +} + +template +iterator BOOST_REGEX_CALL re_is_set_member(iterator next, + iterator last, + const re_set_long* set_, + const regex_data& e, bool icase) +{ + const charT* p = reinterpret_cast(set_+1); + iterator ptr; + unsigned int i; + //bool icase = e.m_flags & regex_constants::icase; + + if(next == last) return next; + + typedef typename traits_type::string_type traits_string_type; + const ::boost::regex_traits_wrapper& traits_inst = *(e.m_ptraits); + + // dwa 9/13/00 suppress incorrect MSVC warning - it claims this is never + // referenced + (void)traits_inst; + + // try and match a single character, could be a multi-character + // collating element... + for(i = 0; i < set_->csingles; ++i) + { + ptr = next; + if(*p == static_cast(0)) + { + // treat null string as special case: + if(traits_inst.translate(*ptr, icase)) + { + ++p; + continue; + } + return set_->isnot ? next : (ptr == next) ? ++next : ptr; + } + else + { + while(*p && (ptr != last)) + { + if(traits_inst.translate(*ptr, icase) != *p) + break; + ++p; + ++ptr; + } + + if(*p == static_cast(0)) // if null we've matched + return set_->isnot ? next : (ptr == next) ? ++next : ptr; + + p = re_skip_past_null(p); // skip null + } + } + + charT col = traits_inst.translate(*next, icase); + + + if(set_->cranges || set_->cequivalents) + { + traits_string_type s1; + // + // try and match a range, NB only a single character can match + if(set_->cranges) + { + if((e.m_flags & regex_constants::collate) == 0) + s1.assign(1, col); + else + { + charT a[2] = { col, charT(0), }; + s1 = traits_inst.transform(a, a + 1); + } + for(i = 0; i < set_->cranges; ++i) + { + if(STR_COMP(s1, p) >= 0) + { + do{ ++p; }while(*p); + ++p; + if(STR_COMP(s1, p) <= 0) + return set_->isnot ? next : ++next; + } + else + { + // skip first string + do{ ++p; }while(*p); + ++p; + } + // skip second string + do{ ++p; }while(*p); + ++p; + } + } + // + // try and match an equivalence class, NB only a single character can match + if(set_->cequivalents) + { + charT a[2] = { col, charT(0), }; + s1 = traits_inst.transform_primary(a, a +1); + for(i = 0; i < set_->cequivalents; ++i) + { + if(STR_COMP(s1, p) == 0) + return set_->isnot ? next : ++next; + // skip string + do{ ++p; }while(*p); + ++p; + } + } + } + if(traits_inst.isctype(col, set_->cclasses) == true) + return set_->isnot ? next : ++next; + if((set_->cnclasses != 0) && (traits_inst.isctype(col, set_->cnclasses) == false)) + return set_->isnot ? next : ++next; + return set_->isnot ? ++next : next; +} + +template +class repeater_count +{ + repeater_count** stack; + repeater_count* next; + int state_id; + std::size_t count; // the number of iterations so far + BidiIterator start_pos; // where the last repeat started + + repeater_count* unwind_until(int n, repeater_count* p, int current_recursion_id) + { + while(p && (p->state_id != n)) + { + if(-2 - current_recursion_id == p->state_id) + return 0; + p = p->next; + if(p && (p->state_id < 0)) + { + p = unwind_until(p->state_id, p, current_recursion_id); + if(!p) + return p; + p = p->next; + } + } + return p; + } +public: + repeater_count(repeater_count** s) : stack(s), next(0), state_id(-1), count(0), start_pos() {} + + repeater_count(int i, repeater_count** s, BidiIterator start, int current_recursion_id) + : start_pos(start) + { + state_id = i; + stack = s; + next = *stack; + *stack = this; + if((state_id > next->state_id) && (next->state_id >= 0)) + count = 0; + else + { + repeater_count* p = next; + p = unwind_until(state_id, p, current_recursion_id); + if(p) + { + count = p->count; + start_pos = p->start_pos; + } + else + count = 0; + } + } + ~repeater_count() + { + if(next) + *stack = next; + } + std::size_t get_count() { return count; } + int get_id() { return state_id; } + std::size_t operator++() { return ++count; } + bool check_null_repeat(const BidiIterator& pos, std::size_t max) + { + // this is called when we are about to start a new repeat, + // if the last one was NULL move our count to max, + // otherwise save the current position. + bool result = (count == 0) ? false : (pos == start_pos); + if(result) + count = max; + else + start_pos = pos; + return result; + } +}; + +struct saved_state; + +enum saved_state_type +{ + saved_type_end = 0, + saved_type_paren = 1, + saved_type_recurse = 2, + saved_type_assertion = 3, + saved_state_alt = 4, + saved_state_repeater_count = 5, + saved_state_extra_block = 6, + saved_state_greedy_single_repeat = 7, + saved_state_rep_slow_dot = 8, + saved_state_rep_fast_dot = 9, + saved_state_rep_char = 10, + saved_state_rep_short_set = 11, + saved_state_rep_long_set = 12, + saved_state_non_greedy_long_repeat = 13, + saved_state_count = 14 +}; + +#ifdef BOOST_MSVC +# pragma warning(push) +#if BOOST_MSVC >= 1800 +#pragma warning(disable:26495) +#endif +#endif +template +struct recursion_info +{ + typedef typename Results::value_type value_type; + typedef typename value_type::iterator iterator; + int idx; + const re_syntax_base* preturn_address; + Results results; + repeater_count* repeater_stack; + iterator location_of_start; +}; +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +template +class perl_matcher +{ +public: + typedef typename traits::char_type char_type; + typedef perl_matcher self_type; + typedef bool (self_type::*matcher_proc_type)(); + typedef std::size_t traits_size_type; + typedef typename is_byte::width_type width_type; + typedef typename regex_iterator_traits::difference_type difference_type; + typedef match_results results_type; + + perl_matcher(BidiIterator first, BidiIterator end, + match_results& what, + const basic_regex& e, + match_flag_type f, + BidiIterator l_base) + : m_result(what), base(first), last(end), + position(first), backstop(l_base), re(e), traits_inst(e.get_traits()), + m_independent(false), next_count(&rep_obj), rep_obj(&next_count) +#ifdef BOOST_REGEX_NON_RECURSIVE + , m_recursions(0) +#endif + { + construct_init(e, f); + } + + bool match(); + bool find(); + + void setf(match_flag_type f) + { m_match_flags |= f; } + void unsetf(match_flag_type f) + { m_match_flags &= ~f; } + +private: + void construct_init(const basic_regex& e, match_flag_type f); + + bool find_imp(); + bool match_imp(); +#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD + typedef bool (perl_matcher::*protected_proc_type)(); + bool protected_call(protected_proc_type); +#endif + void estimate_max_state_count(std::random_access_iterator_tag*); + void estimate_max_state_count(void*); + bool match_prefix(); + bool match_all_states(); + + // match procs, stored in s_match_vtable: + bool match_startmark(); + bool match_endmark(); + bool match_literal(); + bool match_start_line(); + bool match_end_line(); + bool match_wild(); + bool match_match(); + bool match_word_boundary(); + bool match_within_word(); + bool match_word_start(); + bool match_word_end(); + bool match_buffer_start(); + bool match_buffer_end(); + bool match_backref(); + bool match_long_set(); + bool match_set(); + bool match_jump(); + bool match_alt(); + bool match_rep(); + bool match_combining(); + bool match_soft_buffer_end(); + bool match_restart_continue(); + bool match_long_set_repeat(); + bool match_set_repeat(); + bool match_char_repeat(); + bool match_dot_repeat_fast(); + bool match_dot_repeat_slow(); + bool match_dot_repeat_dispatch() + { + return ::boost::is_random_access_iterator::value ? match_dot_repeat_fast() : match_dot_repeat_slow(); + } + bool match_backstep(); + bool match_assert_backref(); + bool match_toggle_case(); +#ifdef BOOST_REGEX_RECURSIVE + bool backtrack_till_match(std::size_t count); +#endif + bool match_recursion(); + bool match_fail(); + bool match_accept(); + bool match_commit(); + bool match_then(); + bool skip_until_paren(int index, bool match = true); + + // find procs stored in s_find_vtable: + bool find_restart_any(); + bool find_restart_word(); + bool find_restart_line(); + bool find_restart_buf(); + bool find_restart_lit(); + +private: + // final result structure to be filled in: + match_results& m_result; + // temporary result for POSIX matches: + scoped_ptr > m_temp_match; + // pointer to actual result structure to fill in: + match_results* m_presult; + // start of sequence being searched: + BidiIterator base; + // end of sequence being searched: + BidiIterator last; + // current character being examined: + BidiIterator position; + // where to restart next search after failed match attempt: + BidiIterator restart; + // where the current search started from, acts as base for $` during grep: + BidiIterator search_base; + // how far we can go back when matching lookbehind: + BidiIterator backstop; + // the expression being examined: + const basic_regex& re; + // the expression's traits class: + const ::boost::regex_traits_wrapper& traits_inst; + // the next state in the machine being matched: + const re_syntax_base* pstate; + // matching flags in use: + match_flag_type m_match_flags; + // how many states we have examined so far: + std::ptrdiff_t state_count; + // max number of states to examine before giving up: + std::ptrdiff_t max_state_count; + // whether we should ignore case or not: + bool icase; + // set to true when (position == last), indicates that we may have a partial match: + bool m_has_partial_match; + // set to true whenever we get a match: + bool m_has_found_match; + // set to true whenever we're inside an independent sub-expression: + bool m_independent; + // the current repeat being examined: + repeater_count* next_count; + // the first repeat being examined (top of linked list): + repeater_count rep_obj; + // the mask to pass when matching word boundaries: + typename traits::char_class_type m_word_mask; + // the bitmask to use when determining whether a match_any matches a newline or not: + unsigned char match_any_mask; + // recursion information: + std::vector > recursion_stack; +#ifdef BOOST_REGEX_RECURSIVE + // Set to false by a (*COMMIT): + bool m_can_backtrack; + bool m_have_accept; + bool m_have_then; +#endif +#ifdef BOOST_REGEX_NON_RECURSIVE + // + // additional members for non-recursive version: + // + typedef bool (self_type::*unwind_proc_type)(bool); + + void extend_stack(); + bool unwind(bool); + bool unwind_end(bool); + bool unwind_paren(bool); + bool unwind_recursion_stopper(bool); + bool unwind_assertion(bool); + bool unwind_alt(bool); + bool unwind_repeater_counter(bool); + bool unwind_extra_block(bool); + bool unwind_greedy_single_repeat(bool); + bool unwind_slow_dot_repeat(bool); + bool unwind_fast_dot_repeat(bool); + bool unwind_char_repeat(bool); + bool unwind_short_set_repeat(bool); + bool unwind_long_set_repeat(bool); + bool unwind_non_greedy_repeat(bool); + bool unwind_recursion(bool); + bool unwind_recursion_pop(bool); + bool unwind_commit(bool); + bool unwind_then(bool); + bool unwind_case(bool); + void destroy_single_repeat(); + void push_matched_paren(int index, const sub_match& sub); + void push_recursion_stopper(); + void push_assertion(const re_syntax_base* ps, bool positive); + void push_alt(const re_syntax_base* ps); + void push_repeater_count(int i, repeater_count** s); + void push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id); + void push_non_greedy_repeat(const re_syntax_base* ps); + void push_recursion(int idx, const re_syntax_base* p, results_type* presults, results_type* presults2); + void push_recursion_pop(); + void push_case_change(bool); + + // pointer to base of stack: + saved_state* m_stack_base; + // pointer to current stack position: + saved_state* m_backup_state; + // how many memory blocks have we used up?: + unsigned used_block_count; + // determines what value to return when unwinding from recursion, + // allows for mixed recursive/non-recursive algorithm: + bool m_recursive_result; + // We have unwound to a lookahead/lookbehind, used by COMMIT/PRUNE/SKIP: + bool m_unwound_lookahead; + // We have unwound to an alternative, used by THEN: + bool m_unwound_alt; + // We are unwinding a commit - used by independent subs to determine whether to stop there or carry on unwinding: + //bool m_unwind_commit; + // Recursion limit: + unsigned m_recursions; +#endif + +#ifdef BOOST_MSVC +# pragma warning(push) +#if BOOST_MSVC >= 1800 +#pragma warning(disable:26495) +#endif +#endif + // these operations aren't allowed, so are declared private, + // bodies are provided to keep explicit-instantiation requests happy: + perl_matcher& operator=(const perl_matcher&) + { + return *this; + } + perl_matcher(const perl_matcher& that) + : m_result(that.m_result), re(that.re), traits_inst(that.traits_inst), rep_obj(0) {} +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif +}; + +} // namespace BOOST_REGEX_DETAIL_NS + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace boost + +// +// include the implementation of perl_matcher: +// +#ifdef BOOST_REGEX_RECURSIVE +#include +#else +#include +#endif +// this one has to be last: +#include + +#endif diff --git a/boost/regex/v4/perl_matcher_common.hpp b/boost/regex/v4/perl_matcher_common.hpp new file mode 100644 index 00000000..7cf0574b --- /dev/null +++ b/boost/regex/v4/perl_matcher_common.hpp @@ -0,0 +1,1030 @@ +/* + * + * Copyright (c) 2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE perl_matcher_common.cpp + * VERSION see + * DESCRIPTION: Definitions of perl_matcher member functions that are + * common to both the recursive and non-recursive versions. + */ + +#ifndef BOOST_REGEX_V4_PERL_MATCHER_COMMON_HPP +#define BOOST_REGEX_V4_PERL_MATCHER_COMMON_HPP + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#if BOOST_MSVC >= 1800 +#pragma warning(disable: 26812) +#endif +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef BOOST_BORLANDC +# pragma option push -w-8008 -w-8066 +#endif +#ifdef BOOST_MSVC +# pragma warning(push) +#if BOOST_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +#ifdef BOOST_MSVC +# pragma warning(push) +#pragma warning(disable:26812) +#endif + template +void perl_matcher::construct_init(const basic_regex& e, match_flag_type f) +{ + typedef typename regex_iterator_traits::iterator_category category; + typedef typename basic_regex::flag_type expression_flag_type; + + if(e.empty()) + { + // precondition failure: e is not a valid regex. + std::invalid_argument ex("Invalid regular expression object"); + boost::throw_exception(ex); + } + pstate = 0; + m_match_flags = f; + estimate_max_state_count(static_cast(0)); + expression_flag_type re_f = re.flags(); + icase = re_f & regex_constants::icase; + if(!(m_match_flags & (match_perl|match_posix))) + { + if((re_f & (regbase::main_option_type|regbase::no_perl_ex)) == 0) + m_match_flags |= match_perl; + else if((re_f & (regbase::main_option_type|regbase::emacs_ex)) == (regbase::basic_syntax_group|regbase::emacs_ex)) + m_match_flags |= match_perl; + else if((re_f & (regbase::main_option_type|regbase::literal)) == (regbase::literal)) + m_match_flags |= match_perl; + else + m_match_flags |= match_posix; + } + if(m_match_flags & match_posix) + { + m_temp_match.reset(new match_results()); + m_presult = m_temp_match.get(); + } + else + m_presult = &m_result; +#ifdef BOOST_REGEX_NON_RECURSIVE + m_stack_base = 0; + m_backup_state = 0; +#elif defined(BOOST_REGEX_RECURSIVE) + m_can_backtrack = true; + m_have_accept = false; +#endif + // find the value to use for matching word boundaries: + m_word_mask = re.get_data().m_word_mask; + // find bitmask to use for matching '.': + match_any_mask = static_cast((f & match_not_dot_newline) ? BOOST_REGEX_DETAIL_NS::test_not_newline : BOOST_REGEX_DETAIL_NS::test_newline); + // Disable match_any if requested in the state machine: + if(e.get_data().m_disable_match_any) + m_match_flags &= regex_constants::match_not_any; +} +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +template +void perl_matcher::estimate_max_state_count(std::random_access_iterator_tag*) +{ + // + // How many states should we allow our machine to visit before giving up? + // This is a heuristic: it takes the greater of O(N^2) and O(NS^2) + // where N is the length of the string, and S is the number of states + // in the machine. It's tempting to up this to O(N^2S) or even O(N^2S^2) + // but these take unreasonably amounts of time to bale out in pathological + // cases. + // + // Calculate NS^2 first: + // + static const std::ptrdiff_t k = 100000; + std::ptrdiff_t dist = boost::BOOST_REGEX_DETAIL_NS::distance(base, last); + if(dist == 0) + dist = 1; + std::ptrdiff_t states = re.size(); + if(states == 0) + states = 1; + if ((std::numeric_limits::max)() / states < states) + { + max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits::max)() - 2); + return; + } + states *= states; + if((std::numeric_limits::max)() / dist < states) + { + max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits::max)() - 2); + return; + } + states *= dist; + if((std::numeric_limits::max)() - k < states) + { + max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits::max)() - 2); + return; + } + states += k; + + max_state_count = states; + + // + // Now calculate N^2: + // + states = dist; + if((std::numeric_limits::max)() / dist < states) + { + max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits::max)() - 2); + return; + } + states *= dist; + if((std::numeric_limits::max)() - k < states) + { + max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits::max)() - 2); + return; + } + states += k; + // + // N^2 can be a very large number indeed, to prevent things getting out + // of control, cap the max states: + // + if(states > BOOST_REGEX_MAX_STATE_COUNT) + states = BOOST_REGEX_MAX_STATE_COUNT; + // + // If (the possibly capped) N^2 is larger than our first estimate, + // use this instead: + // + if(states > max_state_count) + max_state_count = states; +} + +template +inline void perl_matcher::estimate_max_state_count(void*) +{ + // we don't know how long the sequence is: + max_state_count = BOOST_REGEX_MAX_STATE_COUNT; +} + +#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD +template +inline bool perl_matcher::protected_call( + protected_proc_type proc) +{ + ::boost::BOOST_REGEX_DETAIL_NS::concrete_protected_call + > + obj(this, proc); + return obj.execute(); + +} +#endif + +template +inline bool perl_matcher::match() +{ +#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD + return protected_call(&perl_matcher::match_imp); +#else + return match_imp(); +#endif +} + +template +bool perl_matcher::match_imp() +{ + // initialise our stack if we are non-recursive: +#ifdef BOOST_REGEX_NON_RECURSIVE + save_state_init init(&m_stack_base, &m_backup_state); + used_block_count = BOOST_REGEX_MAX_BLOCKS; +#if !defined(BOOST_NO_EXCEPTIONS) + try{ +#endif +#endif + + // reset our state machine: + position = base; + search_base = base; + state_count = 0; + m_match_flags |= regex_constants::match_all; + m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast(1u + re.mark_count()), search_base, last); + m_presult->set_base(base); + m_presult->set_named_subs(this->re.get_named_subs()); + if(m_match_flags & match_posix) + m_result = *m_presult; + verify_options(re.flags(), m_match_flags); + if(0 == match_prefix()) + return false; + return (m_result[0].second == last) && (m_result[0].first == base); + +#if defined(BOOST_REGEX_NON_RECURSIVE) && !defined(BOOST_NO_EXCEPTIONS) + } + catch(...) + { + // unwind all pushed states, apart from anything else this + // ensures that all the states are correctly destructed + // not just the memory freed. + while(unwind(true)){} + throw; + } +#endif +} + +template +inline bool perl_matcher::find() +{ +#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD + return protected_call(&perl_matcher::find_imp); +#else + return find_imp(); +#endif +} + +template +bool perl_matcher::find_imp() +{ + static matcher_proc_type const s_find_vtable[7] = + { + &perl_matcher::find_restart_any, + &perl_matcher::find_restart_word, + &perl_matcher::find_restart_line, + &perl_matcher::find_restart_buf, + &perl_matcher::match_prefix, + &perl_matcher::find_restart_lit, + &perl_matcher::find_restart_lit, + }; + + // initialise our stack if we are non-recursive: +#ifdef BOOST_REGEX_NON_RECURSIVE + save_state_init init(&m_stack_base, &m_backup_state); + used_block_count = BOOST_REGEX_MAX_BLOCKS; +#if !defined(BOOST_NO_EXCEPTIONS) + try{ +#endif +#endif + + state_count = 0; + if((m_match_flags & regex_constants::match_init) == 0) + { + // reset our state machine: + search_base = position = base; + pstate = re.get_first_state(); + m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast(1u + re.mark_count()), base, last); + m_presult->set_base(base); + m_presult->set_named_subs(this->re.get_named_subs()); + m_match_flags |= regex_constants::match_init; + } + else + { + // start again: + search_base = position = m_result[0].second; + // If last match was null and match_not_null was not set then increment + // our start position, otherwise we go into an infinite loop: + if(((m_match_flags & match_not_null) == 0) && (m_result.length() == 0)) + { + if(position == last) + return false; + else + ++position; + } + // reset $` start: + m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast(1u + re.mark_count()), search_base, last); + //if((base != search_base) && (base == backstop)) + // m_match_flags |= match_prev_avail; + } + if(m_match_flags & match_posix) + { + m_result.set_size(static_cast(1u + re.mark_count()), base, last); + m_result.set_base(base); + } + + verify_options(re.flags(), m_match_flags); + // find out what kind of expression we have: + unsigned type = (m_match_flags & match_continuous) ? + static_cast(regbase::restart_continue) + : static_cast(re.get_restart_type()); + + // call the appropriate search routine: + matcher_proc_type proc = s_find_vtable[type]; + return (this->*proc)(); + +#if defined(BOOST_REGEX_NON_RECURSIVE) && !defined(BOOST_NO_EXCEPTIONS) + } + catch(...) + { + // unwind all pushed states, apart from anything else this + // ensures that all the states are correctly destructed + // not just the memory freed. + while(unwind(true)){} + throw; + } +#endif +} + +template +bool perl_matcher::match_prefix() +{ + m_has_partial_match = false; + m_has_found_match = false; + pstate = re.get_first_state(); + m_presult->set_first(position); + restart = position; + match_all_states(); + if(!m_has_found_match && m_has_partial_match && (m_match_flags & match_partial)) + { + m_has_found_match = true; + m_presult->set_second(last, 0, false); + position = last; + if((m_match_flags & match_posix) == match_posix) + { + m_result.maybe_assign(*m_presult); + } + } +#ifdef BOOST_REGEX_MATCH_EXTRA + if(m_has_found_match && (match_extra & m_match_flags)) + { + // + // we have a match, reverse the capture information: + // + for(unsigned i = 0; i < m_presult->size(); ++i) + { + typename sub_match::capture_sequence_type & seq = ((*m_presult)[i]).get_captures(); + std::reverse(seq.begin(), seq.end()); + } + } +#endif + if(!m_has_found_match) + position = restart; // reset search postion +#ifdef BOOST_REGEX_RECURSIVE + m_can_backtrack = true; // reset for further searches +#endif + return m_has_found_match; +} + +template +bool perl_matcher::match_literal() +{ + unsigned int len = static_cast(pstate)->length; + const char_type* what = reinterpret_cast(static_cast(pstate) + 1); + // + // compare string with what we stored in + // our records: + for(unsigned int i = 0; i < len; ++i, ++position) + { + if((position == last) || (traits_inst.translate(*position, icase) != what[i])) + return false; + } + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_start_line() +{ + if(position == backstop) + { + if((m_match_flags & match_prev_avail) == 0) + { + if((m_match_flags & match_not_bol) == 0) + { + pstate = pstate->next.p; + return true; + } + return false; + } + } + else if(m_match_flags & match_single_line) + return false; + + // check the previous value character: + BidiIterator t(position); + --t; + if(position != last) + { + if(is_separator(*t) && !((*t == static_cast('\r')) && (*position == static_cast('\n'))) ) + { + pstate = pstate->next.p; + return true; + } + } + else if(is_separator(*t)) + { + pstate = pstate->next.p; + return true; + } + return false; +} + +template +bool perl_matcher::match_end_line() +{ + if(position != last) + { + if(m_match_flags & match_single_line) + return false; + // we're not yet at the end so *first is always valid: + if(is_separator(*position)) + { + if((position != backstop) || (m_match_flags & match_prev_avail)) + { + // check that we're not in the middle of \r\n sequence + BidiIterator t(position); + --t; + if((*t == static_cast('\r')) && (*position == static_cast('\n'))) + { + return false; + } + } + pstate = pstate->next.p; + return true; + } + } + else if((m_match_flags & match_not_eol) == 0) + { + pstate = pstate->next.p; + return true; + } + return false; +} + +template +bool perl_matcher::match_wild() +{ + if(position == last) + return false; + if(is_separator(*position) && ((match_any_mask & static_cast(pstate)->mask) == 0)) + return false; + if((*position == char_type(0)) && (m_match_flags & match_not_dot_null)) + return false; + pstate = pstate->next.p; + ++position; + return true; +} + +template +bool perl_matcher::match_word_boundary() +{ + bool b; // indcates whether next character is a word character + if(position != last) + { + // prev and this character must be opposites: + b = traits_inst.isctype(*position, m_word_mask); + } + else + { + if (m_match_flags & match_not_eow) + return false; + b = false; + } + if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) + { + if(m_match_flags & match_not_bow) + return false; + else + b ^= false; + } + else + { + --position; + b ^= traits_inst.isctype(*position, m_word_mask); + ++position; + } + if(b) + { + pstate = pstate->next.p; + return true; + } + return false; // no match if we get to here... +} + +template +bool perl_matcher::match_within_word() +{ + if(position == last) + return false; + // both prev and this character must be m_word_mask: + bool prev = traits_inst.isctype(*position, m_word_mask); + { + bool b; + if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) + return false; + else + { + --position; + b = traits_inst.isctype(*position, m_word_mask); + ++position; + } + if(b == prev) + { + pstate = pstate->next.p; + return true; + } + } + return false; +} + +template +bool perl_matcher::match_word_start() +{ + if(position == last) + return false; // can't be starting a word if we're already at the end of input + if(!traits_inst.isctype(*position, m_word_mask)) + return false; // next character isn't a word character + if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) + { + if(m_match_flags & match_not_bow) + return false; // no previous input + } + else + { + // otherwise inside buffer: + BidiIterator t(position); + --t; + if(traits_inst.isctype(*t, m_word_mask)) + return false; // previous character not non-word + } + // OK we have a match: + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_word_end() +{ + if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) + return false; // start of buffer can't be end of word + BidiIterator t(position); + --t; + if(traits_inst.isctype(*t, m_word_mask) == false) + return false; // previous character wasn't a word character + + if(position == last) + { + if(m_match_flags & match_not_eow) + return false; // end of buffer but not end of word + } + else + { + // otherwise inside buffer: + if(traits_inst.isctype(*position, m_word_mask)) + return false; // next character is a word character + } + pstate = pstate->next.p; + return true; // if we fall through to here then we've succeeded +} + +template +bool perl_matcher::match_buffer_start() +{ + if((position != backstop) || (m_match_flags & match_not_bob)) + return false; + // OK match: + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_buffer_end() +{ + if((position != last) || (m_match_flags & match_not_eob)) + return false; + // OK match: + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_backref() +{ + // + // Compare with what we previously matched. + // Note that this succeeds if the backref did not partisipate + // in the match, this is in line with ECMAScript, but not Perl + // or PCRE. + // + int index = static_cast(pstate)->index; + if(index >= hash_value_mask) + { + named_subexpressions::range_type r = re.get_data().equal_range(index); + BOOST_REGEX_ASSERT(r.first != r.second); + do + { + index = r.first->index; + ++r.first; + }while((r.first != r.second) && ((*m_presult)[index].matched != true)); + } + + if((m_match_flags & match_perl) && !(*m_presult)[index].matched) + return false; + + BidiIterator i = (*m_presult)[index].first; + BidiIterator j = (*m_presult)[index].second; + while(i != j) + { + if((position == last) || (traits_inst.translate(*position, icase) != traits_inst.translate(*i, icase))) + return false; + ++i; + ++position; + } + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_long_set() +{ + typedef typename traits::char_class_type char_class_type; + // let the traits class do the work: + if(position == last) + return false; + BidiIterator t = re_is_set_member(position, last, static_cast*>(pstate), re.get_data(), icase); + if(t != position) + { + pstate = pstate->next.p; + position = t; + return true; + } + return false; +} + +template +bool perl_matcher::match_set() +{ + if(position == last) + return false; + if(static_cast(pstate)->_map[static_cast(traits_inst.translate(*position, icase))]) + { + pstate = pstate->next.p; + ++position; + return true; + } + return false; +} + +template +bool perl_matcher::match_jump() +{ + pstate = static_cast(pstate)->alt.p; + return true; +} + +template +bool perl_matcher::match_combining() +{ + if(position == last) + return false; + if(is_combining(traits_inst.translate(*position, icase))) + return false; + ++position; + while((position != last) && is_combining(traits_inst.translate(*position, icase))) + ++position; + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_soft_buffer_end() +{ + if(m_match_flags & match_not_eob) + return false; + BidiIterator p(position); + while((p != last) && is_separator(traits_inst.translate(*p, icase)))++p; + if(p != last) + return false; + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_restart_continue() +{ + if(position == search_base) + { + pstate = pstate->next.p; + return true; + } + return false; +} + +template +bool perl_matcher::match_backstep() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + if( ::boost::is_random_access_iterator::value) + { + std::ptrdiff_t maxlen = ::boost::BOOST_REGEX_DETAIL_NS::distance(backstop, position); + if(maxlen < static_cast(pstate)->index) + return false; + std::advance(position, -static_cast(pstate)->index); + } + else + { + int c = static_cast(pstate)->index; + while(c--) + { + if(position == backstop) + return false; + --position; + } + } + pstate = pstate->next.p; + return true; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +inline bool perl_matcher::match_assert_backref() +{ + // return true if marked sub-expression N has been matched: + int index = static_cast(pstate)->index; + bool result = false; + if(index == 9999) + { + // Magic value for a (DEFINE) block: + return false; + } + else if(index > 0) + { + // Have we matched subexpression "index"? + // Check if index is a hash value: + if(index >= hash_value_mask) + { + named_subexpressions::range_type r = re.get_data().equal_range(index); + while(r.first != r.second) + { + if((*m_presult)[r.first->index].matched) + { + result = true; + break; + } + ++r.first; + } + } + else + { + result = (*m_presult)[index].matched; + } + pstate = pstate->next.p; + } + else + { + // Have we recursed into subexpression "index"? + // If index == 0 then check for any recursion at all, otherwise for recursion to -index-1. + int idx = -(index+1); + if(idx >= hash_value_mask) + { + named_subexpressions::range_type r = re.get_data().equal_range(idx); + int stack_index = recursion_stack.empty() ? -1 : recursion_stack.back().idx; + while(r.first != r.second) + { + result |= (stack_index == r.first->index); + if(result)break; + ++r.first; + } + } + else + { + result = !recursion_stack.empty() && ((recursion_stack.back().idx == idx) || (index == 0)); + } + pstate = pstate->next.p; + } + return result; +} + +template +bool perl_matcher::match_fail() +{ + // Just force a backtrack: + return false; +} + +template +bool perl_matcher::match_accept() +{ + if(!recursion_stack.empty()) + { + return skip_until_paren(recursion_stack.back().idx); + } + else + { + return skip_until_paren(INT_MAX); + } +} + +template +bool perl_matcher::find_restart_any() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + const unsigned char* _map = re.get_map(); + while(true) + { + // skip everything we can't match: + while((position != last) && !can_start(*position, _map, (unsigned char)mask_any) ) + ++position; + if(position == last) + { + // run out of characters, try a null match if possible: + if(re.can_be_null()) + return match_prefix(); + break; + } + // now try and obtain a match: + if(match_prefix()) + return true; + if(position == last) + return false; + ++position; + } + return false; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::find_restart_word() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + // do search optimised for word starts: + const unsigned char* _map = re.get_map(); + if((m_match_flags & match_prev_avail) || (position != base)) + --position; + else if(match_prefix()) + return true; + do + { + while((position != last) && traits_inst.isctype(*position, m_word_mask)) + ++position; + while((position != last) && !traits_inst.isctype(*position, m_word_mask)) + ++position; + if(position == last) + break; + + if(can_start(*position, _map, (unsigned char)mask_any) ) + { + if(match_prefix()) + return true; + } + if(position == last) + break; + } while(true); + return false; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::find_restart_line() +{ + // do search optimised for line starts: + const unsigned char* _map = re.get_map(); + if(match_prefix()) + return true; + while(position != last) + { + while((position != last) && !is_separator(*position)) + ++position; + if(position == last) + return false; + ++position; + if(position == last) + { + if(re.can_be_null() && match_prefix()) + return true; + return false; + } + + if( can_start(*position, _map, (unsigned char)mask_any) ) + { + if(match_prefix()) + return true; + } + if(position == last) + return false; + //++position; + } + return false; +} + +template +bool perl_matcher::find_restart_buf() +{ + if((position == base) && ((m_match_flags & match_not_bob) == 0)) + return match_prefix(); + return false; +} + +template +bool perl_matcher::find_restart_lit() +{ +#if 0 + if(position == last) + return false; // can't possibly match if we're at the end already + + unsigned type = (m_match_flags & match_continuous) ? + static_cast(regbase::restart_continue) + : static_cast(re.get_restart_type()); + + const kmp_info* info = access::get_kmp(re); + int len = info->len; + const char_type* x = info->pstr; + int j = 0; + while (position != last) + { + while((j > -1) && (x[j] != traits_inst.translate(*position, icase))) + j = info->kmp_next[j]; + ++position; + ++j; + if(j >= len) + { + if(type == regbase::restart_fixed_lit) + { + std::advance(position, -j); + restart = position; + std::advance(restart, len); + m_result.set_first(position); + m_result.set_second(restart); + position = restart; + return true; + } + else + { + restart = position; + std::advance(position, -j); + if(match_prefix()) + return true; + else + { + for(int k = 0; (restart != position) && (k < j); ++k, --restart) + {} // dwa 10/20/2000 - warning suppression for MWCW + if(restart != last) + ++restart; + position = restart; + j = 0; //we could do better than this... + } + } + } + } + if((m_match_flags & match_partial) && (position == last) && j) + { + // we need to check for a partial match: + restart = position; + std::advance(position, -j); + return match_prefix(); + } +#endif + return false; +} + +} // namespace BOOST_REGEX_DETAIL_NS + +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#ifdef BOOST_BORLANDC +# pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif + diff --git a/boost/regex/v4/perl_matcher_non_recursive.hpp b/boost/regex/v4/perl_matcher_non_recursive.hpp new file mode 100644 index 00000000..670efbab --- /dev/null +++ b/boost/regex/v4/perl_matcher_non_recursive.hpp @@ -0,0 +1,1947 @@ +/* + * + * Copyright (c) 2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE perl_matcher_common.cpp + * VERSION see + * DESCRIPTION: Definitions of perl_matcher member functions that are + * specific to the non-recursive implementation. + */ + +#ifndef BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP +#define BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP + +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable: 4706) +#if BOOST_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +template +inline void inplace_destroy(T* p) +{ + (void)p; // warning suppression + p->~T(); +} + +struct saved_state +{ + union{ + unsigned int state_id; + // this padding ensures correct alignment on 64-bit platforms: + std::size_t padding1; + std::ptrdiff_t padding2; + void* padding3; + }; + saved_state(unsigned i) : state_id(i) {} +}; + +template +struct saved_matched_paren : public saved_state +{ + int index; + sub_match sub; + saved_matched_paren(int i, const sub_match& s) : saved_state(1), index(i), sub(s){} +}; + +template +struct saved_position : public saved_state +{ + const re_syntax_base* pstate; + BidiIterator position; + saved_position(const re_syntax_base* ps, BidiIterator pos, int i) : saved_state(i), pstate(ps), position(pos){} +}; + +template +struct saved_assertion : public saved_position +{ + bool positive; + saved_assertion(bool p, const re_syntax_base* ps, BidiIterator pos) + : saved_position(ps, pos, saved_type_assertion), positive(p){} +}; + +template +struct saved_repeater : public saved_state +{ + repeater_count count; + saved_repeater(int i, repeater_count** s, BidiIterator start, int current_recursion_id) + : saved_state(saved_state_repeater_count), count(i, s, start, current_recursion_id){} +}; + +struct saved_extra_block : public saved_state +{ + saved_state *base, *end; + saved_extra_block(saved_state* b, saved_state* e) + : saved_state(saved_state_extra_block), base(b), end(e) {} +}; + +struct save_state_init +{ + saved_state** stack; + save_state_init(saved_state** base, saved_state** end) + : stack(base) + { + *base = static_cast(get_mem_block()); + *end = reinterpret_cast(reinterpret_cast(*base)+BOOST_REGEX_BLOCKSIZE); + --(*end); + (void) new (*end)saved_state(0); + BOOST_REGEX_ASSERT(*end > *base); + } + ~save_state_init() + { + put_mem_block(*stack); + *stack = 0; + } +}; + +template +struct saved_single_repeat : public saved_state +{ + std::size_t count; + const re_repeat* rep; + BidiIterator last_position; + saved_single_repeat(std::size_t c, const re_repeat* r, BidiIterator lp, int arg_id) + : saved_state(arg_id), count(c), rep(r), last_position(lp){} +}; + +template +struct saved_recursion : public saved_state +{ + saved_recursion(int idx, const re_syntax_base* p, Results* pr, Results* pr2) + : saved_state(14), recursion_id(idx), preturn_address(p), internal_results(*pr), prior_results(*pr2) {} + int recursion_id; + const re_syntax_base* preturn_address; + Results internal_results, prior_results; +}; + +struct saved_change_case : public saved_state +{ + bool icase; + saved_change_case(bool c) : saved_state(18), icase(c) {} +}; + +struct incrementer +{ + incrementer(unsigned* pu) : m_pu(pu) { ++*m_pu; } + ~incrementer() { --*m_pu; } + bool operator > (unsigned i) { return *m_pu > i; } +private: + unsigned* m_pu; +}; + +template +bool perl_matcher::match_all_states() +{ + static matcher_proc_type const s_match_vtable[34] = + { + (&perl_matcher::match_startmark), + &perl_matcher::match_endmark, + &perl_matcher::match_literal, + &perl_matcher::match_start_line, + &perl_matcher::match_end_line, + &perl_matcher::match_wild, + &perl_matcher::match_match, + &perl_matcher::match_word_boundary, + &perl_matcher::match_within_word, + &perl_matcher::match_word_start, + &perl_matcher::match_word_end, + &perl_matcher::match_buffer_start, + &perl_matcher::match_buffer_end, + &perl_matcher::match_backref, + &perl_matcher::match_long_set, + &perl_matcher::match_set, + &perl_matcher::match_jump, + &perl_matcher::match_alt, + &perl_matcher::match_rep, + &perl_matcher::match_combining, + &perl_matcher::match_soft_buffer_end, + &perl_matcher::match_restart_continue, + // Although this next line *should* be evaluated at compile time, in practice + // some compilers (VC++) emit run-time initialisation which breaks thread + // safety, so use a dispatch function instead: + //(::boost::is_random_access_iterator::value ? &perl_matcher::match_dot_repeat_fast : &perl_matcher::match_dot_repeat_slow), + &perl_matcher::match_dot_repeat_dispatch, + &perl_matcher::match_char_repeat, + &perl_matcher::match_set_repeat, + &perl_matcher::match_long_set_repeat, + &perl_matcher::match_backstep, + &perl_matcher::match_assert_backref, + &perl_matcher::match_toggle_case, + &perl_matcher::match_recursion, + &perl_matcher::match_fail, + &perl_matcher::match_accept, + &perl_matcher::match_commit, + &perl_matcher::match_then, + }; + incrementer inc(&m_recursions); + if(inc > 80) + raise_error(traits_inst, regex_constants::error_complexity); + push_recursion_stopper(); + do{ + while(pstate) + { + matcher_proc_type proc = s_match_vtable[pstate->type]; + ++state_count; + if(!(this->*proc)()) + { + if(state_count > max_state_count) + raise_error(traits_inst, regex_constants::error_complexity); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + bool successful_unwind = unwind(false); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(!successful_unwind) + return m_recursive_result; + } + } + }while(unwind(true)); + return m_recursive_result; +} + +template +void perl_matcher::extend_stack() +{ + if(used_block_count) + { + --used_block_count; + saved_state* stack_base; + saved_state* backup_state; + stack_base = static_cast(get_mem_block()); + backup_state = reinterpret_cast(reinterpret_cast(stack_base)+BOOST_REGEX_BLOCKSIZE); + saved_extra_block* block = static_cast(backup_state); + --block; + (void) new (block) saved_extra_block(m_stack_base, m_backup_state); + m_stack_base = stack_base; + m_backup_state = block; + } + else + raise_error(traits_inst, regex_constants::error_stack); +} + +template +inline void perl_matcher::push_matched_paren(int index, const sub_match& sub) +{ + //BOOST_REGEX_ASSERT(index); + saved_matched_paren* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_matched_paren(index, sub); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_case_change(bool c) +{ + //BOOST_REGEX_ASSERT(index); + saved_change_case* pmp = static_cast(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast(m_backup_state); + --pmp; + } + (void) new (pmp)saved_change_case(c); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_recursion_stopper() +{ + saved_state* pmp = m_backup_state; + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = m_backup_state; + --pmp; + } + (void) new (pmp)saved_state(saved_type_recurse); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_assertion(const re_syntax_base* ps, bool positive) +{ + saved_assertion* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_assertion(positive, ps, position); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_alt(const re_syntax_base* ps) +{ + saved_position* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_position(ps, position, saved_state_alt); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_non_greedy_repeat(const re_syntax_base* ps) +{ + saved_position* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_position(ps, position, saved_state_non_greedy_long_repeat); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_repeater_count(int i, repeater_count** s) +{ + saved_repeater* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_repeater(i, s, position, this->recursion_stack.empty() ? (INT_MIN + 3) : this->recursion_stack.back().idx); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id) +{ + saved_single_repeat* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_single_repeat(c, r, last_position, state_id); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_recursion(int idx, const re_syntax_base* p, results_type* presults, results_type* presults2) +{ + saved_recursion* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_recursion(idx, p, presults, presults2); + m_backup_state = pmp; +} + +template +bool perl_matcher::match_toggle_case() +{ + // change our case sensitivity: + push_case_change(this->icase); + this->icase = static_cast(pstate)->icase; + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_startmark() +{ + int index = static_cast(pstate)->index; + icase = static_cast(pstate)->icase; + switch(index) + { + case 0: + pstate = pstate->next.p; + break; + case -1: + case -2: + { + // forward lookahead assert: + const re_syntax_base* next_pstate = static_cast(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; + push_assertion(next_pstate, index == -1); + break; + } + case -3: + { + // independent sub-expression, currently this is always recursive: + bool old_independent = m_independent; + m_independent = true; + const re_syntax_base* next_pstate = static_cast(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; + bool r = false; +#if !defined(BOOST_NO_EXCEPTIONS) + try{ +#endif + r = match_all_states(); + if(!r && !m_independent) + { + // Must be unwinding from a COMMIT/SKIP/PRUNE and the independent + // sub failed, need to unwind everything else: + while(unwind(false)); + return false; + } +#if !defined(BOOST_NO_EXCEPTIONS) + } + catch(...) + { + pstate = next_pstate; + // unwind all pushed states, apart from anything else this + // ensures that all the states are correctly destructed + // not just the memory freed. + while(unwind(true)) {} + throw; + } +#endif + pstate = next_pstate; + m_independent = old_independent; +#ifdef BOOST_REGEX_MATCH_EXTRA + if(r && (m_match_flags & match_extra)) + { + // + // our captures have been stored in *m_presult + // we need to unpack them, and insert them + // back in the right order when we unwind the stack: + // + match_results temp_match(*m_presult); + unsigned i; + for(i = 0; i < temp_match.size(); ++i) + (*m_presult)[i].get_captures().clear(); + // match everything else: +#if !defined(BOOST_NO_EXCEPTIONS) + try{ +#endif + r = match_all_states(); +#if !defined(BOOST_NO_EXCEPTIONS) + } + catch(...) + { + pstate = next_pstate; + // unwind all pushed states, apart from anything else this + // ensures that all the states are correctly destructed + // not just the memory freed. + while(unwind(true)) {} + throw; + } +#endif + // now place the stored captures back: + for(i = 0; i < temp_match.size(); ++i) + { + typedef typename sub_match::capture_sequence_type seq; + seq& s1 = (*m_presult)[i].get_captures(); + const seq& s2 = temp_match[i].captures(); + s1.insert( + s1.end(), + s2.begin(), + s2.end()); + } + } +#endif + return r; + } + case -4: + { + // conditional expression: + const re_alt* alt = static_cast(pstate->next.p); + BOOST_REGEX_ASSERT(alt->type == syntax_element_alt); + pstate = alt->next.p; + if(pstate->type == syntax_element_assert_backref) + { + if(!match_assert_backref()) + pstate = alt->alt.p; + break; + } + else + { + // zero width assertion, have to match this recursively: + BOOST_REGEX_ASSERT(pstate->type == syntax_element_startmark); + bool negated = static_cast(pstate)->index == -2; + BidiIterator saved_position = position; + const re_syntax_base* next_pstate = static_cast(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; +#if !defined(BOOST_NO_EXCEPTIONS) + try{ +#endif + bool r = match_all_states(); + position = saved_position; + if(negated) + r = !r; + if(r) + pstate = next_pstate; + else + pstate = alt->alt.p; +#if !defined(BOOST_NO_EXCEPTIONS) + } + catch(...) + { + pstate = next_pstate; + // unwind all pushed states, apart from anything else this + // ensures that all the states are correctly destructed + // not just the memory freed. + while(unwind(true)){} + throw; + } +#endif + break; + } + } + case -5: + { + push_matched_paren(0, (*m_presult)[0]); + m_presult->set_first(position, 0, true); + pstate = pstate->next.p; + break; + } + default: + { + BOOST_REGEX_ASSERT(index > 0); + if((m_match_flags & match_nosubs) == 0) + { + push_matched_paren(index, (*m_presult)[index]); + m_presult->set_first(position, index); + } + pstate = pstate->next.p; + break; + } + } + return true; +} + +template +bool perl_matcher::match_alt() +{ + bool take_first, take_second; + const re_alt* jmp = static_cast(pstate); + + // find out which of these two alternatives we need to take: + if(position == last) + { + take_first = jmp->can_be_null & mask_take; + take_second = jmp->can_be_null & mask_skip; + } + else + { + take_first = can_start(*position, jmp->_map, (unsigned char)mask_take); + take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip); + } + + if(take_first) + { + // we can take the first alternative, + // see if we need to push next alternative: + if(take_second) + { + push_alt(jmp->alt.p); + } + pstate = pstate->next.p; + return true; + } + if(take_second) + { + pstate = jmp->alt.p; + return true; + } + return false; // neither option is possible +} + +template +bool perl_matcher::match_rep() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127 4244) +#endif +#ifdef BOOST_BORLANDC +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + const re_repeat* rep = static_cast(pstate); + + // find out which of these two alternatives we need to take: + bool take_first, take_second; + if(position == last) + { + take_first = rep->can_be_null & mask_take; + take_second = rep->can_be_null & mask_skip; + } + else + { + take_first = can_start(*position, rep->_map, (unsigned char)mask_take); + take_second = can_start(*position, rep->_map, (unsigned char)mask_skip); + } + + if((m_backup_state->state_id != saved_state_repeater_count) + || (static_cast*>(m_backup_state)->count.get_id() != rep->state_id) + || (next_count->get_id() != rep->state_id)) + { + // we're moving to a different repeat from the last + // one, so set up a counter object: + push_repeater_count(rep->state_id, &next_count); + } + // + // If we've had at least one repeat already, and the last one + // matched the NULL string then set the repeat count to + // maximum: + // + next_count->check_null_repeat(position, rep->max); + + if(next_count->get_count() < rep->min) + { + // we must take the repeat: + if(take_first) + { + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + return true; + } + return false; + } + + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + if(greedy) + { + // try and take the repeat if we can: + if((next_count->get_count() < rep->max) && take_first) + { + if(take_second) + { + // store position in case we fail: + push_alt(rep->alt.p); + } + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + return true; + } + else if(take_second) + { + pstate = rep->alt.p; + return true; + } + return false; // can't take anything, fail... + } + else // non-greedy + { + // try and skip the repeat if we can: + if(take_second) + { + if((next_count->get_count() < rep->max) && take_first) + { + // store position in case we fail: + push_non_greedy_repeat(rep->next.p); + } + pstate = rep->alt.p; + return true; + } + if((next_count->get_count() < rep->max) && take_first) + { + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + return true; + } + } + return false; +#ifdef BOOST_BORLANDC +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_dot_repeat_slow() +{ + std::size_t count = 0; + const re_repeat* rep = static_cast(pstate); + re_syntax_base* psingle = rep->next.p; + // match compulsory repeats first: + while(count < rep->min) + { + pstate = psingle; + if(!match_wild()) + return false; + ++count; + } + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + if(greedy) + { + // repeat for as long as we can: + while(count < rep->max) + { + pstate = psingle; + if(!match_wild()) + break; + ++count; + } + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_slow_dot); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +} + +template +bool perl_matcher::match_dot_repeat_fast() +{ + if(m_match_flags & match_not_dot_null) + return match_dot_repeat_slow(); + if((static_cast(pstate->next.p)->mask & match_any_mask) == 0) + return match_dot_repeat_slow(); + + const re_repeat* rep = static_cast(pstate); + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t count = static_cast((std::min)(static_cast(::boost::BOOST_REGEX_DETAIL_NS::distance(position, last)), greedy ? rep->max : rep->min)); + if(rep->min > count) + { + position = last; + return false; // not enough text left to match + } + std::advance(position, count); + + if(greedy) + { + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_fast_dot); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +} + +template +bool perl_matcher::match_char_repeat() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif +#ifdef BOOST_BORLANDC +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + const re_repeat* rep = static_cast(pstate); + BOOST_REGEX_ASSERT(1 == static_cast(rep->next.p)->length); + const char_type what = *reinterpret_cast(static_cast(rep->next.p) + 1); + std::size_t count = 0; + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t desired = greedy ? rep->max : rep->min; + if(::boost::is_random_access_iterator::value) + { + BidiIterator end = position; + // Move end forward by "desired", preferably without using distance or advance if we can + // as these can be slow for some iterator types. + std::size_t len = (desired == (std::numeric_limits::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last); + if(desired >= len) + end = last; + else + std::advance(end, desired); + BidiIterator origin(position); + while((position != end) && (traits_inst.translate(*position, icase) == what)) + { + ++position; + } + count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position); + } + else + { + while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what)) + { + ++position; + ++count; + } + } + + if(count < rep->min) + return false; + + if(greedy) + { + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_char); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +#ifdef BOOST_BORLANDC +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_set_repeat() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif +#ifdef BOOST_BORLANDC +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + const re_repeat* rep = static_cast(pstate); + const unsigned char* map = static_cast(rep->next.p)->_map; + std::size_t count = 0; + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t desired = greedy ? rep->max : rep->min; + if(::boost::is_random_access_iterator::value) + { + BidiIterator end = position; + // Move end forward by "desired", preferably without using distance or advance if we can + // as these can be slow for some iterator types. + std::size_t len = (desired == (std::numeric_limits::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last); + if(desired >= len) + end = last; + else + std::advance(end, desired); + BidiIterator origin(position); + while((position != end) && map[static_cast(traits_inst.translate(*position, icase))]) + { + ++position; + } + count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position); + } + else + { + while((count < desired) && (position != last) && map[static_cast(traits_inst.translate(*position, icase))]) + { + ++position; + ++count; + } + } + + if(count < rep->min) + return false; + + if(greedy) + { + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_short_set); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +#ifdef BOOST_BORLANDC +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_long_set_repeat() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif +#ifdef BOOST_BORLANDC +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + typedef typename traits::char_class_type m_type; + const re_repeat* rep = static_cast(pstate); + const re_set_long* set = static_cast*>(pstate->next.p); + std::size_t count = 0; + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t desired = greedy ? rep->max : rep->min; + if(::boost::is_random_access_iterator::value) + { + BidiIterator end = position; + // Move end forward by "desired", preferably without using distance or advance if we can + // as these can be slow for some iterator types. + std::size_t len = (desired == (std::numeric_limits::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last); + if(desired >= len) + end = last; + else + std::advance(end, desired); + BidiIterator origin(position); + while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase))) + { + ++position; + } + count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position); + } + else + { + while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase))) + { + ++position; + ++count; + } + } + + if(count < rep->min) + return false; + + if(greedy) + { + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_long_set); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +#ifdef BOOST_BORLANDC +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_recursion() +{ + BOOST_REGEX_ASSERT(pstate->type == syntax_element_recurse); + // + // See if we've seen this recursion before at this location, if we have then + // we need to prevent infinite recursion: + // + for(typename std::vector >::reverse_iterator i = recursion_stack.rbegin(); i != recursion_stack.rend(); ++i) + { + if(i->idx == static_cast(static_cast(pstate)->alt.p)->index) + { + if(i->location_of_start == position) + return false; + break; + } + } + // + // Backup call stack: + // + push_recursion_pop(); + // + // Set new call stack: + // + if(recursion_stack.capacity() == 0) + { + recursion_stack.reserve(50); + } + recursion_stack.push_back(recursion_info()); + recursion_stack.back().preturn_address = pstate->next.p; + recursion_stack.back().results = *m_presult; + pstate = static_cast(pstate)->alt.p; + recursion_stack.back().idx = static_cast(pstate)->index; + recursion_stack.back().location_of_start = position; + //if(static_cast(pstate)->state_id > 0) + { + push_repeater_count(-(2 + static_cast(pstate)->index), &next_count); + } + + return true; +} + +template +bool perl_matcher::match_endmark() +{ + int index = static_cast(pstate)->index; + icase = static_cast(pstate)->icase; + if(index > 0) + { + if((m_match_flags & match_nosubs) == 0) + { + m_presult->set_second(position, index); + } + if(!recursion_stack.empty()) + { + if(index == recursion_stack.back().idx) + { + pstate = recursion_stack.back().preturn_address; + *m_presult = recursion_stack.back().results; + push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, m_presult, &recursion_stack.back().results); + recursion_stack.pop_back(); + push_repeater_count(-(2 + index), &next_count); + } + } + } + else if((index < 0) && (index != -4)) + { + // matched forward lookahead: + pstate = 0; + return true; + } + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_match() +{ + if(!recursion_stack.empty()) + { + BOOST_REGEX_ASSERT(0 == recursion_stack.back().idx); + pstate = recursion_stack.back().preturn_address; + push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, m_presult, &recursion_stack.back().results); + *m_presult = recursion_stack.back().results; + recursion_stack.pop_back(); + return true; + } + if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first)) + return false; + if((m_match_flags & match_all) && (position != last)) + return false; + if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base)) + return false; + m_presult->set_second(position); + pstate = 0; + m_has_found_match = true; + if((m_match_flags & match_posix) == match_posix) + { + m_result.maybe_assign(*m_presult); + if((m_match_flags & match_any) == 0) + return false; + } +#ifdef BOOST_REGEX_MATCH_EXTRA + if(match_extra & m_match_flags) + { + for(unsigned i = 0; i < m_presult->size(); ++i) + if((*m_presult)[i].matched) + ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]); + } +#endif + return true; +} + +template +bool perl_matcher::match_commit() +{ + // Ideally we would just junk all the states that are on the stack, + // however we might not unwind correctly in that case, so for now, + // just mark that we don't backtrack into whatever is left (or rather + // we'll unwind it unconditionally without pausing to try other matches). + + switch(static_cast(pstate)->action) + { + case commit_commit: + restart = last; + break; + case commit_skip: + if(base != position) + { + restart = position; + // Have to decrement restart since it will get incremented again later: + --restart; + } + break; + case commit_prune: + break; + } + + saved_state* pmp = m_backup_state; + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = m_backup_state; + --pmp; + } + (void) new (pmp)saved_state(16); + m_backup_state = pmp; + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_then() +{ + // Just leave a mark that we need to skip to next alternative: + saved_state* pmp = m_backup_state; + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = m_backup_state; + --pmp; + } + (void) new (pmp)saved_state(17); + m_backup_state = pmp; + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::skip_until_paren(int index, bool have_match) +{ + while(pstate) + { + if(pstate->type == syntax_element_endmark) + { + if(static_cast(pstate)->index == index) + { + if(have_match) + return this->match_endmark(); + pstate = pstate->next.p; + return true; + } + else + { + // Unenclosed closing ), occurs when (*ACCEPT) is inside some other + // parenthesis which may or may not have other side effects associated with it. + const re_syntax_base* sp = pstate; + match_endmark(); + if(!pstate) + { + unwind(true); + // unwind may leave pstate NULL if we've unwound a forward lookahead, in which + // case just move to the next state and keep looking... + if (!pstate) + pstate = sp->next.p; + } + } + continue; + } + else if(pstate->type == syntax_element_match) + return true; + else if(pstate->type == syntax_element_startmark) + { + int idx = static_cast(pstate)->index; + pstate = pstate->next.p; + skip_until_paren(idx, false); + continue; + } + pstate = pstate->next.p; + } + return true; +} + +/**************************************************************************** + +Unwind and associated procedures follow, these perform what normal stack +unwinding does in the recursive implementation. + +****************************************************************************/ + +template +bool perl_matcher::unwind(bool have_match) +{ + static unwind_proc_type const s_unwind_table[19] = + { + &perl_matcher::unwind_end, + &perl_matcher::unwind_paren, + &perl_matcher::unwind_recursion_stopper, + &perl_matcher::unwind_assertion, + &perl_matcher::unwind_alt, + &perl_matcher::unwind_repeater_counter, + &perl_matcher::unwind_extra_block, + &perl_matcher::unwind_greedy_single_repeat, + &perl_matcher::unwind_slow_dot_repeat, + &perl_matcher::unwind_fast_dot_repeat, + &perl_matcher::unwind_char_repeat, + &perl_matcher::unwind_short_set_repeat, + &perl_matcher::unwind_long_set_repeat, + &perl_matcher::unwind_non_greedy_repeat, + &perl_matcher::unwind_recursion, + &perl_matcher::unwind_recursion_pop, + &perl_matcher::unwind_commit, + &perl_matcher::unwind_then, + &perl_matcher::unwind_case, + }; + + m_recursive_result = have_match; + m_unwound_lookahead = false; + m_unwound_alt = false; + unwind_proc_type unwinder; + bool cont; + // + // keep unwinding our stack until we have something to do: + // + do + { + unwinder = s_unwind_table[m_backup_state->state_id]; + cont = (this->*unwinder)(m_recursive_result); + }while(cont); + // + // return true if we have more states to try: + // + return pstate ? true : false; +} + +template +bool perl_matcher::unwind_end(bool) +{ + pstate = 0; // nothing left to search + return false; // end of stack nothing more to search +} + +template +bool perl_matcher::unwind_case(bool) +{ + saved_change_case* pmp = static_cast(m_backup_state); + icase = pmp->icase; + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; +} + +template +bool perl_matcher::unwind_paren(bool have_match) +{ + saved_matched_paren* pmp = static_cast*>(m_backup_state); + // restore previous values if no match was found: + if(!have_match) + { + m_presult->set_first(pmp->sub.first, pmp->index, pmp->index == 0); + m_presult->set_second(pmp->sub.second, pmp->index, pmp->sub.matched, pmp->index == 0); + } +#ifdef BOOST_REGEX_MATCH_EXTRA + // + // we have a match, push the capture information onto the stack: + // + else if(pmp->sub.matched && (match_extra & m_match_flags)) + ((*m_presult)[pmp->index]).get_captures().push_back(pmp->sub); +#endif + // unwind stack: + m_backup_state = pmp+1; + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp); + return true; // keep looking +} + +template +bool perl_matcher::unwind_recursion_stopper(bool) +{ + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++); + pstate = 0; // nothing left to search + return false; // end of stack nothing more to search +} + +template +bool perl_matcher::unwind_assertion(bool r) +{ + saved_assertion* pmp = static_cast*>(m_backup_state); + pstate = pmp->pstate; + position = pmp->position; + bool result = (r == pmp->positive); + m_recursive_result = pmp->positive ? r : !r; + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + m_unwound_lookahead = true; + return !result; // return false if the assertion was matched to stop search. +} + +template +bool perl_matcher::unwind_alt(bool r) +{ + saved_position* pmp = static_cast*>(m_backup_state); + if(!r) + { + pstate = pmp->pstate; + position = pmp->position; + } + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + m_unwound_alt = !r; + return r; +} + +template +bool perl_matcher::unwind_repeater_counter(bool) +{ + ++used_block_count; + saved_repeater* pmp = static_cast*>(m_backup_state); + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; // keep looking +} + +template +bool perl_matcher::unwind_extra_block(bool) +{ + saved_extra_block* pmp = static_cast(m_backup_state); + void* condemmed = m_stack_base; + m_stack_base = pmp->base; + m_backup_state = pmp->end; + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp); + put_mem_block(condemmed); + return true; // keep looking +} + +template +inline void perl_matcher::destroy_single_repeat() +{ + saved_single_repeat* p = static_cast*>(m_backup_state); + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(p++); + m_backup_state = p; +} + +template +bool perl_matcher::unwind_greedy_single_repeat(bool r) +{ + saved_single_repeat* pmp = static_cast*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + BOOST_REGEX_ASSERT(rep->next.p != 0); + BOOST_REGEX_ASSERT(rep->alt.p != 0); + + count -= rep->min; + + if((m_match_flags & match_partial) && (position == last)) + m_has_partial_match = true; + + BOOST_REGEX_ASSERT(count); + position = pmp->last_position; + + // backtrack till we can skip out: + do + { + --position; + --count; + ++state_count; + }while(count && !can_start(*position, rep->_map, mask_skip)); + + // if we've hit base, destroy this state: + if(count == 0) + { + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count + rep->min; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template +bool perl_matcher::unwind_slow_dot_repeat(bool r) +{ + saved_single_repeat* pmp = static_cast*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + BOOST_REGEX_ASSERT(rep->type == syntax_element_dot_rep); + BOOST_REGEX_ASSERT(rep->next.p != 0); + BOOST_REGEX_ASSERT(rep->alt.p != 0); + BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_wild); + + BOOST_REGEX_ASSERT(count < rep->max); + pstate = rep->next.p; + position = pmp->last_position; + + if(position != last) + { + // wind forward until we can skip out of the repeat: + do + { + if(!match_wild()) + { + // failed repeat match, discard this state and look for another: + destroy_single_repeat(); + return true; + } + ++count; + ++state_count; + pstate = rep->next.p; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template +bool perl_matcher::unwind_fast_dot_repeat(bool r) +{ + saved_single_repeat* pmp = static_cast*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + + BOOST_REGEX_ASSERT(count < rep->max); + position = pmp->last_position; + if(position != last) + { + + // wind forward until we can skip out of the repeat: + do + { + ++position; + ++count; + ++state_count; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template +bool perl_matcher::unwind_char_repeat(bool r) +{ + saved_single_repeat* pmp = static_cast*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + pstate = rep->next.p; + const char_type what = *reinterpret_cast(static_cast(pstate) + 1); + position = pmp->last_position; + + BOOST_REGEX_ASSERT(rep->type == syntax_element_char_rep); + BOOST_REGEX_ASSERT(rep->next.p != 0); + BOOST_REGEX_ASSERT(rep->alt.p != 0); + BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_literal); + BOOST_REGEX_ASSERT(count < rep->max); + + if(position != last) + { + // wind forward until we can skip out of the repeat: + do + { + if(traits_inst.translate(*position, icase) != what) + { + // failed repeat match, discard this state and look for another: + destroy_single_repeat(); + return true; + } + ++count; + ++ position; + ++state_count; + pstate = rep->next.p; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template +bool perl_matcher::unwind_short_set_repeat(bool r) +{ + saved_single_repeat* pmp = static_cast*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + pstate = rep->next.p; + const unsigned char* map = static_cast(rep->next.p)->_map; + position = pmp->last_position; + + BOOST_REGEX_ASSERT(rep->type == syntax_element_short_set_rep); + BOOST_REGEX_ASSERT(rep->next.p != 0); + BOOST_REGEX_ASSERT(rep->alt.p != 0); + BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_set); + BOOST_REGEX_ASSERT(count < rep->max); + + if(position != last) + { + // wind forward until we can skip out of the repeat: + do + { + if(!map[static_cast(traits_inst.translate(*position, icase))]) + { + // failed repeat match, discard this state and look for another: + destroy_single_repeat(); + return true; + } + ++count; + ++ position; + ++state_count; + pstate = rep->next.p; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template +bool perl_matcher::unwind_long_set_repeat(bool r) +{ + typedef typename traits::char_class_type m_type; + saved_single_repeat* pmp = static_cast*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + pstate = rep->next.p; + const re_set_long* set = static_cast*>(pstate); + position = pmp->last_position; + + BOOST_REGEX_ASSERT(rep->type == syntax_element_long_set_rep); + BOOST_REGEX_ASSERT(rep->next.p != 0); + BOOST_REGEX_ASSERT(rep->alt.p != 0); + BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_long_set); + BOOST_REGEX_ASSERT(count < rep->max); + + if(position != last) + { + // wind forward until we can skip out of the repeat: + do + { + if(position == re_is_set_member(position, last, set, re.get_data(), icase)) + { + // failed repeat match, discard this state and look for another: + destroy_single_repeat(); + return true; + } + ++position; + ++count; + ++state_count; + pstate = rep->next.p; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template +bool perl_matcher::unwind_non_greedy_repeat(bool r) +{ + saved_position* pmp = static_cast*>(m_backup_state); + if(!r) + { + position = pmp->position; + pstate = pmp->pstate; + ++(*next_count); + } + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + return r; +} + +template +bool perl_matcher::unwind_recursion(bool r) +{ + // We are backtracking back inside a recursion, need to push the info + // back onto the recursion stack, and do so unconditionally, otherwise + // we can get mismatched pushes and pops... + saved_recursion* pmp = static_cast*>(m_backup_state); + if (!r) + { + recursion_stack.push_back(recursion_info()); + recursion_stack.back().idx = pmp->recursion_id; + recursion_stack.back().preturn_address = pmp->preturn_address; + recursion_stack.back().results = pmp->prior_results; + recursion_stack.back().location_of_start = position; + *m_presult = pmp->internal_results; + } + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; +} + +template +bool perl_matcher::unwind_recursion_pop(bool r) +{ + // Backtracking out of a recursion, we must pop state off the recursion + // stack unconditionally to ensure matched pushes and pops: + saved_state* pmp = static_cast(m_backup_state); + if (!r && !recursion_stack.empty()) + { + *m_presult = recursion_stack.back().results; + position = recursion_stack.back().location_of_start; + recursion_stack.pop_back(); + } + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; +} + +template +void perl_matcher::push_recursion_pop() +{ + saved_state* pmp = static_cast(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast(m_backup_state); + --pmp; + } + (void) new (pmp)saved_state(15); + m_backup_state = pmp; +} + +template +bool perl_matcher::unwind_commit(bool b) +{ + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++); + while(unwind(b) && !m_unwound_lookahead){} + if(m_unwound_lookahead && pstate) + { + // + // If we stop because we just unwound an assertion, put the + // commit state back on the stack again: + // + m_unwound_lookahead = false; + saved_state* pmp = m_backup_state; + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = m_backup_state; + --pmp; + } + (void) new (pmp)saved_state(16); + m_backup_state = pmp; + } + // This prevents us from stopping when we exit from an independent sub-expression: + m_independent = false; + return false; +} + +template +bool perl_matcher::unwind_then(bool b) +{ + // Unwind everything till we hit an alternative: + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++); + bool result = false; + while((result = unwind(b)) && !m_unwound_alt){} + // We're now pointing at the next alternative, need one more backtrack + // since *all* the other alternatives must fail once we've reached a THEN clause: + if(result && m_unwound_alt) + unwind(b); + return false; +} + +/* +template +bool perl_matcher::unwind_parenthesis_pop(bool r) +{ + saved_state* pmp = static_cast(m_backup_state); + if(!r) + { + --parenthesis_stack_position; + } + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; +} + +template +void perl_matcher::push_parenthesis_pop() +{ + saved_state* pmp = static_cast(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast(m_backup_state); + --pmp; + } + (void) new (pmp)saved_state(16); + m_backup_state = pmp; +} + +template +bool perl_matcher::unwind_parenthesis_push(bool r) +{ + saved_position* pmp = static_cast*>(m_backup_state); + if(!r) + { + parenthesis_stack[parenthesis_stack_position++] = pmp->position; + } + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; +} + +template +inline void perl_matcher::push_parenthesis_push(BidiIterator p) +{ + saved_position* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_position(0, p, 17); + m_backup_state = pmp; +} +*/ +} // namespace BOOST_REGEX_DETAIL_NS +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif diff --git a/boost/regex/v4/perl_matcher_recursive.hpp b/boost/regex/v4/perl_matcher_recursive.hpp new file mode 100644 index 00000000..7d262fe2 --- /dev/null +++ b/boost/regex/v4/perl_matcher_recursive.hpp @@ -0,0 +1,1131 @@ +/* + * + * Copyright (c) 2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE perl_matcher_common.cpp + * VERSION see + * DESCRIPTION: Definitions of perl_matcher member functions that are + * specific to the recursive implementation. + */ + +#ifndef BOOST_REGEX_V4_PERL_MATCHER_RECURSIVE_HPP +#define BOOST_REGEX_V4_PERL_MATCHER_RECURSIVE_HPP + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4800) +#endif + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +template +class backup_subex +{ + int index; + sub_match sub; +public: + template + backup_subex(const match_results& w, int i) + : index(i), sub(w[i], false) {} + template + void restore(match_results& w) + { + w.set_first(sub.first, index, index == 0); + w.set_second(sub.second, index, sub.matched, index == 0); + } + const sub_match& get() { return sub; } +}; + +template +bool perl_matcher::match_all_states() +{ + static matcher_proc_type const s_match_vtable[34] = + { + (&perl_matcher::match_startmark), + &perl_matcher::match_endmark, + &perl_matcher::match_literal, + &perl_matcher::match_start_line, + &perl_matcher::match_end_line, + &perl_matcher::match_wild, + &perl_matcher::match_match, + &perl_matcher::match_word_boundary, + &perl_matcher::match_within_word, + &perl_matcher::match_word_start, + &perl_matcher::match_word_end, + &perl_matcher::match_buffer_start, + &perl_matcher::match_buffer_end, + &perl_matcher::match_backref, + &perl_matcher::match_long_set, + &perl_matcher::match_set, + &perl_matcher::match_jump, + &perl_matcher::match_alt, + &perl_matcher::match_rep, + &perl_matcher::match_combining, + &perl_matcher::match_soft_buffer_end, + &perl_matcher::match_restart_continue, + // Although this next line *should* be evaluated at compile time, in practice + // some compilers (VC++) emit run-time initialisation which breaks thread + // safety, so use a dispatch function instead: + //(::boost::is_random_access_iterator::value ? &perl_matcher::match_dot_repeat_fast : &perl_matcher::match_dot_repeat_slow), + &perl_matcher::match_dot_repeat_dispatch, + &perl_matcher::match_char_repeat, + &perl_matcher::match_set_repeat, + &perl_matcher::match_long_set_repeat, + &perl_matcher::match_backstep, + &perl_matcher::match_assert_backref, + &perl_matcher::match_toggle_case, + &perl_matcher::match_recursion, + &perl_matcher::match_fail, + &perl_matcher::match_accept, + &perl_matcher::match_commit, + &perl_matcher::match_then, + }; + + if(state_count > max_state_count) + raise_error(traits_inst, regex_constants::error_complexity); + while(pstate) + { + matcher_proc_type proc = s_match_vtable[pstate->type]; + ++state_count; + if(!(this->*proc)()) + { + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + return 0; + } + } + return true; +} + +template +bool perl_matcher::match_startmark() +{ + int index = static_cast(pstate)->index; + icase = static_cast(pstate)->icase; + bool r = true; + switch(index) + { + case 0: + pstate = pstate->next.p; + break; + case -1: + case -2: + { + // forward lookahead assert: + BidiIterator old_position(position); + const re_syntax_base* next_pstate = static_cast(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; + r = match_all_states(); + pstate = next_pstate; + position = old_position; + if((r && (index != -1)) || (!r && (index != -2))) + r = false; + else + r = true; + if(r && m_have_accept) + r = skip_until_paren(INT_MAX); + break; + } + case -3: + { + // independent sub-expression: + bool old_independent = m_independent; + m_independent = true; + const re_syntax_base* next_pstate = static_cast(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; + bool can_backtrack = m_can_backtrack; + r = match_all_states(); + if(r) + m_can_backtrack = can_backtrack; + pstate = next_pstate; + m_independent = old_independent; +#ifdef BOOST_REGEX_MATCH_EXTRA + if(r && (m_match_flags & match_extra)) + { + // + // our captures have been stored in *m_presult + // we need to unpack them, and insert them + // back in the right order when we unwind the stack: + // + unsigned i; + match_results tm(*m_presult); + for(i = 0; i < tm.size(); ++i) + (*m_presult)[i].get_captures().clear(); + // match everything else: + r = match_all_states(); + // now place the stored captures back: + for(i = 0; i < tm.size(); ++i) + { + typedef typename sub_match::capture_sequence_type seq; + seq& s1 = (*m_presult)[i].get_captures(); + const seq& s2 = tm[i].captures(); + s1.insert( + s1.end(), + s2.begin(), + s2.end()); + } + } +#endif + if(r && m_have_accept) + r = skip_until_paren(INT_MAX); + break; + } + case -4: + { + // conditional expression: + const re_alt* alt = static_cast(pstate->next.p); + BOOST_REGEX_ASSERT(alt->type == syntax_element_alt); + pstate = alt->next.p; + if(pstate->type == syntax_element_assert_backref) + { + if(!match_assert_backref()) + pstate = alt->alt.p; + break; + } + else + { + // zero width assertion, have to match this recursively: + BOOST_REGEX_ASSERT(pstate->type == syntax_element_startmark); + bool negated = static_cast(pstate)->index == -2; + BidiIterator saved_position = position; + const re_syntax_base* next_pstate = static_cast(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; + bool res = match_all_states(); + position = saved_position; + if(negated) + res = !res; + if(res) + pstate = next_pstate; + else + pstate = alt->alt.p; + break; + } + } + case -5: + { + // Reset start of $0, since we have a \K escape + backup_subex sub(*m_presult, 0); + m_presult->set_first(position, 0, true); + pstate = pstate->next.p; + r = match_all_states(); + if(r == false) + sub.restore(*m_presult); + break; + } + default: + { + BOOST_REGEX_ASSERT(index > 0); + if((m_match_flags & match_nosubs) == 0) + { + backup_subex sub(*m_presult, index); + m_presult->set_first(position, index); + pstate = pstate->next.p; + r = match_all_states(); + if(r == false) + sub.restore(*m_presult); +#ifdef BOOST_REGEX_MATCH_EXTRA + // + // we have a match, push the capture information onto the stack: + // + else if(sub.get().matched && (match_extra & m_match_flags)) + ((*m_presult)[index]).get_captures().push_back(sub.get()); +#endif + } + else + { + pstate = pstate->next.p; + } + break; + } + } + return r; +} + +template +bool perl_matcher::match_alt() +{ + bool take_first, take_second; + const re_alt* jmp = static_cast(pstate); + + // find out which of these two alternatives we need to take: + if(position == last) + { + take_first = jmp->can_be_null & mask_take; + take_second = jmp->can_be_null & mask_skip; + } + else + { + take_first = can_start(*position, jmp->_map, (unsigned char)mask_take); + take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip); + } + + if(take_first) + { + // we can take the first alternative, + // see if we need to push next alternative: + if(take_second) + { + BidiIterator oldposition(position); + const re_syntax_base* old_pstate = jmp->alt.p; + pstate = pstate->next.p; + bool oldcase = icase; + m_have_then = false; + if(!match_all_states()) + { + pstate = old_pstate; + position = oldposition; + icase = oldcase; + if(m_have_then) + { + m_can_backtrack = true; + m_have_then = false; + return false; + } + } + m_have_then = false; + return m_can_backtrack; + } + pstate = pstate->next.p; + return true; + } + if(take_second) + { + pstate = jmp->alt.p; + return true; + } + return false; // neither option is possible +} + +template +bool perl_matcher::match_rep() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127 4244) +#endif + const re_repeat* rep = static_cast(pstate); + // + // Always copy the repeat count, so that the state is restored + // when we exit this scope: + // + repeater_count r(rep->state_id, &next_count, position, this->recursion_stack.size() ? this->recursion_stack.back().idx : INT_MIN + 3); + // + // If we've had at least one repeat already, and the last one + // matched the NULL string then set the repeat count to + // maximum: + // + next_count->check_null_repeat(position, rep->max); + + // find out which of these two alternatives we need to take: + bool take_first, take_second; + if(position == last) + { + take_first = rep->can_be_null & mask_take; + take_second = rep->can_be_null & mask_skip; + } + else + { + take_first = can_start(*position, rep->_map, (unsigned char)mask_take); + take_second = can_start(*position, rep->_map, (unsigned char)mask_skip); + } + + if(next_count->get_count() < rep->min) + { + // we must take the repeat: + if(take_first) + { + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + return match_all_states(); + } + return false; + } + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + if(greedy) + { + // try and take the repeat if we can: + if((next_count->get_count() < rep->max) && take_first) + { + // store position in case we fail: + BidiIterator pos = position; + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + if(match_all_states()) + return true; + if(!m_can_backtrack) + return false; + // failed repeat, reset posistion and fall through for alternative: + position = pos; + } + if(take_second) + { + pstate = rep->alt.p; + return true; + } + return false; // can't take anything, fail... + } + else // non-greedy + { + // try and skip the repeat if we can: + if(take_second) + { + // store position in case we fail: + BidiIterator pos = position; + pstate = rep->alt.p; + if(match_all_states()) + return true; + if(!m_can_backtrack) + return false; + // failed alternative, reset posistion and fall through for repeat: + position = pos; + } + if((next_count->get_count() < rep->max) && take_first) + { + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + return match_all_states(); + } + } + return false; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_dot_repeat_slow() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + std::size_t count = 0; + const re_repeat* rep = static_cast(pstate); + re_syntax_base* psingle = rep->next.p; + // match compulsary repeats first: + while(count < rep->min) + { + pstate = psingle; + if(!match_wild()) + return false; + ++count; + } + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + if(greedy) + { + // normal repeat: + while(count < rep->max) + { + pstate = psingle; + if(!match_wild()) + break; + ++count; + } + if((rep->leading) && (count < rep->max)) + restart = position; + pstate = rep; + return backtrack_till_match(count - rep->min); + } + else + { + // non-greedy, keep trying till we get a match: + BidiIterator save_pos; + do + { + if((rep->leading) && (rep->max == UINT_MAX)) + restart = position; + pstate = rep->alt.p; + save_pos = position; + ++state_count; + if(match_all_states()) + return true; + if((count >= rep->max) || !m_can_backtrack) + return false; + ++count; + pstate = psingle; + position = save_pos; + if(!match_wild()) + return false; + }while(true); + } +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_dot_repeat_fast() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + if(m_match_flags & match_not_dot_null) + return match_dot_repeat_slow(); + if((static_cast(pstate->next.p)->mask & match_any_mask) == 0) + return match_dot_repeat_slow(); + // + // start by working out how much we can skip: + // + const re_repeat* rep = static_cast(pstate); +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4267) +#endif + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t count = (std::min)(static_cast(::boost::BOOST_REGEX_DETAIL_NS::distance(position, last)), greedy ? rep->max : rep->min); + if(rep->min > count) + { + position = last; + return false; // not enough text left to match + } + std::advance(position, count); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + if((rep->leading) && (count < rep->max) && greedy) + restart = position; + if(greedy) + return backtrack_till_match(count - rep->min); + + // non-greedy, keep trying till we get a match: + BidiIterator save_pos; + do + { + while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip)) + { + ++position; + ++count; + } + if((rep->leading) && (rep->max == UINT_MAX)) + restart = position; + pstate = rep->alt.p; + save_pos = position; + ++state_count; + if(match_all_states()) + return true; + if((count >= rep->max) || !m_can_backtrack) + return false; + if(save_pos == last) + return false; + position = ++save_pos; + ++count; + }while(true); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_char_repeat() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#pragma warning(disable:4267) +#endif +#ifdef BOOST_BORLANDC +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + const re_repeat* rep = static_cast(pstate); + BOOST_REGEX_ASSERT(1 == static_cast(rep->next.p)->length); + const char_type what = *reinterpret_cast(static_cast(rep->next.p) + 1); + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t count, desired; + if(::boost::is_random_access_iterator::value) + { + desired = + (std::min)( + (std::size_t)(greedy ? rep->max : rep->min), + (std::size_t)::boost::BOOST_REGEX_DETAIL_NS::distance(position, last)); + count = desired; + ++desired; + if(icase) + { + while(--desired && (traits_inst.translate_nocase(*position) == what)) + { + ++position; + } + } + else + { + while(--desired && (traits_inst.translate(*position) == what)) + { + ++position; + } + } + count = count - desired; + } + else + { + count = 0; + desired = greedy ? rep->max : rep->min; + while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what)) + { + ++position; + ++count; + } + } + if((rep->leading) && (count < rep->max) && greedy) + restart = position; + if(count < rep->min) + return false; + + if(greedy) + return backtrack_till_match(count - rep->min); + + // non-greedy, keep trying till we get a match: + BidiIterator save_pos; + do + { + while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip)) + { + if((traits_inst.translate(*position, icase) == what)) + { + ++position; + ++count; + } + else + return false; // counldn't repeat even though it was the only option + } + if((rep->leading) && (rep->max == UINT_MAX)) + restart = position; + pstate = rep->alt.p; + save_pos = position; + ++state_count; + if(match_all_states()) + return true; + if((count >= rep->max) || !m_can_backtrack) + return false; + position = save_pos; + if(position == last) + return false; + if(traits_inst.translate(*position, icase) == what) + { + ++position; + ++count; + } + else + { + return false; + } + }while(true); +#ifdef BOOST_BORLANDC +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_set_repeat() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif +#ifdef BOOST_BORLANDC +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + const re_repeat* rep = static_cast(pstate); + const unsigned char* map = static_cast(rep->next.p)->_map; + std::size_t count = 0; + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t desired = greedy ? rep->max : rep->min; + if(::boost::is_random_access_iterator::value) + { + BidiIterator end = position; + // Move end forward by "desired", preferably without using distance or advance if we can + // as these can be slow for some iterator types. + std::size_t len = (desired == (std::numeric_limits::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last); + if(desired >= len) + end = last; + else + std::advance(end, desired); + BidiIterator origin(position); + while((position != end) && map[static_cast(traits_inst.translate(*position, icase))]) + { + ++position; + } + count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position); + } + else + { + while((count < desired) && (position != last) && map[static_cast(traits_inst.translate(*position, icase))]) + { + ++position; + ++count; + } + } + if((rep->leading) && (count < rep->max) && greedy) + restart = position; + if(count < rep->min) + return false; + + if(greedy) + return backtrack_till_match(count - rep->min); + + // non-greedy, keep trying till we get a match: + BidiIterator save_pos; + do + { + while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip)) + { + if(map[static_cast(traits_inst.translate(*position, icase))]) + { + ++position; + ++count; + } + else + return false; // counldn't repeat even though it was the only option + } + if((rep->leading) && (rep->max == UINT_MAX)) + restart = position; + pstate = rep->alt.p; + save_pos = position; + ++state_count; + if(match_all_states()) + return true; + if((count >= rep->max) || !m_can_backtrack) + return false; + position = save_pos; + if(position == last) + return false; + if(map[static_cast(traits_inst.translate(*position, icase))]) + { + ++position; + ++count; + } + else + { + return false; + } + }while(true); +#ifdef BOOST_BORLANDC +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_long_set_repeat() +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif +#ifdef BOOST_BORLANDC +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + typedef typename traits::char_class_type char_class_type; + const re_repeat* rep = static_cast(pstate); + const re_set_long* set = static_cast*>(pstate->next.p); + std::size_t count = 0; + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t desired = greedy ? rep->max : rep->min; + if(::boost::is_random_access_iterator::value) + { + BidiIterator end = position; + // Move end forward by "desired", preferably without using distance or advance if we can + // as these can be slow for some iterator types. + std::size_t len = (desired == (std::numeric_limits::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last); + if(desired >= len) + end = last; + else + std::advance(end, desired); + BidiIterator origin(position); + while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase))) + { + ++position; + } + count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position); + } + else + { + while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase))) + { + ++position; + ++count; + } + } + if((rep->leading) && (count < rep->max) && greedy) + restart = position; + if(count < rep->min) + return false; + + if(greedy) + return backtrack_till_match(count - rep->min); + + // non-greedy, keep trying till we get a match: + BidiIterator save_pos; + do + { + while((position != last) && (count < rep->max) && !can_start(*position, rep->_map, mask_skip)) + { + if(position != re_is_set_member(position, last, set, re.get_data(), icase)) + { + ++position; + ++count; + } + else + return false; // counldn't repeat even though it was the only option + } + if((rep->leading) && (rep->max == UINT_MAX)) + restart = position; + pstate = rep->alt.p; + save_pos = position; + ++state_count; + if(match_all_states()) + return true; + if((count >= rep->max) || !m_can_backtrack) + return false; + position = save_pos; + if(position == last) + return false; + if(position != re_is_set_member(position, last, set, re.get_data(), icase)) + { + ++position; + ++count; + } + else + { + return false; + } + }while(true); +#ifdef BOOST_BORLANDC +#pragma option pop +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::backtrack_till_match(std::size_t count) +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + if(!m_can_backtrack) + return false; + if((m_match_flags & match_partial) && (position == last)) + m_has_partial_match = true; + + const re_repeat* rep = static_cast(pstate); + BidiIterator backtrack = position; + if(position == last) + { + if(rep->can_be_null & mask_skip) + { + pstate = rep->alt.p; + if(match_all_states()) + return true; + } + if(count) + { + position = --backtrack; + --count; + } + else + return false; + } + do + { + while(count && !can_start(*position, rep->_map, mask_skip)) + { + --position; + --count; + ++state_count; + } + pstate = rep->alt.p; + backtrack = position; + if(match_all_states()) + return true; + if(count == 0) + return false; + position = --backtrack; + ++state_count; + --count; + }while(true); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_recursion() +{ + BOOST_REGEX_ASSERT(pstate->type == syntax_element_recurse); + // + // Set new call stack: + // + if(recursion_stack.capacity() == 0) + { + recursion_stack.reserve(50); + } + // + // See if we've seen this recursion before at this location, if we have then + // we need to prevent infinite recursion: + // + for(typename std::vector >::reverse_iterator i = recursion_stack.rbegin(); i != recursion_stack.rend(); ++i) + { + if(i->idx == static_cast(static_cast(pstate)->alt.p)->index) + { + if(i->location_of_start == position) + return false; + break; + } + } + // + // Now get on with it: + // + recursion_stack.push_back(recursion_info()); + recursion_stack.back().preturn_address = pstate->next.p; + recursion_stack.back().results = *m_presult; + recursion_stack.back().repeater_stack = next_count; + recursion_stack.back().location_of_start = position; + pstate = static_cast(pstate)->alt.p; + recursion_stack.back().idx = static_cast(pstate)->index; + + repeater_count* saved = next_count; + repeater_count r(&next_count); // resets all repeat counts since we're recursing and starting fresh on those + next_count = &r; + bool can_backtrack = m_can_backtrack; + bool result = match_all_states(); + m_can_backtrack = can_backtrack; + next_count = saved; + + if(!result) + { + next_count = recursion_stack.back().repeater_stack; + *m_presult = recursion_stack.back().results; + recursion_stack.pop_back(); + return false; + } + return true; +} + +template +bool perl_matcher::match_endmark() +{ + int index = static_cast(pstate)->index; + icase = static_cast(pstate)->icase; + if(index > 0) + { + if((m_match_flags & match_nosubs) == 0) + { + m_presult->set_second(position, index); + } + if(!recursion_stack.empty()) + { + if(index == recursion_stack.back().idx) + { + recursion_info saved = recursion_stack.back(); + recursion_stack.pop_back(); + pstate = saved.preturn_address; + repeater_count* saved_count = next_count; + next_count = saved.repeater_stack; + *m_presult = saved.results; + if(!match_all_states()) + { + recursion_stack.push_back(saved); + next_count = saved_count; + return false; + } + } + } + } + else if((index < 0) && (index != -4)) + { + // matched forward lookahead: + pstate = 0; + return true; + } + pstate = pstate ? pstate->next.p : 0; + return true; +} + +template +bool perl_matcher::match_match() +{ + if(!recursion_stack.empty()) + { + BOOST_REGEX_ASSERT(0 == recursion_stack.back().idx); + const re_syntax_base* saved_state = pstate = recursion_stack.back().preturn_address; + *m_presult = recursion_stack.back().results; + recursion_stack.pop_back(); + if(!match_all_states()) + { + recursion_stack.push_back(recursion_info()); + recursion_stack.back().preturn_address = saved_state; + recursion_stack.back().results = *m_presult; + recursion_stack.back().location_of_start = position; + return false; + } + return true; + } + if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first)) + return false; + if((m_match_flags & match_all) && (position != last)) + return false; + if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base)) + return false; + m_presult->set_second(position); + pstate = 0; + m_has_found_match = true; + if((m_match_flags & match_posix) == match_posix) + { + m_result.maybe_assign(*m_presult); + if((m_match_flags & match_any) == 0) + return false; + } +#ifdef BOOST_REGEX_MATCH_EXTRA + if(match_extra & m_match_flags) + { + for(unsigned i = 0; i < m_presult->size(); ++i) + if((*m_presult)[i].matched) + ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]); + } +#endif + return true; +} + +template +bool perl_matcher::match_commit() +{ + m_can_backtrack = false; + int action = static_cast(pstate)->action; + switch(action) + { + case commit_commit: + restart = last; + break; + case commit_skip: + restart = position; + break; + } + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_then() +{ + pstate = pstate->next.p; + if(match_all_states()) + return true; + m_can_backtrack = false; + m_have_then = true; + return false; +} + +template +bool perl_matcher::match_toggle_case() +{ + // change our case sensitivity: + bool oldcase = this->icase; + this->icase = static_cast(pstate)->icase; + pstate = pstate->next.p; + bool result = match_all_states(); + this->icase = oldcase; + return result; +} + + + +template +bool perl_matcher::skip_until_paren(int index, bool have_match) +{ + while(pstate) + { + if(pstate->type == syntax_element_endmark) + { + if(static_cast(pstate)->index == index) + { + if(have_match) + return this->match_endmark(); + pstate = pstate->next.p; + return true; + } + else + { + // Unenclosed closing ), occurs when (*ACCEPT) is inside some other + // parenthesis which may or may not have other side effects associated with it. + bool r = match_endmark(); + m_have_accept = true; + if(!pstate) + return r; + } + continue; + } + else if(pstate->type == syntax_element_match) + return true; + else if(pstate->type == syntax_element_startmark) + { + int idx = static_cast(pstate)->index; + pstate = pstate->next.p; + skip_until_paren(idx, false); + continue; + } + pstate = pstate->next.p; + } + return true; +} + + +} // namespace BOOST_REGEX_DETAIL_NS +} // namespace boost +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif + diff --git a/boost/regex/v4/primary_transform.hpp b/boost/regex/v4/primary_transform.hpp new file mode 100644 index 00000000..47d172aa --- /dev/null +++ b/boost/regex/v4/primary_transform.hpp @@ -0,0 +1,146 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE: primary_transform.hpp + * VERSION: see + * DESCRIPTION: Heuristically determines the sort string format in use + * by the current locale. + */ + +#ifndef BOOST_REGEX_PRIMARY_TRANSFORM +#define BOOST_REGEX_PRIMARY_TRANSFORM + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +namespace boost{ + namespace BOOST_REGEX_DETAIL_NS{ + + +enum{ + sort_C, + sort_fixed, + sort_delim, + sort_unknown +}; + +template +unsigned count_chars(const S& s, charT c) +{ + // + // Count how many occurrences of character c occur + // in string s: if c is a delimeter between collation + // fields, then this should be the same value for all + // sort keys: + // + unsigned int count = 0; + for(unsigned pos = 0; pos < s.size(); ++pos) + { + if(s[pos] == c) ++count; + } + return count; +} + + +template +unsigned find_sort_syntax(const traits* pt, charT* delim) +{ + // + // compare 'a' with 'A' to see how similar they are, + // should really use a-accute but we can't portably do that, + // + typedef typename traits::string_type string_type; + typedef typename traits::char_type char_type; + + // Suppress incorrect warning for MSVC + (void)pt; + + char_type a[2] = {'a', '\0', }; + string_type sa(pt->transform(a, a+1)); + if(sa == a) + { + *delim = 0; + return sort_C; + } + char_type A[2] = { 'A', '\0', }; + string_type sA(pt->transform(A, A+1)); + char_type c[2] = { ';', '\0', }; + string_type sc(pt->transform(c, c+1)); + + int pos = 0; + while((pos <= static_cast(sa.size())) && (pos <= static_cast(sA.size())) && (sa[pos] == sA[pos])) ++pos; + --pos; + if(pos < 0) + { + *delim = 0; + return sort_unknown; + } + // + // at this point sa[pos] is either the end of a fixed width field + // or the character that acts as a delimiter: + // + charT maybe_delim = sa[pos]; + if((pos != 0) && (count_chars(sa, maybe_delim) == count_chars(sA, maybe_delim)) && (count_chars(sa, maybe_delim) == count_chars(sc, maybe_delim))) + { + *delim = maybe_delim; + return sort_delim; + } + // + // OK doen't look like a delimiter, try for fixed width field: + // + if((sa.size() == sA.size()) && (sa.size() == sc.size())) + { + // note assumes that the fixed width field is less than + // (numeric_limits::max)(), should be true for all types + // I can't imagine 127 character fields... + *delim = static_cast(++pos); + return sort_fixed; + } + // + // don't know what it is: + // + *delim = 0; + return sort_unknown; +} + + + } // namespace BOOST_REGEX_DETAIL_NS +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif + + + + + + + diff --git a/boost/regex/v4/protected_call.hpp b/boost/regex/v4/protected_call.hpp new file mode 100644 index 00000000..451b2e34 --- /dev/null +++ b/boost/regex/v4/protected_call.hpp @@ -0,0 +1,83 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE basic_regex_creator.cpp + * VERSION see + * DESCRIPTION: Declares template class basic_regex_creator which fills in + * the data members of a regex_data object. + */ + +#ifndef BOOST_REGEX_V4_PROTECTED_CALL_HPP +#define BOOST_REGEX_V4_PROTECTED_CALL_HPP + +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +class BOOST_REGEX_DECL abstract_protected_call +{ +public: + bool BOOST_REGEX_CALL execute()const; + // this stops gcc-4 from complaining: + virtual ~abstract_protected_call(){} +private: + virtual bool call()const = 0; +}; + +template +class concrete_protected_call + : public abstract_protected_call +{ +public: + typedef bool (T::*proc_type)(); + concrete_protected_call(T* o, proc_type p) + : obj(o), proc(p) {} +private: + bool call()const BOOST_OVERRIDE; + T* obj; + proc_type proc; +}; + +template +bool concrete_protected_call::call()const +{ + return (obj->*proc)(); +} + +} +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif diff --git a/boost/regex/v4/regbase.hpp b/boost/regex/v4/regbase.hpp new file mode 100644 index 00000000..2b737d5a --- /dev/null +++ b/boost/regex/v4/regbase.hpp @@ -0,0 +1,180 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regbase.cpp + * VERSION see + * DESCRIPTION: Declares class regbase. + */ + +#ifndef BOOST_REGEX_V4_REGBASE_HPP +#define BOOST_REGEX_V4_REGBASE_HPP + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +namespace boost{ +// +// class regbase +// handles error codes and flags +// +class BOOST_REGEX_DECL regbase +{ +public: + enum flag_type_ + { + // + // Divide the flags up into logical groups: + // bits 0-7 indicate main synatx type. + // bits 8-15 indicate syntax subtype. + // bits 16-31 indicate options that are common to all + // regex syntaxes. + // In all cases the default is 0. + // + // Main synatx group: + // + perl_syntax_group = 0, // default + basic_syntax_group = 1, // POSIX basic + literal = 2, // all characters are literals + main_option_type = literal | basic_syntax_group | perl_syntax_group, // everything! + // + // options specific to perl group: + // + no_bk_refs = 1 << 8, // \d not allowed + no_perl_ex = 1 << 9, // disable perl extensions + no_mod_m = 1 << 10, // disable Perl m modifier + mod_x = 1 << 11, // Perl x modifier + mod_s = 1 << 12, // force s modifier on (overrides match_not_dot_newline) + no_mod_s = 1 << 13, // force s modifier off (overrides match_not_dot_newline) + + // + // options specific to basic group: + // + no_char_classes = 1 << 8, // [[:CLASS:]] not allowed + no_intervals = 1 << 9, // {x,y} not allowed + bk_plus_qm = 1 << 10, // uses \+ and \? + bk_vbar = 1 << 11, // use \| for alternatives + emacs_ex = 1 << 12, // enables emacs extensions + + // + // options common to all groups: + // + no_escape_in_lists = 1 << 16, // '\' not special inside [...] + newline_alt = 1 << 17, // \n is the same as | + no_except = 1 << 18, // no exception on error + failbit = 1 << 19, // error flag + icase = 1 << 20, // characters are matched regardless of case + nocollate = 0, // don't use locale specific collation (deprecated) + collate = 1 << 21, // use locale specific collation + nosubs = 1 << 22, // don't mark sub-expressions + save_subexpression_location = 1 << 23, // save subexpression locations + no_empty_expressions = 1 << 24, // no empty expressions allowed + optimize = 0, // not really supported + + + + basic = basic_syntax_group | collate | no_escape_in_lists, + extended = no_bk_refs | collate | no_perl_ex | no_escape_in_lists, + normal = 0, + emacs = basic_syntax_group | collate | emacs_ex | bk_vbar, + awk = no_bk_refs | collate | no_perl_ex, + grep = basic | newline_alt, + egrep = extended | newline_alt, + sed = basic, + perl = normal, + ECMAScript = normal, + JavaScript = normal, + JScript = normal + }; + typedef unsigned int flag_type; + + enum restart_info + { + restart_any = 0, + restart_word = 1, + restart_line = 2, + restart_buf = 3, + restart_continue = 4, + restart_lit = 5, + restart_fixed_lit = 6, + restart_count = 7 + }; +}; + +// +// provide std lib proposal compatible constants: +// +namespace regex_constants{ + + enum flag_type_ + { + + no_except = ::boost::regbase::no_except, + failbit = ::boost::regbase::failbit, + literal = ::boost::regbase::literal, + icase = ::boost::regbase::icase, + nocollate = ::boost::regbase::nocollate, + collate = ::boost::regbase::collate, + nosubs = ::boost::regbase::nosubs, + optimize = ::boost::regbase::optimize, + bk_plus_qm = ::boost::regbase::bk_plus_qm, + bk_vbar = ::boost::regbase::bk_vbar, + no_intervals = ::boost::regbase::no_intervals, + no_char_classes = ::boost::regbase::no_char_classes, + no_escape_in_lists = ::boost::regbase::no_escape_in_lists, + no_mod_m = ::boost::regbase::no_mod_m, + mod_x = ::boost::regbase::mod_x, + mod_s = ::boost::regbase::mod_s, + no_mod_s = ::boost::regbase::no_mod_s, + save_subexpression_location = ::boost::regbase::save_subexpression_location, + no_empty_expressions = ::boost::regbase::no_empty_expressions, + + basic = ::boost::regbase::basic, + extended = ::boost::regbase::extended, + normal = ::boost::regbase::normal, + emacs = ::boost::regbase::emacs, + awk = ::boost::regbase::awk, + grep = ::boost::regbase::grep, + egrep = ::boost::regbase::egrep, + sed = basic, + perl = normal, + ECMAScript = normal, + JavaScript = normal, + JScript = normal + }; + typedef ::boost::regbase::flag_type syntax_option_type; + +} // namespace regex_constants + +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif + diff --git a/boost/regex/v4/regex.hpp b/boost/regex/v4/regex.hpp new file mode 100644 index 00000000..e8ce7e5e --- /dev/null +++ b/boost/regex/v4/regex.hpp @@ -0,0 +1,166 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex.cpp + * VERSION see + * DESCRIPTION: Declares boost::basic_regex<> and associated + * functions and classes. This header is the main + * entry point for the template regex code. + */ + +#ifndef BOOST_RE_REGEX_HPP_INCLUDED +#define BOOST_RE_REGEX_HPP_INCLUDED + +#ifdef __cplusplus + +// what follows is all C++ don't include in C builds!! + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif +#ifndef BOOST_REGEX_WORKAROUND_HPP +#include +#endif + +#ifndef BOOST_REGEX_FWD_HPP +#include +#endif +#ifndef BOOST_REGEX_TRAITS_HPP +#include +#endif +#ifndef BOOST_REGEX_RAW_BUFFER_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_MATCH_FLAGS +#include +#endif +#ifndef BOOST_REGEX_RAW_BUFFER_HPP +#include +#endif +#ifndef BOOST_RE_PAT_EXCEPT_HPP +#include +#endif + +#ifndef BOOST_REGEX_V4_CHAR_REGEX_TRAITS_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_STATES_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_REGBASE_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_ITERATOR_TRAITS_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_BASIC_REGEX_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_BASIC_REGEX_CREATOR_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_BASIC_REGEX_PARSER_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_SUB_MATCH_HPP +#include +#endif +#ifndef BOOST_REGEX_FORMAT_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_MATCH_RESULTS_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_PROTECTED_CALL_HPP +#include +#endif +#ifndef BOOST_REGEX_MATCHER_HPP +#include +#endif + + +namespace boost{ +#ifdef BOOST_REGEX_NO_FWD +typedef basic_regex > regex; +#ifndef BOOST_NO_WREGEX +typedef basic_regex > wregex; +#endif +#endif + +typedef match_results cmatch; +typedef match_results smatch; +#ifndef BOOST_NO_WREGEX +typedef match_results wcmatch; +typedef match_results wsmatch; +#endif + +} // namespace boost +#ifndef BOOST_REGEX_MATCH_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_REGEX_SEARCH_HPP +#include +#endif +#ifndef BOOST_REGEX_ITERATOR_HPP +#include +#endif +#ifndef BOOST_REGEX_TOKEN_ITERATOR_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_REGEX_GREP_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_REGEX_REPLACE_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_REGEX_MERGE_HPP +#include +#endif +#ifndef BOOST_REGEX_SPLIT_HPP +#include +#endif + +#endif // __cplusplus + +#endif // include + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/boost/regex/v4/regex_format.hpp b/boost/regex/v4/regex_format.hpp new file mode 100644 index 00000000..9401fa30 --- /dev/null +++ b/boost/regex/v4/regex_format.hpp @@ -0,0 +1,1158 @@ +/* + * + * Copyright (c) 1998-2009 John Maddock + * Copyright 2008 Eric Niebler. + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_format.hpp + * VERSION see + * DESCRIPTION: Provides formatting output routines for search and replace + * operations. Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_FORMAT_HPP +#define BOOST_REGEX_FORMAT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef BOOST_NO_SFINAE +#include +#endif +#include + +namespace boost{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +// +// Forward declaration: +// + template >::allocator_type > +class match_results; + +namespace BOOST_REGEX_DETAIL_NS{ + +// +// struct trivial_format_traits: +// defines minimum localisation support for formatting +// in the case that the actual regex traits is unavailable. +// +template +struct trivial_format_traits +{ + typedef charT char_type; + + static std::ptrdiff_t length(const charT* p) + { + return global_length(p); + } + static charT tolower(charT c) + { + return ::boost::BOOST_REGEX_DETAIL_NS::global_lower(c); + } + static charT toupper(charT c) + { + return ::boost::BOOST_REGEX_DETAIL_NS::global_upper(c); + } + static int value(const charT c, int radix) + { + int result = global_value(c); + return result >= radix ? -1 : result; + } + int toi(const charT*& p1, const charT* p2, int radix)const + { + return (int)global_toi(p1, p2, radix, *this); + } +}; + +#ifdef BOOST_MSVC +# pragma warning(push) +#pragma warning(disable:26812) +#endif +template +class basic_regex_formatter +{ +public: + typedef typename traits::char_type char_type; + basic_regex_formatter(OutputIterator o, const Results& r, const traits& t) + : m_traits(t), m_results(r), m_out(o), m_position(), m_end(), m_flags(), m_state(output_copy), m_restore_state(output_copy), m_have_conditional(false) {} + OutputIterator format(ForwardIter p1, ForwardIter p2, match_flag_type f); + OutputIterator format(ForwardIter p1, match_flag_type f) + { + return format(p1, p1 + m_traits.length(p1), f); + } +private: + typedef typename Results::value_type sub_match_type; + enum output_state + { + output_copy, + output_next_lower, + output_next_upper, + output_lower, + output_upper, + output_none + }; + + void put(char_type c); + void put(const sub_match_type& sub); + void format_all(); + void format_perl(); + void format_escape(); + void format_conditional(); + void format_until_scope_end(); + bool handle_perl_verb(bool have_brace); + + inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const mpl::false_&) + { + std::vector v(i, j); + return (i != j) ? this->m_results.named_subexpression(&v[0], &v[0] + v.size()) + : this->m_results.named_subexpression(static_cast(0), static_cast(0)); + } + inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const mpl::true_&) + { + return this->m_results.named_subexpression(i, j); + } + inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j) + { + typedef typename boost::is_convertible::type tag_type; + return get_named_sub(i, j, tag_type()); + } + inline int get_named_sub_index(ForwardIter i, ForwardIter j, const mpl::false_&) + { + std::vector v(i, j); + return (i != j) ? this->m_results.named_subexpression_index(&v[0], &v[0] + v.size()) + : this->m_results.named_subexpression_index(static_cast(0), static_cast(0)); + } + inline int get_named_sub_index(ForwardIter i, ForwardIter j, const mpl::true_&) + { + return this->m_results.named_subexpression_index(i, j); + } + inline int get_named_sub_index(ForwardIter i, ForwardIter j) + { + typedef typename boost::is_convertible::type tag_type; + return get_named_sub_index(i, j, tag_type()); + } +#ifdef BOOST_MSVC + // msvc-8.0 issues a spurious warning on the call to std::advance here: +#pragma warning(push) +#pragma warning(disable:4244) +#endif + inline int toi(ForwardIter& i, ForwardIter j, int base, const boost::mpl::false_&) + { + if(i != j) + { + std::vector v(i, j); + const char_type* start = &v[0]; + const char_type* pos = start; + int r = (int)m_traits.toi(pos, &v[0] + v.size(), base); + std::advance(i, pos - start); + return r; + } + return -1; + } +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + inline int toi(ForwardIter& i, ForwardIter j, int base, const boost::mpl::true_&) + { + return m_traits.toi(i, j, base); + } + inline int toi(ForwardIter& i, ForwardIter j, int base) + { +#if defined(_MSC_VER) && defined(__INTEL_COMPILER) && ((__INTEL_COMPILER == 9999) || (__INTEL_COMPILER == 1210)) + // Workaround for Intel support issue #656654. + // See also https://svn.boost.org/trac/boost/ticket/6359 + return toi(i, j, base, mpl::false_()); +#else + typedef typename boost::is_convertible::type tag_type; + return toi(i, j, base, tag_type()); +#endif + } + + const traits& m_traits; // the traits class for localised formatting operations + const Results& m_results; // the match_results being used. + OutputIterator m_out; // where to send output. + ForwardIter m_position; // format string, current position + ForwardIter m_end; // format string end + match_flag_type m_flags; // format flags to use + output_state m_state; // what to do with the next character + output_state m_restore_state; // what state to restore to. + bool m_have_conditional; // we are parsing a conditional +private: + basic_regex_formatter(const basic_regex_formatter&); + basic_regex_formatter& operator=(const basic_regex_formatter&); +}; +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +template +OutputIterator basic_regex_formatter::format(ForwardIter p1, ForwardIter p2, match_flag_type f) +{ + m_position = p1; + m_end = p2; + m_flags = f; + format_all(); + return m_out; +} + +template +void basic_regex_formatter::format_all() +{ + // over and over: + while(m_position != m_end) + { + switch(*m_position) + { + case '&': + if(m_flags & ::boost::regex_constants::format_sed) + { + ++m_position; + put(m_results[0]); + break; + } + put(*m_position++); + break; + case '\\': + format_escape(); + break; + case '(': + if(m_flags & boost::regex_constants::format_all) + { + ++m_position; + bool have_conditional = m_have_conditional; + m_have_conditional = false; + format_until_scope_end(); + m_have_conditional = have_conditional; + if(m_position == m_end) + return; + BOOST_REGEX_ASSERT(*m_position == static_cast(')')); + ++m_position; // skip the closing ')' + break; + } + put(*m_position); + ++m_position; + break; + case ')': + if(m_flags & boost::regex_constants::format_all) + { + return; + } + put(*m_position); + ++m_position; + break; + case ':': + if((m_flags & boost::regex_constants::format_all) && m_have_conditional) + { + return; + } + put(*m_position); + ++m_position; + break; + case '?': + if(m_flags & boost::regex_constants::format_all) + { + ++m_position; + format_conditional(); + break; + } + put(*m_position); + ++m_position; + break; + case '$': + if((m_flags & format_sed) == 0) + { + format_perl(); + break; + } + // not a special character: + BOOST_FALLTHROUGH; + default: + put(*m_position); + ++m_position; + break; + } + } +} + +template +void basic_regex_formatter::format_perl() +{ + // + // On entry *m_position points to a '$' character + // output the information that goes with it: + // + BOOST_REGEX_ASSERT(*m_position == '$'); + // + // see if this is a trailing '$': + // + if(++m_position == m_end) + { + --m_position; + put(*m_position); + ++m_position; + return; + } + // + // OK find out what kind it is: + // + bool have_brace = false; + ForwardIter save_position = m_position; + switch(*m_position) + { + case '&': + ++m_position; + put(this->m_results[0]); + break; + case '`': + ++m_position; + put(this->m_results.prefix()); + break; + case '\'': + ++m_position; + put(this->m_results.suffix()); + break; + case '$': + put(*m_position++); + break; + case '+': + if((++m_position != m_end) && (*m_position == '{')) + { + ForwardIter base = ++m_position; + while((m_position != m_end) && (*m_position != '}')) ++m_position; + if(m_position != m_end) + { + // Named sub-expression: + put(get_named_sub(base, m_position)); + ++m_position; + break; + } + else + { + m_position = --base; + } + } + put((this->m_results)[this->m_results.size() > 1 ? static_cast(this->m_results.size() - 1) : 1]); + break; + case '{': + have_brace = true; + ++m_position; + BOOST_FALLTHROUGH; + default: + // see if we have a number: + { + std::ptrdiff_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end); + //len = (std::min)(static_cast(2), len); + int v = this->toi(m_position, m_position + len, 10); + if((v < 0) || (have_brace && ((m_position == m_end) || (*m_position != '}')))) + { + // Look for a Perl-5.10 verb: + if(!handle_perl_verb(have_brace)) + { + // leave the $ as is, and carry on: + m_position = --save_position; + put(*m_position); + ++m_position; + } + break; + } + // otherwise output sub v: + put(this->m_results[v]); + if(have_brace) + ++m_position; + } + } +} + +template +bool basic_regex_formatter::handle_perl_verb(bool have_brace) +{ + // + // We may have a capitalised string containing a Perl action: + // + static const char_type MATCH[] = { 'M', 'A', 'T', 'C', 'H' }; + static const char_type PREMATCH[] = { 'P', 'R', 'E', 'M', 'A', 'T', 'C', 'H' }; + static const char_type POSTMATCH[] = { 'P', 'O', 'S', 'T', 'M', 'A', 'T', 'C', 'H' }; + static const char_type LAST_PAREN_MATCH[] = { 'L', 'A', 'S', 'T', '_', 'P', 'A', 'R', 'E', 'N', '_', 'M', 'A', 'T', 'C', 'H' }; + static const char_type LAST_SUBMATCH_RESULT[] = { 'L', 'A', 'S', 'T', '_', 'S', 'U', 'B', 'M', 'A', 'T', 'C', 'H', '_', 'R', 'E', 'S', 'U', 'L', 'T' }; + static const char_type LAST_SUBMATCH_RESULT_ALT[] = { '^', 'N' }; + + if(m_position == m_end) + return false; + if(have_brace && (*m_position == '^')) + ++m_position; + + std::ptrdiff_t max_len = m_end - m_position; + + if((max_len >= 5) && std::equal(m_position, m_position + 5, MATCH)) + { + m_position += 5; + if(have_brace) + { + if((m_position != m_end) && (*m_position == '}')) + ++m_position; + else + { + m_position -= 5; + return false; + } + } + put(this->m_results[0]); + return true; + } + if((max_len >= 8) && std::equal(m_position, m_position + 8, PREMATCH)) + { + m_position += 8; + if(have_brace) + { + if((m_position != m_end) && (*m_position == '}')) + ++m_position; + else + { + m_position -= 8; + return false; + } + } + put(this->m_results.prefix()); + return true; + } + if((max_len >= 9) && std::equal(m_position, m_position + 9, POSTMATCH)) + { + m_position += 9; + if(have_brace) + { + if((m_position != m_end) && (*m_position == '}')) + ++m_position; + else + { + m_position -= 9; + return false; + } + } + put(this->m_results.suffix()); + return true; + } + if((max_len >= 16) && std::equal(m_position, m_position + 16, LAST_PAREN_MATCH)) + { + m_position += 16; + if(have_brace) + { + if((m_position != m_end) && (*m_position == '}')) + ++m_position; + else + { + m_position -= 16; + return false; + } + } + put((this->m_results)[this->m_results.size() > 1 ? static_cast(this->m_results.size() - 1) : 1]); + return true; + } + if((max_len >= 20) && std::equal(m_position, m_position + 20, LAST_SUBMATCH_RESULT)) + { + m_position += 20; + if(have_brace) + { + if((m_position != m_end) && (*m_position == '}')) + ++m_position; + else + { + m_position -= 20; + return false; + } + } + put(this->m_results.get_last_closed_paren()); + return true; + } + if((max_len >= 2) && std::equal(m_position, m_position + 2, LAST_SUBMATCH_RESULT_ALT)) + { + m_position += 2; + if(have_brace) + { + if((m_position != m_end) && (*m_position == '}')) + ++m_position; + else + { + m_position -= 2; + return false; + } + } + put(this->m_results.get_last_closed_paren()); + return true; + } + return false; +} + +template +void basic_regex_formatter::format_escape() +{ + // skip the escape and check for trailing escape: + if(++m_position == m_end) + { + put(static_cast('\\')); + return; + } + // now switch on the escape type: + switch(*m_position) + { + case 'a': + put(static_cast('\a')); + ++m_position; + break; + case 'f': + put(static_cast('\f')); + ++m_position; + break; + case 'n': + put(static_cast('\n')); + ++m_position; + break; + case 'r': + put(static_cast('\r')); + ++m_position; + break; + case 't': + put(static_cast('\t')); + ++m_position; + break; + case 'v': + put(static_cast('\v')); + ++m_position; + break; + case 'x': + if(++m_position == m_end) + { + put(static_cast('x')); + return; + } + // maybe have \x{ddd} + if(*m_position == static_cast('{')) + { + ++m_position; + int val = this->toi(m_position, m_end, 16); + if(val < 0) + { + // invalid value treat everything as literals: + put(static_cast('x')); + put(static_cast('{')); + return; + } + if((m_position == m_end) || (*m_position != static_cast('}'))) + { + --m_position; + while(*m_position != static_cast('\\')) + --m_position; + ++m_position; + put(*m_position++); + return; + } + ++m_position; + put(static_cast(val)); + return; + } + else + { + std::ptrdiff_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end); + len = (std::min)(static_cast(2), len); + int val = this->toi(m_position, m_position + len, 16); + if(val < 0) + { + --m_position; + put(*m_position++); + return; + } + put(static_cast(val)); + } + break; + case 'c': + if(++m_position == m_end) + { + --m_position; + put(*m_position++); + return; + } + put(static_cast(*m_position++ % 32)); + break; + case 'e': + put(static_cast(27)); + ++m_position; + break; + default: + // see if we have a perl specific escape: + if((m_flags & boost::regex_constants::format_sed) == 0) + { + bool breakout = false; + switch(*m_position) + { + case 'l': + ++m_position; + m_restore_state = m_state; + m_state = output_next_lower; + breakout = true; + break; + case 'L': + ++m_position; + m_state = output_lower; + breakout = true; + break; + case 'u': + ++m_position; + m_restore_state = m_state; + m_state = output_next_upper; + breakout = true; + break; + case 'U': + ++m_position; + m_state = output_upper; + breakout = true; + break; + case 'E': + ++m_position; + m_state = output_copy; + breakout = true; + break; + } + if(breakout) + break; + } + // see if we have a \n sed style backreference: + std::ptrdiff_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end); + len = (std::min)(static_cast(1), len); + int v = this->toi(m_position, m_position+len, 10); + if((v > 0) || ((v == 0) && (m_flags & ::boost::regex_constants::format_sed))) + { + put(m_results[v]); + break; + } + else if(v == 0) + { + // octal ecape sequence: + --m_position; + len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end); + len = (std::min)(static_cast(4), len); + v = this->toi(m_position, m_position + len, 8); + BOOST_REGEX_ASSERT(v >= 0); + put(static_cast(v)); + break; + } + // Otherwise output the character "as is": + put(*m_position++); + break; + } +} + +template +void basic_regex_formatter::format_conditional() +{ + if(m_position == m_end) + { + // oops trailing '?': + put(static_cast('?')); + return; + } + int v; + if(*m_position == '{') + { + ForwardIter base = m_position; + ++m_position; + v = this->toi(m_position, m_end, 10); + if(v < 0) + { + // Try a named subexpression: + while((m_position != m_end) && (*m_position != '}')) + ++m_position; + v = this->get_named_sub_index(base + 1, m_position); + } + if((v < 0) || (*m_position != '}')) + { + m_position = base; + // oops trailing '?': + put(static_cast('?')); + return; + } + // Skip trailing '}': + ++m_position; + } + else + { + std::ptrdiff_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end); + len = (std::min)(static_cast(2), len); + v = this->toi(m_position, m_position + len, 10); + } + if(v < 0) + { + // oops not a number: + put(static_cast('?')); + return; + } + + // output varies depending upon whether sub-expression v matched or not: + if(m_results[v].matched) + { + m_have_conditional = true; + format_all(); + m_have_conditional = false; + if((m_position != m_end) && (*m_position == static_cast(':'))) + { + // skip the ':': + ++m_position; + // save output state, then turn it off: + output_state saved_state = m_state; + m_state = output_none; + // format the rest of this scope: + format_until_scope_end(); + // restore output state: + m_state = saved_state; + } + } + else + { + // save output state, then turn it off: + output_state saved_state = m_state; + m_state = output_none; + // format until ':' or ')': + m_have_conditional = true; + format_all(); + m_have_conditional = false; + // restore state: + m_state = saved_state; + if((m_position != m_end) && (*m_position == static_cast(':'))) + { + // skip the ':': + ++m_position; + // format the rest of this scope: + format_until_scope_end(); + } + } +} + +template +void basic_regex_formatter::format_until_scope_end() +{ + do + { + format_all(); + if((m_position == m_end) || (*m_position == static_cast(')'))) + return; + put(*m_position++); + }while(m_position != m_end); +} + +template +void basic_regex_formatter::put(char_type c) +{ + // write a single character to output + // according to which case translation mode we are in: + switch(this->m_state) + { + case output_none: + return; + case output_next_lower: + c = m_traits.tolower(c); + this->m_state = m_restore_state; + break; + case output_next_upper: + c = m_traits.toupper(c); + this->m_state = m_restore_state; + break; + case output_lower: + c = m_traits.tolower(c); + break; + case output_upper: + c = m_traits.toupper(c); + break; + default: + break; + } + *m_out = c; + ++m_out; +} + +template +void basic_regex_formatter::put(const sub_match_type& sub) +{ + typedef typename sub_match_type::iterator iterator_type; + iterator_type i = sub.first; + while(i != sub.second) + { + put(*i); + ++i; + } +} + +template +class string_out_iterator +{ + S* out; +public: + string_out_iterator(S& s) : out(&s) {} + string_out_iterator& operator++() { return *this; } + string_out_iterator& operator++(int) { return *this; } + string_out_iterator& operator*() { return *this; } + string_out_iterator& operator=(typename S::value_type v) + { + out->append(1, v); + return *this; + } + + typedef std::ptrdiff_t difference_type; + typedef typename S::value_type value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef std::output_iterator_tag iterator_category; +}; + +template +OutputIterator regex_format_imp(OutputIterator out, + const match_results& m, + ForwardIter p1, ForwardIter p2, + match_flag_type flags, + const traits& t + ) +{ + if(flags & regex_constants::format_literal) + { + return BOOST_REGEX_DETAIL_NS::copy(p1, p2, out); + } + + BOOST_REGEX_DETAIL_NS::basic_regex_formatter< + OutputIterator, + match_results, + traits, ForwardIter> f(out, m, t); + return f.format(p1, p2, flags); +} + +#ifndef BOOST_NO_SFINAE + +BOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator) + +struct any_type +{ + template + any_type(const T&); + template + any_type(const T&, const U&); + template + any_type(const T&, const U&, const V&); +}; +typedef char no_type; +typedef char (&unary_type)[2]; +typedef char (&binary_type)[3]; +typedef char (&ternary_type)[4]; + +no_type check_is_formatter(unary_type, binary_type, ternary_type); +template +unary_type check_is_formatter(T const &, binary_type, ternary_type); +template +binary_type check_is_formatter(unary_type, T const &, ternary_type); +template +binary_type check_is_formatter(T const &, U const &, ternary_type); +template +ternary_type check_is_formatter(unary_type, binary_type, T const &); +template +ternary_type check_is_formatter(T const &, binary_type, U const &); +template +ternary_type check_is_formatter(unary_type, T const &, U const &); +template +ternary_type check_is_formatter(T const &, U const &, V const &); + +struct unary_binary_ternary +{ + typedef unary_type (*unary_fun)(any_type); + typedef binary_type (*binary_fun)(any_type, any_type); + typedef ternary_type (*ternary_fun)(any_type, any_type, any_type); + operator unary_fun(); + operator binary_fun(); + operator ternary_fun(); +}; + +template::value> +struct formatter_wrapper + : Formatter + , unary_binary_ternary +{ + formatter_wrapper(){} +}; + +template +struct formatter_wrapper + : unary_binary_ternary +{ + operator Formatter *(); +}; + +template +struct formatter_wrapper + : unary_binary_ternary +{ + operator Formatter *(); +}; + +template +struct format_traits_imp +{ +private: + // + // F must be a pointer, a function, or a class with a function call operator: + // + BOOST_STATIC_ASSERT((::boost::is_pointer::value || ::boost::is_function::value || ::boost::is_class::value)); + static formatter_wrapper::type> f; + static M m; + static O out; + static boost::regex_constants::match_flag_type flags; +public: + BOOST_STATIC_CONSTANT(int, value = sizeof(check_is_formatter(f(m), f(m, out), f(m, out, flags)))); +}; + +template +struct format_traits +{ +public: + // + // Type is mpl::int_ where N is one of: + // + // 0 : F is a pointer to a presumably null-terminated string. + // 1 : F is a character-container such as a std::string. + // 2 : F is a Unary Functor. + // 3 : F is a Binary Functor. + // 4 : F is a Ternary Functor. + // + typedef typename boost::mpl::if_< + boost::mpl::and_, boost::mpl::not_::type> > >, + boost::mpl::int_<0>, + typename boost::mpl::if_< + has_const_iterator, + boost::mpl::int_<1>, + boost::mpl::int_::value> + >::type + >::type type; + // + // This static assertion will fail if the functor passed does not accept + // the same type of arguments passed. + // + BOOST_STATIC_ASSERT( boost::is_class::value && !has_const_iterator::value ? (type::value > 1) : true); +}; + +#else // BOOST_NO_SFINAE + +template +struct format_traits +{ +public: + // + // Type is mpl::int_ where N is one of: + // + // 0 : F is a pointer to a presumably null-terminated string. + // 1 : F is a character-container such as a std::string. + // + // Other options such as F being a Functor are not supported without + // SFINAE support. + // + typedef typename boost::mpl::if_< + boost::is_pointer, + boost::mpl::int_<0>, + boost::mpl::int_<1> + >::type type; +}; + +#endif // BOOST_NO_SFINAE + +template +struct format_functor3 +{ + format_functor3(Base b) : func(b) {} + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f) + { + return boost::unwrap_ref(func)(m, i, f); + } + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&) + { + return (*this)(m, i, f); + } +private: + Base func; + format_functor3(const format_functor3&); + format_functor3& operator=(const format_functor3&); +}; + +template +struct format_functor2 +{ + format_functor2(Base b) : func(b) {} + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type /*f*/) + { + return boost::unwrap_ref(func)(m, i); + } + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&) + { + return (*this)(m, i, f); + } +private: + Base func; + format_functor2(const format_functor2&); + format_functor2& operator=(const format_functor2&); +}; + +template +struct format_functor1 +{ + format_functor1(Base b) : func(b) {} + + template + OutputIter do_format_string(const S& s, OutputIter i) + { + return BOOST_REGEX_DETAIL_NS::copy(s.begin(), s.end(), i); + } + template + inline OutputIter do_format_string(const S* s, OutputIter i) + { + while(s && *s) + { + *i = *s; + ++i; + ++s; + } + return i; + } + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type /*f*/) + { + return do_format_string(boost::unwrap_ref(func)(m), i); + } + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&) + { + return (*this)(m, i, f); + } +private: + Base func; + format_functor1(const format_functor1&); + format_functor1& operator=(const format_functor1&); +}; + +template +struct format_functor_c_string +{ + format_functor_c_string(const charT* ps) : func(ps) {} + + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits& t = Traits()) + { + //typedef typename Match::char_type char_type; + const charT* end = func; + while(*end) ++end; + return regex_format_imp(i, m, func, end, f, t); + } +private: + const charT* func; + format_functor_c_string(const format_functor_c_string&); + format_functor_c_string& operator=(const format_functor_c_string&); +}; + +template +struct format_functor_container +{ + format_functor_container(const Container& c) : func(c) {} + + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits& t = Traits()) + { + //typedef typename Match::char_type char_type; + return BOOST_REGEX_DETAIL_NS::regex_format_imp(i, m, func.begin(), func.end(), f, t); + } +private: + const Container& func; + format_functor_container(const format_functor_container&); + format_functor_container& operator=(const format_functor_container&); +}; + +template > +struct compute_functor_type +{ + typedef typename format_traits::type tag; + typedef typename boost::remove_cv< typename boost::remove_pointer::type>::type maybe_char_type; + + typedef typename mpl::if_< + ::boost::is_same >, format_functor_c_string, + typename mpl::if_< + ::boost::is_same >, format_functor_container, + typename mpl::if_< + ::boost::is_same >, format_functor1, + typename mpl::if_< + ::boost::is_same >, format_functor2, + format_functor3 + >::type + >::type + >::type + >::type type; +}; + +} // namespace BOOST_REGEX_DETAIL_NS + +template +inline OutputIterator regex_format(OutputIterator out, + const match_results& m, + Functor fmt, + match_flag_type flags = format_all + ) +{ + return m.format(out, fmt, flags); +} + +template +inline std::basic_string::char_type> regex_format(const match_results& m, + Functor fmt, + match_flag_type flags = format_all) +{ + return m.format(fmt, flags); +} + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace boost + +#endif // BOOST_REGEX_FORMAT_HPP + + + + + + diff --git a/boost/regex/v4/regex_fwd.hpp b/boost/regex/v4/regex_fwd.hpp new file mode 100644 index 00000000..3076b069 --- /dev/null +++ b/boost/regex/v4/regex_fwd.hpp @@ -0,0 +1,73 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_fwd.cpp + * VERSION see + * DESCRIPTION: Forward declares boost::basic_regex<> and + * associated typedefs. + */ + +#ifndef BOOST_REGEX_FWD_HPP_INCLUDED +#define BOOST_REGEX_FWD_HPP_INCLUDED + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif + +// +// define BOOST_REGEX_NO_FWD if this +// header doesn't work! +// +#ifdef BOOST_REGEX_NO_FWD +# ifndef BOOST_RE_REGEX_HPP +# include +# endif +#else + +namespace boost{ + +template +class cpp_regex_traits; +template +struct c_regex_traits; +template +class w32_regex_traits; + +#ifdef BOOST_REGEX_USE_WIN32_LOCALE +template > +struct regex_traits; +#elif defined(BOOST_REGEX_USE_CPP_LOCALE) +template > +struct regex_traits; +#else +template > +struct regex_traits; +#endif + +template > +class basic_regex; + +typedef basic_regex > regex; +#ifndef BOOST_NO_WREGEX +typedef basic_regex > wregex; +#endif + +} // namespace boost + +#endif // BOOST_REGEX_NO_FWD + +#endif + + + + diff --git a/boost/regex/v4/regex_grep.hpp b/boost/regex/v4/regex_grep.hpp new file mode 100644 index 00000000..c5cb054e --- /dev/null +++ b/boost/regex/v4/regex_grep.hpp @@ -0,0 +1,155 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_grep.hpp + * VERSION see + * DESCRIPTION: Provides regex_grep implementation. + */ + +#ifndef BOOST_REGEX_V4_REGEX_GREP_HPP +#define BOOST_REGEX_V4_REGEX_GREP_HPP + + +namespace boost{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +// +// regex_grep: +// find all non-overlapping matches within the sequence first last: +// +template +inline unsigned int regex_grep(Predicate foo, + BidiIterator first, + BidiIterator last, + const basic_regex& e, + match_flag_type flags = match_default) +{ + if(e.flags() & regex_constants::failbit) + return false; + + typedef typename match_results::allocator_type match_allocator_type; + + match_results m; + BOOST_REGEX_DETAIL_NS::perl_matcher matcher(first, last, m, e, flags, first); + unsigned int count = 0; + while(matcher.find()) + { + ++count; + if(0 == foo(m)) + return count; // caller doesn't want to go on + if(m[0].second == last) + return count; // we've reached the end, don't try and find an extra null match. + if(m.length() == 0) + { + if(m[0].second == last) + return count; + // we found a NULL-match, now try to find + // a non-NULL one at the same position: + match_results m2(m); + matcher.setf(match_not_null | match_continuous); + if(matcher.find()) + { + ++count; + if(0 == foo(m)) + return count; + } + else + { + // reset match back to where it was: + m = m2; + } + matcher.unsetf((match_not_null | match_continuous) & ~flags); + } + } + return count; +} + +// +// regex_grep convenience interfaces: +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +// +// this isn't really a partial specialisation, but template function +// overloading - if the compiler doesn't support partial specialisation +// then it really won't support this either: +template +inline unsigned int regex_grep(Predicate foo, const charT* str, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, str, str + traits::length(str), e, flags); +} + +template +inline unsigned int regex_grep(Predicate foo, const std::basic_string& s, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, s.begin(), s.end(), e, flags); +} +#else // partial specialisation +inline unsigned int regex_grep(bool (*foo)(const cmatch&), const char* str, + const regex& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, str, str + regex::traits_type::length(str), e, flags); +} +#ifndef BOOST_NO_WREGEX +inline unsigned int regex_grep(bool (*foo)(const wcmatch&), const wchar_t* str, + const wregex& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, str, str + wregex::traits_type::length(str), e, flags); +} +#endif +inline unsigned int regex_grep(bool (*foo)(const match_results&), const std::string& s, + const regex& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, s.begin(), s.end(), e, flags); +} +#if !defined(BOOST_NO_WREGEX) +inline unsigned int regex_grep(bool (*foo)(const match_results::const_iterator>&), + const std::basic_string& s, + const wregex& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, s.begin(), s.end(), e, flags); +} +#endif +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace boost + +#endif // BOOST_REGEX_V4_REGEX_GREP_HPP + diff --git a/boost/regex/v4/regex_iterator.hpp b/boost/regex/v4/regex_iterator.hpp new file mode 100644 index 00000000..bbdeed58 --- /dev/null +++ b/boost/regex/v4/regex_iterator.hpp @@ -0,0 +1,195 @@ +/* + * + * Copyright (c) 2003 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_iterator.hpp + * VERSION see + * DESCRIPTION: Provides regex_iterator implementation. + */ + +#ifndef BOOST_REGEX_V4_REGEX_ITERATOR_HPP +#define BOOST_REGEX_V4_REGEX_ITERATOR_HPP + +#include + +namespace boost{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +template +class regex_iterator_implementation +{ + typedef basic_regex regex_type; + + match_results what; // current match + BidirectionalIterator base; // start of sequence + BidirectionalIterator end; // end of sequence + const regex_type re; // the expression + match_flag_type flags; // flags for matching + +public: + regex_iterator_implementation(const regex_type* p, BidirectionalIterator last, match_flag_type f) + : base(), end(last), re(*p), flags(f){} + regex_iterator_implementation(const regex_iterator_implementation& other) + :what(other.what), base(other.base), end(other.end), re(other.re), flags(other.flags){} + bool init(BidirectionalIterator first) + { + base = first; + return regex_search(first, end, what, re, flags); + } + bool compare(const regex_iterator_implementation& that) + { + if(this == &that) return true; + return (&re.get_data() == &that.re.get_data()) && (end == that.end) && (flags == that.flags) && (what[0].first == that.what[0].first) && (what[0].second == that.what[0].second); + } + const match_results& get() + { return what; } + bool next() + { + //if(what.prefix().first != what[0].second) + // flags |= match_prev_avail; + BidirectionalIterator next_start = what[0].second; + match_flag_type f(flags); + if(!what.length() || (f & regex_constants::match_posix)) + f |= regex_constants::match_not_initial_null; + //if(base != next_start) + // f |= regex_constants::match_not_bob; + bool result = regex_search(next_start, end, what, re, f, base); + if(result) + what.set_base(base); + return result; + } +private: + regex_iterator_implementation& operator=(const regex_iterator_implementation&); +}; + +template ::value_type, + class traits = regex_traits > +class regex_iterator +{ +private: + typedef regex_iterator_implementation impl; + typedef shared_ptr pimpl; +public: + typedef basic_regex regex_type; + typedef match_results value_type; + typedef typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::difference_type + difference_type; + typedef const value_type* pointer; + typedef const value_type& reference; + typedef std::forward_iterator_tag iterator_category; + + regex_iterator(){} + regex_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + match_flag_type m = match_default) + : pdata(new impl(&re, b, m)) + { + if(!pdata->init(a)) + { + pdata.reset(); + } + } + regex_iterator(const regex_iterator& that) + : pdata(that.pdata) {} + regex_iterator& operator=(const regex_iterator& that) + { + pdata = that.pdata; + return *this; + } + bool operator==(const regex_iterator& that)const + { + if((pdata.get() == 0) || (that.pdata.get() == 0)) + return pdata.get() == that.pdata.get(); + return pdata->compare(*(that.pdata.get())); + } + bool operator!=(const regex_iterator& that)const + { return !(*this == that); } + const value_type& operator*()const + { return pdata->get(); } + const value_type* operator->()const + { return &(pdata->get()); } + regex_iterator& operator++() + { + cow(); + if(0 == pdata->next()) + { + pdata.reset(); + } + return *this; + } + regex_iterator operator++(int) + { + regex_iterator result(*this); + ++(*this); + return result; + } +private: + + pimpl pdata; + + void cow() + { + // copy-on-write + if(pdata.get() && !pdata.unique()) + { + pdata.reset(new impl(*(pdata.get()))); + } + } +}; + +typedef regex_iterator cregex_iterator; +typedef regex_iterator sregex_iterator; +#ifndef BOOST_NO_WREGEX +typedef regex_iterator wcregex_iterator; +typedef regex_iterator wsregex_iterator; +#endif + +// make_regex_iterator: +template +inline regex_iterator make_regex_iterator(const charT* p, const basic_regex& e, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_iterator(p, p+traits::length(p), e, m); +} +template +inline regex_iterator::const_iterator, charT, traits> make_regex_iterator(const std::basic_string& p, const basic_regex& e, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_iterator::const_iterator, charT, traits>(p.begin(), p.end(), e, m); +} + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace boost + +#endif // BOOST_REGEX_V4_REGEX_ITERATOR_HPP + diff --git a/boost/regex/v4/regex_match.hpp b/boost/regex/v4/regex_match.hpp new file mode 100644 index 00000000..a50daa2a --- /dev/null +++ b/boost/regex/v4/regex_match.hpp @@ -0,0 +1,382 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_match.hpp + * VERSION see + * DESCRIPTION: Regular expression matching algorithms. + * Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + + +#ifndef BOOST_REGEX_MATCH_HPP +#define BOOST_REGEX_MATCH_HPP + +namespace boost{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +// +// proc regex_match +// returns true if the specified regular expression matches +// the whole of the input. Fills in what matched in m. +// +template +bool regex_match(BidiIterator first, BidiIterator last, + match_results& m, + const basic_regex& e, + match_flag_type flags = match_default) +{ + BOOST_REGEX_DETAIL_NS::perl_matcher matcher(first, last, m, e, flags, first); + return matcher.match(); +} +template +bool regex_match(iterator first, iterator last, + const basic_regex& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(first, last, m, e, flags | regex_constants::match_any); +} +// +// query_match convenience interfaces: +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +// +// this isn't really a partial specialisation, but template function +// overloading - if the compiler doesn't support partial specialisation +// then it really won't support this either: +template +inline bool regex_match(const charT* str, + match_results& m, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + traits::length(str), m, e, flags); +} + +template +inline bool regex_match(const std::basic_string& s, + match_results::const_iterator, Allocator>& m, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +template +inline bool regex_match(const charT* str, + const basic_regex& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(str, str + traits::length(str), m, e, flags | regex_constants::match_any); +} + +template +inline bool regex_match(const std::basic_string& s, + const basic_regex& e, + match_flag_type flags = match_default) +{ + typedef typename std::basic_string::const_iterator iterator; + match_results m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#else // partial ordering +inline bool regex_match(const char* str, + cmatch& m, + const regex& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + regex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const char* str, + const regex& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(str, str + regex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#ifndef BOOST_NO_STD_LOCALE +inline bool regex_match(const char* str, + cmatch& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + regex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const char* str, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(str, str + regex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#endif +inline bool regex_match(const char* str, + cmatch& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + regex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const char* str, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(str, str + regex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +inline bool regex_match(const char* str, + cmatch& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + regex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const char* str, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(str, str + regex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#endif +#ifndef BOOST_NO_WREGEX +inline bool regex_match(const wchar_t* str, + wcmatch& m, + const wregex& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const wchar_t* str, + const wregex& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#ifndef BOOST_NO_STD_LOCALE +inline bool regex_match(const wchar_t* str, + wcmatch& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const wchar_t* str, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#endif +inline bool regex_match(const wchar_t* str, + wcmatch& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const wchar_t* str, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +inline bool regex_match(const wchar_t* str, + wcmatch& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const wchar_t* str, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#endif +#endif +inline bool regex_match(const std::string& s, + smatch& m, + const regex& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::string& s, + const regex& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#ifndef BOOST_NO_STD_LOCALE +inline bool regex_match(const std::string& s, + smatch& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::string& s, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#endif +inline bool regex_match(const std::string& s, + smatch& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::string& s, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +inline bool regex_match(const std::string& s, + smatch& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::string& s, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#endif +#if !defined(BOOST_NO_WREGEX) +inline bool regex_match(const std::basic_string& s, + match_results::const_iterator>& m, + const wregex& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::basic_string& s, + const wregex& e, + match_flag_type flags = match_default) +{ + match_results::const_iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#ifndef BOOST_NO_STD_LOCALE +inline bool regex_match(const std::basic_string& s, + match_results::const_iterator>& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::basic_string& s, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results::const_iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#endif +inline bool regex_match(const std::basic_string& s, + match_results::const_iterator>& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::basic_string& s, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results::const_iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +inline bool regex_match(const std::basic_string& s, + match_results::const_iterator>& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::basic_string& s, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results::const_iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#endif +#endif + +#endif + + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace boost + +#endif // BOOST_REGEX_MATCH_HPP + + + + + + + + + + + + + + + + + + diff --git a/boost/regex/v4/regex_merge.hpp b/boost/regex/v4/regex_merge.hpp new file mode 100644 index 00000000..404ca775 --- /dev/null +++ b/boost/regex/v4/regex_merge.hpp @@ -0,0 +1,93 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_format.hpp + * VERSION see + * DESCRIPTION: Provides formatting output routines for search and replace + * operations. Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_V4_REGEX_MERGE_HPP +#define BOOST_REGEX_V4_REGEX_MERGE_HPP + + +namespace boost{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +template +inline OutputIterator regex_merge(OutputIterator out, + Iterator first, + Iterator last, + const basic_regex& e, + const charT* fmt, + match_flag_type flags = match_default) +{ + return regex_replace(out, first, last, e, fmt, flags); +} + +template +inline OutputIterator regex_merge(OutputIterator out, + Iterator first, + Iterator last, + const basic_regex& e, + const std::basic_string& fmt, + match_flag_type flags = match_default) +{ + return regex_merge(out, first, last, e, fmt.c_str(), flags); +} + +template +inline std::basic_string regex_merge(const std::basic_string& s, + const basic_regex& e, + const charT* fmt, + match_flag_type flags = match_default) +{ + return regex_replace(s, e, fmt, flags); +} + +template +inline std::basic_string regex_merge(const std::basic_string& s, + const basic_regex& e, + const std::basic_string& fmt, + match_flag_type flags = match_default) +{ + return regex_replace(s, e, fmt, flags); +} + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace boost + +#endif // BOOST_REGEX_V4_REGEX_MERGE_HPP + + diff --git a/boost/regex/v4/regex_raw_buffer.hpp b/boost/regex/v4/regex_raw_buffer.hpp new file mode 100644 index 00000000..ac27e1a2 --- /dev/null +++ b/boost/regex/v4/regex_raw_buffer.hpp @@ -0,0 +1,241 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_raw_buffer.hpp + * VERSION see + * DESCRIPTION: Raw character buffer for regex code. + * Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_RAW_BUFFER_HPP +#define BOOST_REGEX_RAW_BUFFER_HPP + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif + +#include +#include + +namespace boost{ + namespace BOOST_REGEX_DETAIL_NS{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +struct empty_padding{}; + +union padding +{ + void* p; + unsigned int i; +}; + +template +struct padding3 +{ + enum{ + padding_size = 8, + padding_mask = 7 + }; +}; + +template<> +struct padding3<2> +{ + enum{ + padding_size = 2, + padding_mask = 1 + }; +}; + +template<> +struct padding3<4> +{ + enum{ + padding_size = 4, + padding_mask = 3 + }; +}; + +template<> +struct padding3<8> +{ + enum{ + padding_size = 8, + padding_mask = 7 + }; +}; + +template<> +struct padding3<16> +{ + enum{ + padding_size = 16, + padding_mask = 15 + }; +}; + +enum{ + padding_size = padding3::padding_size, + padding_mask = padding3::padding_mask +}; + +// +// class raw_storage +// basically this is a simplified vector +// this is used by basic_regex for expression storage +// + +class raw_storage +{ +public: + typedef std::size_t size_type; + typedef unsigned char* pointer; +private: + pointer last, start, end; +public: + + raw_storage(); + raw_storage(size_type n); + + ~raw_storage() + { + ::operator delete(start); + } + + void BOOST_REGEX_CALL resize(size_type n) + { + size_type newsize = start ? last - start : 1024; + while (newsize < n) + newsize *= 2; + size_type datasize = end - start; + // extend newsize to WORD/DWORD boundary: + newsize = (newsize + padding_mask) & ~(padding_mask); + + // allocate and copy data: + pointer ptr = static_cast(::operator new(newsize)); + BOOST_REGEX_NOEH_ASSERT(ptr) + if (start) + std::memcpy(ptr, start, datasize); + + // get rid of old buffer: + ::operator delete(start); + + // and set up pointers: + start = ptr; + end = ptr + datasize; + last = ptr + newsize; + } + + void* BOOST_REGEX_CALL extend(size_type n) + { + if(size_type(last - end) < n) + resize(n + (end - start)); + pointer result = end; + end += n; + return result; + } + + void* BOOST_REGEX_CALL insert(size_type pos, size_type n) + { + BOOST_REGEX_ASSERT(pos <= size_type(end - start)); + if (size_type(last - end) < n) + resize(n + (end - start)); + void* result = start + pos; + std::memmove(start + pos + n, start + pos, (end - start) - pos); + end += n; + return result; + } + + size_type BOOST_REGEX_CALL size() + { + return size_type(end - start); + } + + size_type BOOST_REGEX_CALL capacity() + { + return size_type(last - start); + } + + void* BOOST_REGEX_CALL data()const + { + return start; + } + + size_type BOOST_REGEX_CALL index(void* ptr) + { + return size_type(static_cast(ptr) - static_cast(data())); + } + + void BOOST_REGEX_CALL clear() + { + end = start; + } + + void BOOST_REGEX_CALL align() + { + // move end up to a boundary: + end = start + (((end - start) + padding_mask) & ~padding_mask); + } + void swap(raw_storage& that) + { + std::swap(start, that.start); + std::swap(end, that.end); + std::swap(last, that.last); + } +}; + +inline raw_storage::raw_storage() +{ + last = start = end = 0; +} + +inline raw_storage::raw_storage(size_type n) +{ + start = end = static_cast(::operator new(n)); + BOOST_REGEX_NOEH_ASSERT(start) + last = start + n; +} + + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace BOOST_REGEX_DETAIL_NS +} // namespace boost + +#endif + + + + + + diff --git a/boost/regex/v4/regex_replace.hpp b/boost/regex/v4/regex_replace.hpp new file mode 100644 index 00000000..415c58b6 --- /dev/null +++ b/boost/regex/v4/regex_replace.hpp @@ -0,0 +1,99 @@ +/* + * + * Copyright (c) 1998-2009 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_format.hpp + * VERSION see + * DESCRIPTION: Provides formatting output routines for search and replace + * operations. Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_V4_REGEX_REPLACE_HPP +#define BOOST_REGEX_V4_REGEX_REPLACE_HPP + + +namespace boost{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +template +OutputIterator regex_replace(OutputIterator out, + BidirectionalIterator first, + BidirectionalIterator last, + const basic_regex& e, + Formatter fmt, + match_flag_type flags = match_default) +{ + regex_iterator i(first, last, e, flags); + regex_iterator j; + if(i == j) + { + if(!(flags & regex_constants::format_no_copy)) + out = BOOST_REGEX_DETAIL_NS::copy(first, last, out); + } + else + { + BidirectionalIterator last_m(first); + while(i != j) + { + if(!(flags & regex_constants::format_no_copy)) + out = BOOST_REGEX_DETAIL_NS::copy(i->prefix().first, i->prefix().second, out); + out = i->format(out, fmt, flags, e); + last_m = (*i)[0].second; + if(flags & regex_constants::format_first_only) + break; + ++i; + } + if(!(flags & regex_constants::format_no_copy)) + out = BOOST_REGEX_DETAIL_NS::copy(last_m, last, out); + } + return out; +} + +template +std::basic_string regex_replace(const std::basic_string& s, + const basic_regex& e, + Formatter fmt, + match_flag_type flags = match_default) +{ + std::basic_string result; + BOOST_REGEX_DETAIL_NS::string_out_iterator > i(result); + regex_replace(i, s.begin(), s.end(), e, fmt, flags); + return result; +} + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace boost + +#endif // BOOST_REGEX_V4_REGEX_REPLACE_HPP + + diff --git a/boost/regex/v4/regex_search.hpp b/boost/regex/v4/regex_search.hpp new file mode 100644 index 00000000..0725d3ec --- /dev/null +++ b/boost/regex/v4/regex_search.hpp @@ -0,0 +1,217 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_search.hpp + * VERSION see + * DESCRIPTION: Provides regex_search implementation. + */ + +#ifndef BOOST_REGEX_V4_REGEX_SEARCH_HPP +#define BOOST_REGEX_V4_REGEX_SEARCH_HPP + + +namespace boost{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +template +bool regex_search(BidiIterator first, BidiIterator last, + match_results& m, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_search(first, last, m, e, flags, first); +} + +template +bool regex_search(BidiIterator first, BidiIterator last, + match_results& m, + const basic_regex& e, + match_flag_type flags, + BidiIterator base) +{ + if(e.flags() & regex_constants::failbit) + return false; + + BOOST_REGEX_DETAIL_NS::perl_matcher matcher(first, last, m, e, flags, base); + return matcher.find(); +} + +// +// regex_search convenience interfaces: +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +// +// this isn't really a partial specialisation, but template function +// overloading - if the compiler doesn't support partial specialisation +// then it really won't support this either: +template +inline bool regex_search(const charT* str, + match_results& m, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_search(str, str + traits::length(str), m, e, flags); +} + +template +inline bool regex_search(const std::basic_string& s, + match_results::const_iterator, Allocator>& m, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_search(s.begin(), s.end(), m, e, flags); +} +#else // partial overloads: +inline bool regex_search(const char* str, + cmatch& m, + const regex& e, + match_flag_type flags = match_default) +{ + return regex_search(str, str + regex::traits_type::length(str), m, e, flags); +} +inline bool regex_search(const char* first, const char* last, + const regex& e, + match_flag_type flags = match_default) +{ + cmatch m; + return regex_search(first, last, m, e, flags | regex_constants::match_any); +} + +#ifndef BOOST_NO_WREGEX +inline bool regex_search(const wchar_t* str, + wcmatch& m, + const wregex& e, + match_flag_type flags = match_default) +{ + return regex_search(str, str + wregex::traits_type::length(str), m, e, flags); +} +inline bool regex_search(const wchar_t* first, const wchar_t* last, + const wregex& e, + match_flag_type flags = match_default) +{ + wcmatch m; + return regex_search(first, last, m, e, flags | regex_constants::match_any); +} +#endif +inline bool regex_search(const std::string& s, + smatch& m, + const regex& e, + match_flag_type flags = match_default) +{ + return regex_search(s.begin(), s.end(), m, e, flags); +} +#if !defined(BOOST_NO_WREGEX) +inline bool regex_search(const std::basic_string& s, + wsmatch& m, + const wregex& e, + match_flag_type flags = match_default) +{ + return regex_search(s.begin(), s.end(), m, e, flags); +} +#endif + +#endif + +template +bool regex_search(BidiIterator first, BidiIterator last, + const basic_regex& e, + match_flag_type flags = match_default) +{ + if(e.flags() & regex_constants::failbit) + return false; + + match_results m; + typedef typename match_results::allocator_type match_alloc_type; + BOOST_REGEX_DETAIL_NS::perl_matcher matcher(first, last, m, e, flags | regex_constants::match_any, first); + return matcher.find(); +} + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +template +inline bool regex_search(const charT* str, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_search(str, str + traits::length(str), e, flags); +} + +template +inline bool regex_search(const std::basic_string& s, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_search(s.begin(), s.end(), e, flags); +} +#else // non-template function overloads +inline bool regex_search(const char* str, + const regex& e, + match_flag_type flags = match_default) +{ + cmatch m; + return regex_search(str, str + regex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#ifndef BOOST_NO_WREGEX +inline bool regex_search(const wchar_t* str, + const wregex& e, + match_flag_type flags = match_default) +{ + wcmatch m; + return regex_search(str, str + wregex::traits_type::length(str), m, e, flags | regex_constants::match_any); +} +#endif +inline bool regex_search(const std::string& s, + const regex& e, + match_flag_type flags = match_default) +{ + smatch m; + return regex_search(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} +#if !defined(BOOST_NO_WREGEX) +inline bool regex_search(const std::basic_string& s, + const wregex& e, + match_flag_type flags = match_default) +{ + wsmatch m; + return regex_search(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} + +#endif // BOOST_NO_WREGEX + +#endif // partial overload + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace boost + +#endif // BOOST_REGEX_V4_REGEX_SEARCH_HPP + + diff --git a/boost/regex/v4/regex_split.hpp b/boost/regex/v4/regex_split.hpp new file mode 100644 index 00000000..afa56598 --- /dev/null +++ b/boost/regex/v4/regex_split.hpp @@ -0,0 +1,174 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_split.hpp + * VERSION see + * DESCRIPTION: Implements regex_split and associated functions. + * Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_SPLIT_HPP +#define BOOST_REGEX_SPLIT_HPP + +namespace boost{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +# pragma warning(push) +#if BOOST_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +namespace BOOST_REGEX_DETAIL_NS{ + +template +const basic_regex& get_default_expression(charT) +{ + static const charT expression_text[4] = { '\\', 's', '+', '\00', }; + static const basic_regex e(expression_text); + return e; +} + +template +class split_pred +{ + typedef std::basic_string string_type; + typedef typename string_type::const_iterator iterator_type; + iterator_type* p_last; + OutputIterator* p_out; + std::size_t* p_max; + std::size_t initial_max; +public: + split_pred(iterator_type* a, OutputIterator* b, std::size_t* c) + : p_last(a), p_out(b), p_max(c), initial_max(*c) {} + + bool operator()(const match_results& what); +}; + +template +bool split_pred::operator() + (const match_results& what) +{ + *p_last = what[0].second; + if(what.size() > 1) + { + // output sub-expressions only: + for(unsigned i = 1; i < what.size(); ++i) + { + *(*p_out) = what.str(i); + ++(*p_out); + if(0 == --*p_max) return false; + } + return *p_max != 0; + } + else + { + // output $` only if it's not-null or not at the start of the input: + const sub_match& sub = what[-1]; + if((sub.first != sub.second) || (*p_max != initial_max)) + { + *(*p_out) = sub.str(); + ++(*p_out); + return --*p_max; + } + } + // + // initial null, do nothing: + return true; +} + +} // namespace BOOST_REGEX_DETAIL_NS + +template +std::size_t regex_split(OutputIterator out, + std::basic_string& s, + const basic_regex& e, + match_flag_type flags, + std::size_t max_split) +{ + typedef typename std::basic_string::const_iterator ci_t; + //typedef typename match_results::allocator_type match_allocator; + ci_t last = s.begin(); + std::size_t init_size = max_split; + BOOST_REGEX_DETAIL_NS::split_pred pred(&last, &out, &max_split); + ci_t i, j; + i = s.begin(); + j = s.end(); + regex_grep(pred, i, j, e, flags); + // + // if there is still input left, do a final push as long as max_split + // is not exhausted, and we're not splitting sub-expressions rather + // than whitespace: + if(max_split && (last != s.end()) && (e.mark_count() == 0)) + { + *out = std::basic_string((ci_t)last, (ci_t)s.end()); + ++out; + last = s.end(); + --max_split; + } + // + // delete from the string everything that has been processed so far: + s.erase(0, last - s.begin()); + // + // return the number of new records pushed: + return init_size - max_split; +} + +template +inline std::size_t regex_split(OutputIterator out, + std::basic_string& s, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_split(out, s, e, flags, UINT_MAX); +} + +template +inline std::size_t regex_split(OutputIterator out, + std::basic_string& s) +{ + return regex_split(out, s, BOOST_REGEX_DETAIL_NS::get_default_expression(charT(0)), match_default, UINT_MAX); +} + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace boost + +#endif + + diff --git a/boost/regex/v4/regex_token_iterator.hpp b/boost/regex/v4/regex_token_iterator.hpp new file mode 100644 index 00000000..fc54b3c9 --- /dev/null +++ b/boost/regex/v4/regex_token_iterator.hpp @@ -0,0 +1,327 @@ +/* + * + * Copyright (c) 2003 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_token_iterator.hpp + * VERSION see + * DESCRIPTION: Provides regex_token_iterator implementation. + */ + +#ifndef BOOST_REGEX_V4_REGEX_TOKEN_ITERATOR_HPP +#define BOOST_REGEX_V4_REGEX_TOKEN_ITERATOR_HPP + +#include +#include +#if (BOOST_WORKAROUND(BOOST_BORLANDC, >= 0x560) && BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x570)))\ + || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) +// +// Borland C++ Builder 6, and Visual C++ 6, +// can't cope with the array template constructor +// so we have a template member that will accept any type as +// argument, and then assert that is really is an array: +// +#include +#include +#endif + +namespace boost{ + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#pragma warning(push) +#pragma warning(disable:4700) +#endif + +template +class regex_token_iterator_implementation +{ + typedef basic_regex regex_type; + typedef sub_match value_type; + + match_results what; // current match + BidirectionalIterator base; // start of search area + BidirectionalIterator end; // end of search area + const regex_type re; // the expression + match_flag_type flags; // match flags + value_type result; // the current string result + int N; // the current sub-expression being enumerated + std::vector subs; // the sub-expressions to enumerate + +public: + regex_token_iterator_implementation(const regex_token_iterator_implementation& other) + : what(other.what), base(other.base), end(other.end), re(other.re), flags(other.flags), result(other.result), N(other.N), subs(other.subs) {} + regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, int sub, match_flag_type f) + : end(last), re(*p), flags(f), N(0){ subs.push_back(sub); } + regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const std::vector& v, match_flag_type f) + : end(last), re(*p), flags(f), N(0), subs(v){} +#if !BOOST_WORKAROUND(__HP_aCC, < 60700) +#if (BOOST_WORKAROUND(BOOST_BORLANDC, >= 0x560) && BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x570)))\ + || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) \ + || BOOST_WORKAROUND(__HP_aCC, < 60700) + template + regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const T& submatches, match_flag_type f) + : end(last), re(*p), flags(f), N(0) + { + // assert that T really is an array: + BOOST_STATIC_ASSERT(::boost::is_array::value); + const std::size_t array_size = sizeof(T) / sizeof(submatches[0]); + for(std::size_t i = 0; i < array_size; ++i) + { + subs.push_back(submatches[i]); + } + } +#else + template + regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const int (&submatches)[CN], match_flag_type f) + : end(last), re(*p), flags(f), N(0) + { + for(std::size_t i = 0; i < CN; ++i) + { + subs.push_back(submatches[i]); + } + } +#endif +#endif + bool init(BidirectionalIterator first) + { + N = 0; + base = first; + if(regex_search(first, end, what, re, flags, base) == true) + { + N = 0; + result = ((subs[N] == -1) ? what.prefix() : what[(int)subs[N]]); + return true; + } + else if((subs[N] == -1) && (first != end)) + { + result.first = first; + result.second = end; + result.matched = (first != end); + N = -1; + return true; + } + return false; + } + bool compare(const regex_token_iterator_implementation& that) + { + if(this == &that) return true; + return (&re.get_data() == &that.re.get_data()) + && (end == that.end) + && (flags == that.flags) + && (N == that.N) + && (what[0].first == that.what[0].first) + && (what[0].second == that.what[0].second); + } + const value_type& get() + { return result; } + bool next() + { + if(N == -1) + return false; + if(N+1 < (int)subs.size()) + { + ++N; + result =((subs[N] == -1) ? what.prefix() : what[subs[N]]); + return true; + } + //if(what.prefix().first != what[0].second) + // flags |= /*match_prev_avail |*/ regex_constants::match_not_bob; + BidirectionalIterator last_end(what[0].second); + if(regex_search(last_end, end, what, re, ((what[0].first == what[0].second) ? flags | regex_constants::match_not_initial_null : flags), base)) + { + N =0; + result =((subs[N] == -1) ? what.prefix() : what[subs[N]]); + return true; + } + else if((last_end != end) && (subs[0] == -1)) + { + N =-1; + result.first = last_end; + result.second = end; + result.matched = (last_end != end); + return true; + } + return false; + } +private: + regex_token_iterator_implementation& operator=(const regex_token_iterator_implementation&); +}; + +template ::value_type, + class traits = regex_traits > +class regex_token_iterator +{ +private: + typedef regex_token_iterator_implementation impl; + typedef shared_ptr pimpl; +public: + typedef basic_regex regex_type; + typedef sub_match value_type; + typedef typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::difference_type + difference_type; + typedef const value_type* pointer; + typedef const value_type& reference; + typedef std::forward_iterator_tag iterator_category; + + regex_token_iterator(){} + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + int submatch = 0, match_flag_type m = match_default) + : pdata(new impl(&re, b, submatch, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + const std::vector& submatches, match_flag_type m = match_default) + : pdata(new impl(&re, b, submatches, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } +#if !BOOST_WORKAROUND(__HP_aCC, < 60700) +#if (BOOST_WORKAROUND(BOOST_BORLANDC, >= 0x560) && BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x570)))\ + || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) \ + || BOOST_WORKAROUND(__HP_aCC, < 60700) + template + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + const T& submatches, match_flag_type m = match_default) + : pdata(new impl(&re, b, submatches, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } +#else + template + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + const int (&submatches)[N], match_flag_type m = match_default) + : pdata(new impl(&re, b, submatches, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } +#endif +#endif + regex_token_iterator(const regex_token_iterator& that) + : pdata(that.pdata) {} + regex_token_iterator& operator=(const regex_token_iterator& that) + { + pdata = that.pdata; + return *this; + } + bool operator==(const regex_token_iterator& that)const + { + if((pdata.get() == 0) || (that.pdata.get() == 0)) + return pdata.get() == that.pdata.get(); + return pdata->compare(*(that.pdata.get())); + } + bool operator!=(const regex_token_iterator& that)const + { return !(*this == that); } + const value_type& operator*()const + { return pdata->get(); } + const value_type* operator->()const + { return &(pdata->get()); } + regex_token_iterator& operator++() + { + cow(); + if(0 == pdata->next()) + { + pdata.reset(); + } + return *this; + } + regex_token_iterator operator++(int) + { + regex_token_iterator result(*this); + ++(*this); + return result; + } +private: + + pimpl pdata; + + void cow() + { + // copy-on-write + if(pdata.get() && !pdata.unique()) + { + pdata.reset(new impl(*(pdata.get()))); + } + } +}; + +typedef regex_token_iterator cregex_token_iterator; +typedef regex_token_iterator sregex_token_iterator; +#ifndef BOOST_NO_WREGEX +typedef regex_token_iterator wcregex_token_iterator; +typedef regex_token_iterator wsregex_token_iterator; +#endif + +template +inline regex_token_iterator make_regex_token_iterator(const charT* p, const basic_regex& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator(p, p+traits::length(p), e, submatch, m); +} +template +inline regex_token_iterator::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string& p, const basic_regex& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m); +} +template +inline regex_token_iterator make_regex_token_iterator(const charT* p, const basic_regex& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator(p, p+traits::length(p), e, submatch, m); +} +template +inline regex_token_iterator::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string& p, const basic_regex& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m); +} +template +inline regex_token_iterator make_regex_token_iterator(const charT* p, const basic_regex& e, const std::vector& submatch, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator(p, p+traits::length(p), e, submatch, m); +} +template +inline regex_token_iterator::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string& p, const basic_regex& e, const std::vector& submatch, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m); +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +} // namespace boost + +#endif // BOOST_REGEX_V4_REGEX_TOKEN_ITERATOR_HPP + + + + diff --git a/boost/regex/v4/regex_traits.hpp b/boost/regex/v4/regex_traits.hpp new file mode 100644 index 00000000..ffa2bb68 --- /dev/null +++ b/boost/regex/v4/regex_traits.hpp @@ -0,0 +1,189 @@ +/* + * + * Copyright (c) 2003 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_traits.hpp + * VERSION see + * DESCRIPTION: Declares regular expression traits classes. + */ + +#ifndef BOOST_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_REGEX_TRAITS_HPP_INCLUDED + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif +#ifndef BOOST_REGEX_WORKAROUND_HPP +#include +#endif +#ifndef BOOST_REGEX_SYNTAX_TYPE_HPP +#include +#endif +#ifndef BOOST_REGEX_ERROR_TYPE_HPP +#include +#endif +#ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED +#include +#endif +#ifndef BOOST_NO_STD_LOCALE +# ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED +# include +# endif +#endif +#if !BOOST_WORKAROUND(BOOST_BORLANDC, < 0x560) +# ifndef BOOST_C_REGEX_TRAITS_HPP_INCLUDED +# include +# endif +#endif +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +# ifndef BOOST_W32_REGEX_TRAITS_HPP_INCLUDED +# include +# endif +#endif +#ifndef BOOST_REGEX_FWD_HPP_INCLUDED +#include +#endif + +#include "boost/mpl/has_xxx.hpp" +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +namespace boost{ + +template +struct regex_traits : public implementationT +{ + regex_traits() : implementationT() {} +}; + +// +// class regex_traits_wrapper. +// this is what our implementation will actually store; +// it provides default implementations of the "optional" +// interfaces that we support, in addition to the +// required "standard" ones: +// +namespace BOOST_REGEX_DETAIL_NS{ +#if !BOOST_WORKAROUND(__HP_aCC, < 60000) +BOOST_MPL_HAS_XXX_TRAIT_DEF(boost_extensions_tag) +#else +template +struct has_boost_extensions_tag +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; +#endif + +template +struct default_wrapper : public BaseT +{ + typedef typename BaseT::char_type char_type; + std::string error_string(::boost::regex_constants::error_type e)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::get_default_error_string(e); + } + ::boost::regex_constants::syntax_type syntax_type(char_type c)const + { + return ((c & 0x7f) == c) ? get_default_syntax_type(static_cast(c)) : ::boost::regex_constants::syntax_char; + } + ::boost::regex_constants::escape_syntax_type escape_syntax_type(char_type c)const + { + return ((c & 0x7f) == c) ? get_default_escape_syntax_type(static_cast(c)) : ::boost::regex_constants::escape_type_identity; + } + boost::intmax_t toi(const char_type*& p1, const char_type* p2, int radix)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::global_toi(p1, p2, radix, *this); + } + char_type translate(char_type c, bool icase)const + { + return (icase ? this->translate_nocase(c) : this->translate(c)); + } + char_type translate(char_type c)const + { + return BaseT::translate(c); + } + char_type tolower(char_type c)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::global_lower(c); + } + char_type toupper(char_type c)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::global_upper(c); + } +}; + +template +struct compute_wrapper_base +{ + typedef BaseT type; +}; +#if !BOOST_WORKAROUND(__HP_aCC, < 60000) +template +struct compute_wrapper_base +{ + typedef default_wrapper type; +}; +#else +template <> +struct compute_wrapper_base, false> +{ + typedef default_wrapper > type; +}; +#ifndef BOOST_NO_WREGEX +template <> +struct compute_wrapper_base, false> +{ + typedef default_wrapper > type; +}; +#endif +#endif + +} // namespace BOOST_REGEX_DETAIL_NS + +template +struct regex_traits_wrapper + : public ::boost::BOOST_REGEX_DETAIL_NS::compute_wrapper_base< + BaseT, + ::boost::BOOST_REGEX_DETAIL_NS::has_boost_extensions_tag::value + >::type +{ + regex_traits_wrapper(){} +private: + regex_traits_wrapper(const regex_traits_wrapper&); + regex_traits_wrapper& operator=(const regex_traits_wrapper&); +}; + +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // include + diff --git a/boost/regex/v4/regex_traits_defaults.hpp b/boost/regex/v4/regex_traits_defaults.hpp new file mode 100644 index 00000000..1dbb0bf9 --- /dev/null +++ b/boost/regex/v4/regex_traits_defaults.hpp @@ -0,0 +1,997 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_traits_defaults.hpp + * VERSION see + * DESCRIPTION: Declares API's for access to regex_traits default properties. + */ + +#ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED +#define BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include +#include + +#include +#include +#include + +#ifndef BOOST_REGEX_SYNTAX_TYPE_HPP +#include +#endif +#ifndef BOOST_REGEX_ERROR_TYPE_HPP +#include +#endif +#include +#include +#include + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ + using ::strlen; +} +#endif + +namespace boost{ namespace BOOST_REGEX_DETAIL_NS{ + + +// +// helpers to suppress warnings: +// +template +inline bool is_extended(charT c) +{ + typedef typename make_unsigned::type unsigned_type; + return (sizeof(charT) > 1) && (static_cast(c) >= 256u); +} +inline bool is_extended(char) +{ return false; } + +inline const char* BOOST_REGEX_CALL get_default_syntax(regex_constants::syntax_type n) +{ + // if the user hasn't supplied a message catalog, then this supplies + // default "messages" for us to load in the range 1-100. + const char* messages[] = { + "", + "(", + ")", + "$", + "^", + ".", + "*", + "+", + "?", + "[", + "]", + "|", + "\\", + "#", + "-", + "{", + "}", + "0123456789", + "b", + "B", + "<", + ">", + "", + "", + "A`", + "z'", + "\n", + ",", + "a", + "f", + "n", + "r", + "t", + "v", + "x", + "c", + ":", + "=", + "e", + "", + "", + "", + "", + "", + "", + "", + "", + "E", + "Q", + "X", + "C", + "Z", + "G", + "!", + "p", + "P", + "N", + "gk", + "K", + "R", + }; + + return ((n >= (sizeof(messages) / sizeof(messages[1]))) ? "" : messages[n]); +} + +inline const char* BOOST_REGEX_CALL get_default_error_string(regex_constants::error_type n) +{ + static const char* const s_default_error_messages[] = { + "Success", /* REG_NOERROR 0 error_ok */ + "No match", /* REG_NOMATCH 1 error_no_match */ + "Invalid regular expression.", /* REG_BADPAT 2 error_bad_pattern */ + "Invalid collation character.", /* REG_ECOLLATE 3 error_collate */ + "Invalid character class name, collating name, or character range.", /* REG_ECTYPE 4 error_ctype */ + "Invalid or unterminated escape sequence.", /* REG_EESCAPE 5 error_escape */ + "Invalid back reference: specified capturing group does not exist.", /* REG_ESUBREG 6 error_backref */ + "Unmatched [ or [^ in character class declaration.", /* REG_EBRACK 7 error_brack */ + "Unmatched marking parenthesis ( or \\(.", /* REG_EPAREN 8 error_paren */ + "Unmatched quantified repeat operator { or \\{.", /* REG_EBRACE 9 error_brace */ + "Invalid content of repeat range.", /* REG_BADBR 10 error_badbrace */ + "Invalid range end in character class", /* REG_ERANGE 11 error_range */ + "Out of memory.", /* REG_ESPACE 12 error_space NOT USED */ + "Invalid preceding regular expression prior to repetition operator.", /* REG_BADRPT 13 error_badrepeat */ + "Premature end of regular expression", /* REG_EEND 14 error_end NOT USED */ + "Regular expression is too large.", /* REG_ESIZE 15 error_size NOT USED */ + "Unmatched ) or \\)", /* REG_ERPAREN 16 error_right_paren NOT USED */ + "Empty regular expression.", /* REG_EMPTY 17 error_empty */ + "The complexity of matching the regular expression exceeded predefined bounds. " + "Try refactoring the regular expression to make each choice made by the state machine unambiguous. " + "This exception is thrown to prevent \"eternal\" matches that take an " + "indefinite period time to locate.", /* REG_ECOMPLEXITY 18 error_complexity */ + "Ran out of stack space trying to match the regular expression.", /* REG_ESTACK 19 error_stack */ + "Invalid or unterminated Perl (?...) sequence.", /* REG_E_PERL 20 error_perl */ + "Unknown error.", /* REG_E_UNKNOWN 21 error_unknown */ + }; + + return (n > ::boost::regex_constants::error_unknown) ? s_default_error_messages[::boost::regex_constants::error_unknown] : s_default_error_messages[n]; +} + +inline regex_constants::syntax_type BOOST_REGEX_CALL get_default_syntax_type(char c) +{ + // + // char_syntax determines how the compiler treats a given character + // in a regular expression. + // + static regex_constants::syntax_type char_syntax[] = { + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_newline, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /* */ // 32 + regex_constants::syntax_not, /*!*/ + regex_constants::syntax_char, /*"*/ + regex_constants::syntax_hash, /*#*/ + regex_constants::syntax_dollar, /*$*/ + regex_constants::syntax_char, /*%*/ + regex_constants::syntax_char, /*&*/ + regex_constants::escape_type_end_buffer, /*'*/ + regex_constants::syntax_open_mark, /*(*/ + regex_constants::syntax_close_mark, /*)*/ + regex_constants::syntax_star, /***/ + regex_constants::syntax_plus, /*+*/ + regex_constants::syntax_comma, /*,*/ + regex_constants::syntax_dash, /*-*/ + regex_constants::syntax_dot, /*.*/ + regex_constants::syntax_char, /*/*/ + regex_constants::syntax_digit, /*0*/ + regex_constants::syntax_digit, /*1*/ + regex_constants::syntax_digit, /*2*/ + regex_constants::syntax_digit, /*3*/ + regex_constants::syntax_digit, /*4*/ + regex_constants::syntax_digit, /*5*/ + regex_constants::syntax_digit, /*6*/ + regex_constants::syntax_digit, /*7*/ + regex_constants::syntax_digit, /*8*/ + regex_constants::syntax_digit, /*9*/ + regex_constants::syntax_colon, /*:*/ + regex_constants::syntax_char, /*;*/ + regex_constants::escape_type_left_word, /*<*/ + regex_constants::syntax_equal, /*=*/ + regex_constants::escape_type_right_word, /*>*/ + regex_constants::syntax_question, /*?*/ + regex_constants::syntax_char, /*@*/ + regex_constants::syntax_char, /*A*/ + regex_constants::syntax_char, /*B*/ + regex_constants::syntax_char, /*C*/ + regex_constants::syntax_char, /*D*/ + regex_constants::syntax_char, /*E*/ + regex_constants::syntax_char, /*F*/ + regex_constants::syntax_char, /*G*/ + regex_constants::syntax_char, /*H*/ + regex_constants::syntax_char, /*I*/ + regex_constants::syntax_char, /*J*/ + regex_constants::syntax_char, /*K*/ + regex_constants::syntax_char, /*L*/ + regex_constants::syntax_char, /*M*/ + regex_constants::syntax_char, /*N*/ + regex_constants::syntax_char, /*O*/ + regex_constants::syntax_char, /*P*/ + regex_constants::syntax_char, /*Q*/ + regex_constants::syntax_char, /*R*/ + regex_constants::syntax_char, /*S*/ + regex_constants::syntax_char, /*T*/ + regex_constants::syntax_char, /*U*/ + regex_constants::syntax_char, /*V*/ + regex_constants::syntax_char, /*W*/ + regex_constants::syntax_char, /*X*/ + regex_constants::syntax_char, /*Y*/ + regex_constants::syntax_char, /*Z*/ + regex_constants::syntax_open_set, /*[*/ + regex_constants::syntax_escape, /*\*/ + regex_constants::syntax_close_set, /*]*/ + regex_constants::syntax_caret, /*^*/ + regex_constants::syntax_char, /*_*/ + regex_constants::syntax_char, /*`*/ + regex_constants::syntax_char, /*a*/ + regex_constants::syntax_char, /*b*/ + regex_constants::syntax_char, /*c*/ + regex_constants::syntax_char, /*d*/ + regex_constants::syntax_char, /*e*/ + regex_constants::syntax_char, /*f*/ + regex_constants::syntax_char, /*g*/ + regex_constants::syntax_char, /*h*/ + regex_constants::syntax_char, /*i*/ + regex_constants::syntax_char, /*j*/ + regex_constants::syntax_char, /*k*/ + regex_constants::syntax_char, /*l*/ + regex_constants::syntax_char, /*m*/ + regex_constants::syntax_char, /*n*/ + regex_constants::syntax_char, /*o*/ + regex_constants::syntax_char, /*p*/ + regex_constants::syntax_char, /*q*/ + regex_constants::syntax_char, /*r*/ + regex_constants::syntax_char, /*s*/ + regex_constants::syntax_char, /*t*/ + regex_constants::syntax_char, /*u*/ + regex_constants::syntax_char, /*v*/ + regex_constants::syntax_char, /*w*/ + regex_constants::syntax_char, /*x*/ + regex_constants::syntax_char, /*y*/ + regex_constants::syntax_char, /*z*/ + regex_constants::syntax_open_brace, /*{*/ + regex_constants::syntax_or, /*|*/ + regex_constants::syntax_close_brace, /*}*/ + regex_constants::syntax_char, /*~*/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + }; + + return char_syntax[(unsigned char)c]; +} + +inline regex_constants::escape_syntax_type BOOST_REGEX_CALL get_default_escape_syntax_type(char c) +{ + // + // char_syntax determines how the compiler treats a given character + // in a regular expression. + // + static regex_constants::escape_syntax_type char_syntax[] = { + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /* */ // 32 + regex_constants::escape_type_identity, /*!*/ + regex_constants::escape_type_identity, /*"*/ + regex_constants::escape_type_identity, /*#*/ + regex_constants::escape_type_identity, /*$*/ + regex_constants::escape_type_identity, /*%*/ + regex_constants::escape_type_identity, /*&*/ + regex_constants::escape_type_end_buffer, /*'*/ + regex_constants::syntax_open_mark, /*(*/ + regex_constants::syntax_close_mark, /*)*/ + regex_constants::escape_type_identity, /***/ + regex_constants::syntax_plus, /*+*/ + regex_constants::escape_type_identity, /*,*/ + regex_constants::escape_type_identity, /*-*/ + regex_constants::escape_type_identity, /*.*/ + regex_constants::escape_type_identity, /*/*/ + regex_constants::escape_type_decimal, /*0*/ + regex_constants::escape_type_backref, /*1*/ + regex_constants::escape_type_backref, /*2*/ + regex_constants::escape_type_backref, /*3*/ + regex_constants::escape_type_backref, /*4*/ + regex_constants::escape_type_backref, /*5*/ + regex_constants::escape_type_backref, /*6*/ + regex_constants::escape_type_backref, /*7*/ + regex_constants::escape_type_backref, /*8*/ + regex_constants::escape_type_backref, /*9*/ + regex_constants::escape_type_identity, /*:*/ + regex_constants::escape_type_identity, /*;*/ + regex_constants::escape_type_left_word, /*<*/ + regex_constants::escape_type_identity, /*=*/ + regex_constants::escape_type_right_word, /*>*/ + regex_constants::syntax_question, /*?*/ + regex_constants::escape_type_identity, /*@*/ + regex_constants::escape_type_start_buffer, /*A*/ + regex_constants::escape_type_not_word_assert, /*B*/ + regex_constants::escape_type_C, /*C*/ + regex_constants::escape_type_not_class, /*D*/ + regex_constants::escape_type_E, /*E*/ + regex_constants::escape_type_not_class, /*F*/ + regex_constants::escape_type_G, /*G*/ + regex_constants::escape_type_not_class, /*H*/ + regex_constants::escape_type_not_class, /*I*/ + regex_constants::escape_type_not_class, /*J*/ + regex_constants::escape_type_reset_start_mark, /*K*/ + regex_constants::escape_type_not_class, /*L*/ + regex_constants::escape_type_not_class, /*M*/ + regex_constants::escape_type_named_char, /*N*/ + regex_constants::escape_type_not_class, /*O*/ + regex_constants::escape_type_not_property, /*P*/ + regex_constants::escape_type_Q, /*Q*/ + regex_constants::escape_type_line_ending, /*R*/ + regex_constants::escape_type_not_class, /*S*/ + regex_constants::escape_type_not_class, /*T*/ + regex_constants::escape_type_not_class, /*U*/ + regex_constants::escape_type_not_class, /*V*/ + regex_constants::escape_type_not_class, /*W*/ + regex_constants::escape_type_X, /*X*/ + regex_constants::escape_type_not_class, /*Y*/ + regex_constants::escape_type_Z, /*Z*/ + regex_constants::escape_type_identity, /*[*/ + regex_constants::escape_type_identity, /*\*/ + regex_constants::escape_type_identity, /*]*/ + regex_constants::escape_type_identity, /*^*/ + regex_constants::escape_type_identity, /*_*/ + regex_constants::escape_type_start_buffer, /*`*/ + regex_constants::escape_type_control_a, /*a*/ + regex_constants::escape_type_word_assert, /*b*/ + regex_constants::escape_type_ascii_control, /*c*/ + regex_constants::escape_type_class, /*d*/ + regex_constants::escape_type_e, /*e*/ + regex_constants::escape_type_control_f, /*f*/ + regex_constants::escape_type_extended_backref, /*g*/ + regex_constants::escape_type_class, /*h*/ + regex_constants::escape_type_class, /*i*/ + regex_constants::escape_type_class, /*j*/ + regex_constants::escape_type_extended_backref, /*k*/ + regex_constants::escape_type_class, /*l*/ + regex_constants::escape_type_class, /*m*/ + regex_constants::escape_type_control_n, /*n*/ + regex_constants::escape_type_class, /*o*/ + regex_constants::escape_type_property, /*p*/ + regex_constants::escape_type_class, /*q*/ + regex_constants::escape_type_control_r, /*r*/ + regex_constants::escape_type_class, /*s*/ + regex_constants::escape_type_control_t, /*t*/ + regex_constants::escape_type_class, /*u*/ + regex_constants::escape_type_control_v, /*v*/ + regex_constants::escape_type_class, /*w*/ + regex_constants::escape_type_hex, /*x*/ + regex_constants::escape_type_class, /*y*/ + regex_constants::escape_type_end_buffer, /*z*/ + regex_constants::syntax_open_brace, /*{*/ + regex_constants::syntax_or, /*|*/ + regex_constants::syntax_close_brace, /*}*/ + regex_constants::escape_type_identity, /*~*/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + }; + + return char_syntax[(unsigned char)c]; +} + +// is charT c a combining character? +inline bool BOOST_REGEX_CALL is_combining_implementation(boost::uint_least16_t c) +{ + const boost::uint_least16_t combining_ranges[] = { 0x0300, 0x0361, + 0x0483, 0x0486, + 0x0903, 0x0903, + 0x093E, 0x0940, + 0x0949, 0x094C, + 0x0982, 0x0983, + 0x09BE, 0x09C0, + 0x09C7, 0x09CC, + 0x09D7, 0x09D7, + 0x0A3E, 0x0A40, + 0x0A83, 0x0A83, + 0x0ABE, 0x0AC0, + 0x0AC9, 0x0ACC, + 0x0B02, 0x0B03, + 0x0B3E, 0x0B3E, + 0x0B40, 0x0B40, + 0x0B47, 0x0B4C, + 0x0B57, 0x0B57, + 0x0B83, 0x0B83, + 0x0BBE, 0x0BBF, + 0x0BC1, 0x0BCC, + 0x0BD7, 0x0BD7, + 0x0C01, 0x0C03, + 0x0C41, 0x0C44, + 0x0C82, 0x0C83, + 0x0CBE, 0x0CBE, + 0x0CC0, 0x0CC4, + 0x0CC7, 0x0CCB, + 0x0CD5, 0x0CD6, + 0x0D02, 0x0D03, + 0x0D3E, 0x0D40, + 0x0D46, 0x0D4C, + 0x0D57, 0x0D57, + 0x0F7F, 0x0F7F, + 0x20D0, 0x20E1, + 0x3099, 0x309A, + 0xFE20, 0xFE23, + 0xffff, 0xffff, }; + + const boost::uint_least16_t* p = combining_ranges + 1; + while (*p < c) p += 2; + --p; + if ((c >= *p) && (c <= *(p + 1))) + return true; + return false; +} + +template +inline bool is_combining(charT c) +{ + return (c <= static_cast(0)) ? false : ((c >= static_cast((std::numeric_limits::max)())) ? false : is_combining_implementation(static_cast(c))); +} +template <> +inline bool is_combining(char) +{ + return false; +} +template <> +inline bool is_combining(signed char) +{ + return false; +} +template <> +inline bool is_combining(unsigned char) +{ + return false; +} +#if !defined(__hpux) && !defined(__WINSCW__) // can't use WCHAR_MAX/MIN in pp-directives +#ifdef _MSC_VER +template<> +inline bool is_combining(wchar_t c) +{ + return is_combining_implementation(static_cast(c)); +} +#elif !defined(__DECCXX) && !defined(__osf__) && !defined(__OSF__) && defined(WCHAR_MIN) && (WCHAR_MIN == 0) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) +#if defined(WCHAR_MAX) && (WCHAR_MAX <= USHRT_MAX) +template<> +inline bool is_combining(wchar_t c) +{ + return is_combining_implementation(static_cast(c)); +} +#else +template<> +inline bool is_combining(wchar_t c) +{ + return (c >= (std::numeric_limits::max)()) ? false : is_combining_implementation(static_cast(c)); +} +#endif +#endif +#endif + +// +// is a charT c a line separator? +// +template +inline bool is_separator(charT c) +{ + return BOOST_REGEX_MAKE_BOOL( + (c == static_cast('\n')) + || (c == static_cast('\r')) + || (c == static_cast('\f')) + || (static_cast(c) == 0x2028u) + || (static_cast(c) == 0x2029u) + || (static_cast(c) == 0x85u)); +} +template <> +inline bool is_separator(char c) +{ + return BOOST_REGEX_MAKE_BOOL((c == '\n') || (c == '\r') || (c == '\f')); +} + +// +// get a default collating element: +// +inline std::string BOOST_REGEX_CALL lookup_default_collate_name(const std::string& name) +{ + // + // these are the POSIX collating names: + // + static const char* def_coll_names[] = { + "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "alert", "backspace", "tab", "newline", + "vertical-tab", "form-feed", "carriage-return", "SO", "SI", "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", + "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "IS4", "IS3", "IS2", "IS1", "space", "exclamation-mark", + "quotation-mark", "number-sign", "dollar-sign", "percent-sign", "ampersand", "apostrophe", + "left-parenthesis", "right-parenthesis", "asterisk", "plus-sign", "comma", "hyphen", + "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", + "colon", "semicolon", "less-than-sign", "equals-sign", "greater-than-sign", + "question-mark", "commercial-at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", + "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "left-square-bracket", "backslash", + "right-square-bracket", "circumflex", "underscore", "grave-accent", "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "left-curly-bracket", + "vertical-line", "right-curly-bracket", "tilde", "DEL", "", + }; + + // these multi-character collating elements + // should keep most Western-European locales + // happy - we should really localise these a + // little more - but this will have to do for + // now: + + static const char* def_multi_coll[] = { + "ae", + "Ae", + "AE", + "ch", + "Ch", + "CH", + "ll", + "Ll", + "LL", + "ss", + "Ss", + "SS", + "nj", + "Nj", + "NJ", + "dz", + "Dz", + "DZ", + "lj", + "Lj", + "LJ", + "", + }; + + unsigned int i = 0; + while (*def_coll_names[i]) + { + if (def_coll_names[i] == name) + { + return std::string(1, char(i)); + } + ++i; + } + i = 0; + while (*def_multi_coll[i]) + { + if (def_multi_coll[i] == name) + { + return def_multi_coll[i]; + } + ++i; + } + return std::string(); +} + +// +// get the state_id of a character classification, the individual +// traits classes then transform that state_id into a bitmask: +// +template +struct character_pointer_range +{ + const charT* p1; + const charT* p2; + + bool operator < (const character_pointer_range& r)const + { + return std::lexicographical_compare(p1, p2, r.p1, r.p2); + } + bool operator == (const character_pointer_range& r)const + { + // Not only do we check that the ranges are of equal size before + // calling std::equal, but there is no other algorithm available: + // not even a non-standard MS one. So forward to unchecked_equal + // in the MS case. + return ((p2 - p1) == (r.p2 - r.p1)) && BOOST_REGEX_DETAIL_NS::equal(p1, p2, r.p1); + } +}; +template +int get_default_class_id(const charT* p1, const charT* p2) +{ + static const charT data[73] = { + 'a', 'l', 'n', 'u', 'm', + 'a', 'l', 'p', 'h', 'a', + 'b', 'l', 'a', 'n', 'k', + 'c', 'n', 't', 'r', 'l', + 'd', 'i', 'g', 'i', 't', + 'g', 'r', 'a', 'p', 'h', + 'l', 'o', 'w', 'e', 'r', + 'p', 'r', 'i', 'n', 't', + 'p', 'u', 'n', 'c', 't', + 's', 'p', 'a', 'c', 'e', + 'u', 'n', 'i', 'c', 'o', 'd', 'e', + 'u', 'p', 'p', 'e', 'r', + 'v', + 'w', 'o', 'r', 'd', + 'x', 'd', 'i', 'g', 'i', 't', + }; + + static const character_pointer_range ranges[21] = + { + {data+0, data+5,}, // alnum + {data+5, data+10,}, // alpha + {data+10, data+15,}, // blank + {data+15, data+20,}, // cntrl + {data+20, data+21,}, // d + {data+20, data+25,}, // digit + {data+25, data+30,}, // graph + {data+29, data+30,}, // h + {data+30, data+31,}, // l + {data+30, data+35,}, // lower + {data+35, data+40,}, // print + {data+40, data+45,}, // punct + {data+45, data+46,}, // s + {data+45, data+50,}, // space + {data+57, data+58,}, // u + {data+50, data+57,}, // unicode + {data+57, data+62,}, // upper + {data+62, data+63,}, // v + {data+63, data+64,}, // w + {data+63, data+67,}, // word + {data+67, data+73,}, // xdigit + }; + const character_pointer_range* ranges_begin = ranges; + const character_pointer_range* ranges_end = ranges + (sizeof(ranges)/sizeof(ranges[0])); + + character_pointer_range t = { p1, p2, }; + const character_pointer_range* p = std::lower_bound(ranges_begin, ranges_end, t); + if((p != ranges_end) && (t == *p)) + return static_cast(p - ranges); + return -1; +} + +// +// helper functions: +// +template +std::ptrdiff_t global_length(const charT* p) +{ + std::ptrdiff_t n = 0; + while(*p) + { + ++p; + ++n; + } + return n; +} +template<> +inline std::ptrdiff_t global_length(const char* p) +{ + return (std::strlen)(p); +} +#ifndef BOOST_NO_WREGEX +template<> +inline std::ptrdiff_t global_length(const wchar_t* p) +{ + return (std::ptrdiff_t)(std::wcslen)(p); +} +#endif +template +inline charT BOOST_REGEX_CALL global_lower(charT c) +{ + return c; +} +template +inline charT BOOST_REGEX_CALL global_upper(charT c) +{ + return c; +} + +inline char BOOST_REGEX_CALL do_global_lower(char c) +{ + return static_cast((std::tolower)((unsigned char)c)); +} + +inline char BOOST_REGEX_CALL do_global_upper(char c) +{ + return static_cast((std::toupper)((unsigned char)c)); +} +#ifndef BOOST_NO_WREGEX +inline wchar_t BOOST_REGEX_CALL do_global_lower(wchar_t c) +{ + return (std::towlower)(c); +} + +inline wchar_t BOOST_REGEX_CALL do_global_upper(wchar_t c) +{ + return (std::towupper)(c); +} +#endif +// +// This sucks: declare template specialisations of global_lower/global_upper +// that just forward to the non-template implementation functions. We do +// this because there is one compiler (Compaq Tru64 C++) that doesn't seem +// to differentiate between templates and non-template overloads.... +// what's more, the primary template, plus all overloads have to be +// defined in the same translation unit (if one is inline they all must be) +// otherwise the "local template instantiation" compiler option can pick +// the wrong instantiation when linking: +// +template<> inline char BOOST_REGEX_CALL global_lower(char c) { return do_global_lower(c); } +template<> inline char BOOST_REGEX_CALL global_upper(char c) { return do_global_upper(c); } +#ifndef BOOST_NO_WREGEX +template<> inline wchar_t BOOST_REGEX_CALL global_lower(wchar_t c) { return do_global_lower(c); } +template<> inline wchar_t BOOST_REGEX_CALL global_upper(wchar_t c) { return do_global_upper(c); } +#endif + +template +int global_value(charT c) +{ + static const charT zero = '0'; + static const charT nine = '9'; + static const charT a = 'a'; + static const charT f = 'f'; + static const charT A = 'A'; + static const charT F = 'F'; + + if(c > f) return -1; + if(c >= a) return 10 + (c - a); + if(c > F) return -1; + if(c >= A) return 10 + (c - A); + if(c > nine) return -1; + if(c >= zero) return c - zero; + return -1; +} +template +boost::intmax_t global_toi(const charT*& p1, const charT* p2, int radix, const traits& t) +{ + (void)t; // warning suppression + boost::intmax_t limit = (std::numeric_limits::max)() / radix; + boost::intmax_t next_value = t.value(*p1, radix); + if((p1 == p2) || (next_value < 0) || (next_value >= radix)) + return -1; + boost::intmax_t result = 0; + while(p1 != p2) + { + next_value = t.value(*p1, radix); + if((next_value < 0) || (next_value >= radix)) + break; + result *= radix; + result += next_value; + ++p1; + if (result > limit) + return -1; + } + return result; +} + +template +inline typename boost::enable_if_c<(sizeof(charT) > 1), const charT*>::type get_escape_R_string() +{ +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4309 4245) +#endif + static const charT e1[] = { '(', '?', '-', 'x', ':', '(', '?', '>', '\x0D', '\x0A', '?', + '|', '[', '\x0A', '\x0B', '\x0C', static_cast(0x85), static_cast(0x2028), + static_cast(0x2029), ']', ')', ')', '\0' }; + static const charT e2[] = { '(', '?', '-', 'x', ':', '(', '?', '>', '\x0D', '\x0A', '?', + '|', '[', '\x0A', '\x0B', '\x0C', static_cast(0x85), ']', ')', ')', '\0' }; + + charT c = static_cast(0x2029u); + bool b = (static_cast(c) == 0x2029u); + + return (b ? e1 : e2); +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif +} + +template +inline typename boost::disable_if_c<(sizeof(charT) > 1), const charT*>::type get_escape_R_string() +{ +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4309) +#endif + static const charT e2[] = { '(', '?', '-', 'x', ':', '(', '?', '>', '\x0D', '\x0A', '?', + '|', '[', '\x0A', '\x0B', '\x0C', '\x85', ']', ')', ')', '\0' }; + return e2; +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif +} + +} // BOOST_REGEX_DETAIL_NS +} // boost + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif diff --git a/boost/regex/v4/regex_workaround.hpp b/boost/regex/v4/regex_workaround.hpp new file mode 100644 index 00000000..324136e0 --- /dev/null +++ b/boost/regex/v4/regex_workaround.hpp @@ -0,0 +1,237 @@ +/* + * + * Copyright (c) 1998-2005 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_workarounds.cpp + * VERSION see + * DESCRIPTION: Declares Misc workarounds. + */ + +#ifndef BOOST_REGEX_WORKAROUND_HPP +#define BOOST_REGEX_WORKAROUND_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef BOOST_NO_STD_LOCALE +# include +#endif + +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::sprintf; using ::strcpy; using ::strcat; using ::strlen; +} +#endif + +namespace boost{ namespace BOOST_REGEX_DETAIL_NS{ +#ifdef BOOST_NO_STD_DISTANCE +template +std::ptrdiff_t distance(const T& x, const T& y) +{ return y - x; } +#else +using std::distance; +#endif +}} + + +#ifdef BOOST_REGEX_NO_BOOL +# define BOOST_REGEX_MAKE_BOOL(x) static_cast((x) ? true : false) +#else +# define BOOST_REGEX_MAKE_BOOL(x) static_cast(x) +#endif + +/***************************************************************************** + * + * Fix broken namespace support: + * + ****************************************************************************/ + +#if defined(BOOST_NO_STDC_NAMESPACE) && defined(__cplusplus) + +namespace std{ + using ::ptrdiff_t; + using ::size_t; + using ::abs; + using ::memset; + using ::memcpy; +} + +#endif + +/***************************************************************************** + * + * helper functions pointer_construct/pointer_destroy: + * + ****************************************************************************/ + +#ifdef __cplusplus +namespace boost{ namespace BOOST_REGEX_DETAIL_NS{ + +#ifdef BOOST_MSVC +#pragma warning (push) +#pragma warning (disable : 4100) +#endif + +template +inline void pointer_destroy(T* p) +{ p->~T(); (void)p; } + +#ifdef BOOST_MSVC +#pragma warning (pop) +#endif + +template +inline void pointer_construct(T* p, const T& t) +{ new (p) T(t); } + +}} // namespaces +#endif + +/***************************************************************************** + * + * helper function copy: + * + ****************************************************************************/ + +#ifdef __cplusplus +namespace boost{ namespace BOOST_REGEX_DETAIL_NS{ +#if BOOST_WORKAROUND(BOOST_MSVC,>=1400) && BOOST_WORKAROUND(BOOST_MSVC, <1600) && defined(_CPPLIB_VER) && defined(BOOST_DINKUMWARE_STDLIB) && !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) + // + // MSVC 8 will either emit warnings or else refuse to compile + // code that makes perfectly legitimate use of std::copy, when + // the OutputIterator type is a user-defined class (apparently all user + // defined iterators are "unsafe"). This code works around that: + // + template + inline OutputIterator copy( + InputIterator first, + InputIterator last, + OutputIterator dest + ) + { + return stdext::unchecked_copy(first, last, dest); + } + template + inline bool equal( + InputIterator1 first, + InputIterator1 last, + InputIterator2 with + ) + { + return stdext::unchecked_equal(first, last, with); + } +#elif BOOST_WORKAROUND(BOOST_MSVC, > 1500) + // + // MSVC 10 will either emit warnings or else refuse to compile + // code that makes perfectly legitimate use of std::copy, when + // the OutputIterator type is a user-defined class (apparently all user + // defined iterators are "unsafe"). What's more Microsoft have removed their + // non-standard "unchecked" versions, even though their still in the MS + // documentation!! Work around this as best we can: + // + template + inline OutputIterator copy( + InputIterator first, + InputIterator last, + OutputIterator dest + ) + { + while(first != last) + *dest++ = *first++; + return dest; + } + template + inline bool equal( + InputIterator1 first, + InputIterator1 last, + InputIterator2 with + ) + { + while(first != last) + if(*first++ != *with++) return false; + return true; + } +#else + using std::copy; + using std::equal; +#endif +#if BOOST_WORKAROUND(BOOST_MSVC,>=1400) && defined(__STDC_WANT_SECURE_LIB__) && __STDC_WANT_SECURE_LIB__ + + // use safe versions of strcpy etc: + using ::strcpy_s; + using ::strcat_s; +#else + inline std::size_t strcpy_s( + char *strDestination, + std::size_t sizeInBytes, + const char *strSource + ) + { + std::size_t lenSourceWithNull = std::strlen(strSource) + 1; + if (lenSourceWithNull > sizeInBytes) + return 1; + std::memcpy(strDestination, strSource, lenSourceWithNull); + return 0; + } + inline std::size_t strcat_s( + char *strDestination, + std::size_t sizeInBytes, + const char *strSource + ) + { + std::size_t lenSourceWithNull = std::strlen(strSource) + 1; + std::size_t lenDestination = std::strlen(strDestination); + if (lenSourceWithNull + lenDestination > sizeInBytes) + return 1; + std::memcpy(strDestination + lenDestination, strSource, lenSourceWithNull); + return 0; + } + +#endif + + inline void overflow_error_if_not_zero(std::size_t i) + { + if(i) + { + std::overflow_error e("String buffer too small"); + boost::throw_exception(e); + } + } + +}} // namespaces + +#endif // __cplusplus + +#endif // include guard + diff --git a/boost/regex/v4/states.hpp b/boost/regex/v4/states.hpp new file mode 100644 index 00000000..86eb02b1 --- /dev/null +++ b/boost/regex/v4/states.hpp @@ -0,0 +1,321 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE states.cpp + * VERSION see + * DESCRIPTION: Declares internal state machine structures. + */ + +#ifndef BOOST_REGEX_V4_STATES_HPP +#define BOOST_REGEX_V4_STATES_HPP + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +/*** mask_type ******************************************************* +Whenever we have a choice of two alternatives, we use an array of bytes +to indicate which of the two alternatives it is possible to take for any +given input character. If mask_take is set, then we can take the next +state, and if mask_skip is set then we can take the alternative. +***********************************************************************/ +enum mask_type +{ + mask_take = 1, + mask_skip = 2, + mask_init = 4, + mask_any = mask_skip | mask_take, + mask_all = mask_any +}; + +/*** helpers ********************************************************** +These helpers let us use function overload resolution to detect whether +we have narrow or wide character strings: +***********************************************************************/ +struct _narrow_type{}; +struct _wide_type{}; +template struct is_byte; +template<> struct is_byte { typedef _narrow_type width_type; }; +template<> struct is_byte{ typedef _narrow_type width_type; }; +template<> struct is_byte { typedef _narrow_type width_type; }; +template struct is_byte { typedef _wide_type width_type; }; + +/*** enum syntax_element_type ****************************************** +Every record in the state machine falls into one of the following types: +***********************************************************************/ +enum syntax_element_type +{ + // start of a marked sub-expression, or perl-style (?...) extension + syntax_element_startmark = 0, + // end of a marked sub-expression, or perl-style (?...) extension + syntax_element_endmark = syntax_element_startmark + 1, + // any sequence of literal characters + syntax_element_literal = syntax_element_endmark + 1, + // start of line assertion: ^ + syntax_element_start_line = syntax_element_literal + 1, + // end of line assertion $ + syntax_element_end_line = syntax_element_start_line + 1, + // match any character: . + syntax_element_wild = syntax_element_end_line + 1, + // end of expression: we have a match when we get here + syntax_element_match = syntax_element_wild + 1, + // perl style word boundary: \b + syntax_element_word_boundary = syntax_element_match + 1, + // perl style within word boundary: \B + syntax_element_within_word = syntax_element_word_boundary + 1, + // start of word assertion: \< + syntax_element_word_start = syntax_element_within_word + 1, + // end of word assertion: \> + syntax_element_word_end = syntax_element_word_start + 1, + // start of buffer assertion: \` + syntax_element_buffer_start = syntax_element_word_end + 1, + // end of buffer assertion: \' + syntax_element_buffer_end = syntax_element_buffer_start + 1, + // backreference to previously matched sub-expression + syntax_element_backref = syntax_element_buffer_end + 1, + // either a wide character set [..] or one with multicharacter collating elements: + syntax_element_long_set = syntax_element_backref + 1, + // narrow character set: [...] + syntax_element_set = syntax_element_long_set + 1, + // jump to a new state in the machine: + syntax_element_jump = syntax_element_set + 1, + // choose between two production states: + syntax_element_alt = syntax_element_jump + 1, + // a repeat + syntax_element_rep = syntax_element_alt + 1, + // match a combining character sequence + syntax_element_combining = syntax_element_rep + 1, + // perl style soft buffer end: \z + syntax_element_soft_buffer_end = syntax_element_combining + 1, + // perl style continuation: \G + syntax_element_restart_continue = syntax_element_soft_buffer_end + 1, + // single character repeats: + syntax_element_dot_rep = syntax_element_restart_continue + 1, + syntax_element_char_rep = syntax_element_dot_rep + 1, + syntax_element_short_set_rep = syntax_element_char_rep + 1, + syntax_element_long_set_rep = syntax_element_short_set_rep + 1, + // a backstep for lookbehind repeats: + syntax_element_backstep = syntax_element_long_set_rep + 1, + // an assertion that a mark was matched: + syntax_element_assert_backref = syntax_element_backstep + 1, + syntax_element_toggle_case = syntax_element_assert_backref + 1, + // a recursive expression: + syntax_element_recurse = syntax_element_toggle_case + 1, + // Verbs: + syntax_element_fail = syntax_element_recurse + 1, + syntax_element_accept = syntax_element_fail + 1, + syntax_element_commit = syntax_element_accept + 1, + syntax_element_then = syntax_element_commit + 1 +}; + +#ifdef BOOST_REGEX_DEBUG +// dwa 09/26/00 - This is needed to suppress warnings about an ambiguous conversion +std::ostream& operator<<(std::ostream&, syntax_element_type); +#endif + +struct re_syntax_base; + +/*** union offset_type ************************************************ +Points to another state in the machine. During machine construction +we use integral offsets, but these are converted to pointers before +execution of the machine. +***********************************************************************/ +union offset_type +{ + re_syntax_base* p; + std::ptrdiff_t i; +}; + +/*** struct re_syntax_base ******************************************** +Base class for all states in the machine. +***********************************************************************/ +struct re_syntax_base +{ + syntax_element_type type; // what kind of state this is + offset_type next; // next state in the machine +}; + +/*** struct re_brace ************************************************** +A marked parenthesis. +***********************************************************************/ +struct re_brace : public re_syntax_base +{ + // The index to match, can be zero (don't mark the sub-expression) + // or negative (for perl style (?...) extensions): + int index; + bool icase; +}; + +/*** struct re_dot ************************************************** +Match anything. +***********************************************************************/ +enum +{ + dont_care = 1, + force_not_newline = 0, + force_newline = 2, + + test_not_newline = 2, + test_newline = 3 +}; +struct re_dot : public re_syntax_base +{ + unsigned char mask; +}; + +/*** struct re_literal ************************************************ +A string of literals, following this structure will be an +array of characters: charT[length] +***********************************************************************/ +struct re_literal : public re_syntax_base +{ + unsigned int length; +}; + +/*** struct re_case ************************************************ +Indicates whether we are moving to a case insensive block or not +***********************************************************************/ +struct re_case : public re_syntax_base +{ + bool icase; +}; + +/*** struct re_set_long *********************************************** +A wide character set of characters, following this structure will be +an array of type charT: +First csingles null-terminated strings +Then 2 * cranges NULL terminated strings +Then cequivalents NULL terminated strings +***********************************************************************/ +template +struct re_set_long : public re_syntax_base +{ + unsigned int csingles, cranges, cequivalents; + mask_type cclasses; + mask_type cnclasses; + bool isnot; + bool singleton; +}; + +/*** struct re_set **************************************************** +A set of narrow-characters, matches any of _map which is none-zero +***********************************************************************/ +struct re_set : public re_syntax_base +{ + unsigned char _map[1 << CHAR_BIT]; +}; + +/*** struct re_jump *************************************************** +Jump to a new location in the machine (not next). +***********************************************************************/ +struct re_jump : public re_syntax_base +{ + offset_type alt; // location to jump to +}; + +/*** struct re_alt *************************************************** +Jump to a new location in the machine (possibly next). +***********************************************************************/ +struct re_alt : public re_jump +{ + unsigned char _map[1 << CHAR_BIT]; // which characters can take the jump + unsigned int can_be_null; // true if we match a NULL string +}; + +/*** struct re_repeat ************************************************* +Repeat a section of the machine +***********************************************************************/ +struct re_repeat : public re_alt +{ + std::size_t min, max; // min and max allowable repeats + int state_id; // Unique identifier for this repeat + bool leading; // True if this repeat is at the start of the machine (lets us optimize some searches) + bool greedy; // True if this is a greedy repeat +}; + +/*** struct re_recurse ************************************************ +Recurse to a particular subexpression. +**********************************************************************/ +struct re_recurse : public re_jump +{ + int state_id; // identifier of first nested repeat within the recursion. +}; + +/*** struct re_commit ************************************************* +Used for the PRUNE, SKIP and COMMIT verbs which basically differ only in what happens +if no match is found and we start searching forward. +**********************************************************************/ +enum commit_type +{ + commit_prune, + commit_skip, + commit_commit +}; +struct re_commit : public re_syntax_base +{ + commit_type action; +}; + +/*** enum re_jump_size_type ******************************************* +Provides compiled size of re_jump structure (allowing for trailing alignment). +We provide this so we know how manybytes to insert when constructing the machine +(The value of padding_mask is defined in regex_raw_buffer.hpp). +***********************************************************************/ +enum re_jump_size_type +{ + re_jump_size = (sizeof(re_jump) + padding_mask) & ~(padding_mask), + re_repeater_size = (sizeof(re_repeat) + padding_mask) & ~(padding_mask), + re_alt_size = (sizeof(re_alt) + padding_mask) & ~(padding_mask) +}; + +/*** proc re_is_set_member ********************************************* +Forward declaration: we'll need this one later... +***********************************************************************/ + +template +struct regex_data; + +template +iterator BOOST_REGEX_CALL re_is_set_member(iterator next, + iterator last, + const re_set_long* set_, + const regex_data& e, bool icase); + +} // namespace BOOST_REGEX_DETAIL_NS + +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif + + diff --git a/boost/regex/v4/sub_match.hpp b/boost/regex/v4/sub_match.hpp new file mode 100644 index 00000000..30a580d5 --- /dev/null +++ b/boost/regex/v4/sub_match.hpp @@ -0,0 +1,516 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE sub_match.cpp + * VERSION see + * DESCRIPTION: Declares template class sub_match. + */ + +#ifndef BOOST_REGEX_V4_SUB_MATCH_HPP +#define BOOST_REGEX_V4_SUB_MATCH_HPP + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +namespace boost{ + +template +struct sub_match : public std::pair +{ + typedef typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type value_type; +#if defined(BOOST_NO_STD_ITERATOR_TRAITS) + typedef std::ptrdiff_t difference_type; +#else + typedef typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::difference_type difference_type; +#endif + typedef BidiIterator iterator_type; + typedef BidiIterator iterator; + typedef BidiIterator const_iterator; + + bool matched; + + sub_match() : std::pair(), matched(false) {} + sub_match(BidiIterator i) : std::pair(i, i), matched(false) {} +#if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\ + && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0551)\ + && !BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) + template + operator std::basic_string ()const + { + return matched ? std::basic_string(this->first, this->second) : std::basic_string(); + } +#else + operator std::basic_string ()const + { + return str(); + } +#endif + difference_type BOOST_REGEX_CALL length()const + { + difference_type n = matched ? ::boost::BOOST_REGEX_DETAIL_NS::distance((BidiIterator)this->first, (BidiIterator)this->second) : 0; + return n; + } + std::basic_string str()const + { + std::basic_string result; + if(matched) + { + std::size_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance((BidiIterator)this->first, (BidiIterator)this->second); + result.reserve(len); + BidiIterator i = this->first; + while(i != this->second) + { + result.append(1, *i); + ++i; + } + } + return result; + } + int compare(const sub_match& s)const + { + if(matched != s.matched) + return static_cast(matched) - static_cast(s.matched); + return str().compare(s.str()); + } + int compare(const std::basic_string& s)const + { + return str().compare(s); + } + int compare(const value_type* p)const + { + return str().compare(p); + } + + bool operator==(const sub_match& that)const + { return compare(that) == 0; } + bool BOOST_REGEX_CALL operator !=(const sub_match& that)const + { return compare(that) != 0; } + bool operator<(const sub_match& that)const + { return compare(that) < 0; } + bool operator>(const sub_match& that)const + { return compare(that) > 0; } + bool operator<=(const sub_match& that)const + { return compare(that) <= 0; } + bool operator>=(const sub_match& that)const + { return compare(that) >= 0; } + +#ifdef BOOST_REGEX_MATCH_EXTRA + typedef std::vector > capture_sequence_type; + + const capture_sequence_type& captures()const + { + if(!m_captures) + m_captures.reset(new capture_sequence_type()); + return *m_captures; + } + // + // Private implementation API: DO NOT USE! + // + capture_sequence_type& get_captures()const + { + if(!m_captures) + m_captures.reset(new capture_sequence_type()); + return *m_captures; + } + +private: + mutable boost::scoped_ptr m_captures; +public: + +#endif + sub_match(const sub_match& that, bool +#ifdef BOOST_REGEX_MATCH_EXTRA + deep_copy +#endif + = true + ) + : std::pair(that), + matched(that.matched) + { +#ifdef BOOST_REGEX_MATCH_EXTRA + if(that.m_captures) + if(deep_copy) + m_captures.reset(new capture_sequence_type(*(that.m_captures))); +#endif + } + sub_match& operator=(const sub_match& that) + { + this->first = that.first; + this->second = that.second; + matched = that.matched; +#ifdef BOOST_REGEX_MATCH_EXTRA + if(that.m_captures) + get_captures() = *(that.m_captures); +#endif + return *this; + } + // + // Make this type a range, for both Boost.Range, and C++11: + // + BidiIterator begin()const { return this->first; } + BidiIterator end()const { return this->second; } + + +#ifdef BOOST_OLD_REGEX_H + // + // the following are deprecated, do not use!! + // + operator int()const; + operator unsigned int()const; + operator short()const + { + return (short)(int)(*this); + } + operator unsigned short()const + { + return (unsigned short)(unsigned int)(*this); + } +#endif +}; + +typedef sub_match csub_match; +typedef sub_match ssub_match; +#ifndef BOOST_NO_WREGEX +typedef sub_match wcsub_match; +typedef sub_match wssub_match; +#endif + +// comparison to std::basic_string<> part 1: +template +inline bool operator == (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ return s.compare(m.str()) == 0; } +template +inline bool operator != (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ return s.compare(m.str()) != 0; } +template +inline bool operator < (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ return s.compare(m.str()) < 0; } +template +inline bool operator <= (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ return s.compare(m.str()) <= 0; } +template +inline bool operator >= (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ return s.compare(m.str()) >= 0; } +template +inline bool operator > (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ return s.compare(m.str()) > 0; } +// comparison to std::basic_string<> part 2: +template +inline bool operator == (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ return m.str().compare(s) == 0; } +template +inline bool operator != (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ return m.str().compare(s) != 0; } +template +inline bool operator < (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ return m.str().compare(s) < 0; } +template +inline bool operator > (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ return m.str().compare(s) > 0; } +template +inline bool operator <= (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ return m.str().compare(s) <= 0; } +template +inline bool operator >= (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ return m.str().compare(s) >= 0; } +// comparison to const charT* part 1: +template +inline bool operator == (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s) +{ return m.str().compare(s) == 0; } +template +inline bool operator != (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s) +{ return m.str().compare(s) != 0; } +template +inline bool operator > (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s) +{ return m.str().compare(s) > 0; } +template +inline bool operator < (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s) +{ return m.str().compare(s) < 0; } +template +inline bool operator >= (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s) +{ return m.str().compare(s) >= 0; } +template +inline bool operator <= (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s) +{ return m.str().compare(s) <= 0; } +// comparison to const charT* part 2: +template +inline bool operator == (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s, + const sub_match& m) +{ return m.str().compare(s) == 0; } +template +inline bool operator != (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s, + const sub_match& m) +{ return m.str().compare(s) != 0; } +template +inline bool operator < (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s, + const sub_match& m) +{ return m.str().compare(s) > 0; } +template +inline bool operator > (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s, + const sub_match& m) +{ return m.str().compare(s) < 0; } +template +inline bool operator <= (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s, + const sub_match& m) +{ return m.str().compare(s) >= 0; } +template +inline bool operator >= (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s, + const sub_match& m) +{ return m.str().compare(s) <= 0; } + +// comparison to const charT& part 1: +template +inline bool operator == (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) == 0; } +template +inline bool operator != (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) != 0; } +template +inline bool operator > (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) > 0; } +template +inline bool operator < (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) < 0; } +template +inline bool operator >= (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) >= 0; } +template +inline bool operator <= (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) <= 0; } +// comparison to const charT* part 2: +template +inline bool operator == (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s, + const sub_match& m) +{ return m.str().compare(0, m.length(), &s, 1) == 0; } +template +inline bool operator != (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s, + const sub_match& m) +{ return m.str().compare(0, m.length(), &s, 1) != 0; } +template +inline bool operator < (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s, + const sub_match& m) +{ return m.str().compare(0, m.length(), &s, 1) > 0; } +template +inline bool operator > (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s, + const sub_match& m) +{ return m.str().compare(0, m.length(), &s, 1) < 0; } +template +inline bool operator <= (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s, + const sub_match& m) +{ return m.str().compare(0, m.length(), &s, 1) >= 0; } +template +inline bool operator >= (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s, + const sub_match& m) +{ return m.str().compare(0, m.length(), &s, 1) <= 0; } + +// addition operators: +template +inline std::basic_string::value_type, traits, Allocator> +operator + (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ + std::basic_string::value_type, traits, Allocator> result; + result.reserve(s.size() + m.length() + 1); + return result.append(s).append(m.first, m.second); +} +template +inline std::basic_string::value_type, traits, Allocator> +operator + (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ + std::basic_string::value_type, traits, Allocator> result; + result.reserve(s.size() + m.length() + 1); + return result.append(m.first, m.second).append(s); +} +#if !(defined(__GNUC__) && defined(BOOST_NO_STD_LOCALE)) +template +inline std::basic_string::value_type> +operator + (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s, + const sub_match& m) +{ + std::basic_string::value_type> result; + result.reserve(std::char_traits::value_type>::length(s) + m.length() + 1); + return result.append(s).append(m.first, m.second); +} +template +inline std::basic_string::value_type> +operator + (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const * s) +{ + std::basic_string::value_type> result; + result.reserve(std::char_traits::value_type>::length(s) + m.length() + 1); + return result.append(m.first, m.second).append(s); +} +#else +// worwaround versions: +template +inline std::basic_string::value_type> +operator + (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const* s, + const sub_match& m) +{ + return s + m.str(); +} +template +inline std::basic_string::value_type> +operator + (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const * s) +{ + return m.str() + s; +} +#endif +template +inline std::basic_string::value_type> +operator + (typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s, + const sub_match& m) +{ + std::basic_string::value_type> result; + result.reserve(m.length() + 2); + return result.append(1, s).append(m.first, m.second); +} +template +inline std::basic_string::value_type> +operator + (const sub_match& m, + typename BOOST_REGEX_DETAIL_NS::regex_iterator_traits::value_type const& s) +{ + std::basic_string::value_type> result; + result.reserve(m.length() + 2); + return result.append(m.first, m.second).append(1, s); +} +template +inline std::basic_string::value_type> +operator + (const sub_match& m1, + const sub_match& m2) +{ + std::basic_string::value_type> result; + result.reserve(m1.length() + m2.length() + 1); + return result.append(m1.first, m1.second).append(m2.first, m2.second); +} +#ifndef BOOST_NO_STD_LOCALE +template +std::basic_ostream& + operator << (std::basic_ostream& os, + const sub_match& s) +{ + return (os << s.str()); +} +#else +template +std::ostream& operator << (std::ostream& os, + const sub_match& s) +{ + return (os << s.str()); +} +#endif + +#ifdef BOOST_OLD_REGEX_H +namespace BOOST_REGEX_DETAIL_NS{ +template +int do_toi(BidiIterator i, BidiIterator j, char c, int radix) +{ + std::string s(i, j); + char* p; + int result = std::strtol(s.c_str(), &p, radix); + if(*p)raise_regex_exception("Bad sub-expression"); + return result; +} + +// +// helper: +template +int do_toi(I& i, I j, charT c) +{ + int result = 0; + while((i != j) && (isdigit(*i))) + { + result = result*10 + (*i - '0'); + ++i; + } + return result; +} +} + + +template +sub_match::operator int()const +{ + BidiIterator i = first; + BidiIterator j = second; + if(i == j)raise_regex_exception("Bad sub-expression"); + int neg = 1; + if((i != j) && (*i == '-')) + { + neg = -1; + ++i; + } + neg *= BOOST_REGEX_DETAIL_NS::do_toi(i, j, *i); + if(i != j)raise_regex_exception("Bad sub-expression"); + return neg; +} +template +sub_match::operator unsigned int()const +{ + BidiIterator i = first; + BidiIterator j = second; + if(i == j) + raise_regex_exception("Bad sub-expression"); + return BOOST_REGEX_DETAIL_NS::do_toi(i, j, *first); +} +#endif + +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif + diff --git a/boost/regex/v4/syntax_type.hpp b/boost/regex/v4/syntax_type.hpp new file mode 100644 index 00000000..3efdf0b0 --- /dev/null +++ b/boost/regex/v4/syntax_type.hpp @@ -0,0 +1,105 @@ +/* + * + * Copyright (c) 2003 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE syntax_type.hpp + * VERSION see + * DESCRIPTION: Declares regular expression synatx type enumerator. + */ + +#ifndef BOOST_REGEX_SYNTAX_TYPE_HPP +#define BOOST_REGEX_SYNTAX_TYPE_HPP + +namespace boost{ +namespace regex_constants{ + +typedef unsigned char syntax_type; + +// +// values chosen are binary compatible with previous version: +// +static const syntax_type syntax_char = 0; +static const syntax_type syntax_open_mark = 1; +static const syntax_type syntax_close_mark = 2; +static const syntax_type syntax_dollar = 3; +static const syntax_type syntax_caret = 4; +static const syntax_type syntax_dot = 5; +static const syntax_type syntax_star = 6; +static const syntax_type syntax_plus = 7; +static const syntax_type syntax_question = 8; +static const syntax_type syntax_open_set = 9; +static const syntax_type syntax_close_set = 10; +static const syntax_type syntax_or = 11; +static const syntax_type syntax_escape = 12; +static const syntax_type syntax_dash = 14; +static const syntax_type syntax_open_brace = 15; +static const syntax_type syntax_close_brace = 16; +static const syntax_type syntax_digit = 17; +static const syntax_type syntax_comma = 27; +static const syntax_type syntax_equal = 37; +static const syntax_type syntax_colon = 36; +static const syntax_type syntax_not = 53; + +// extensions: + +static const syntax_type syntax_hash = 13; +static const syntax_type syntax_newline = 26; + +// escapes: + +typedef syntax_type escape_syntax_type; + +static const escape_syntax_type escape_type_word_assert = 18; +static const escape_syntax_type escape_type_not_word_assert = 19; +static const escape_syntax_type escape_type_control_f = 29; +static const escape_syntax_type escape_type_control_n = 30; +static const escape_syntax_type escape_type_control_r = 31; +static const escape_syntax_type escape_type_control_t = 32; +static const escape_syntax_type escape_type_control_v = 33; +static const escape_syntax_type escape_type_ascii_control = 35; +static const escape_syntax_type escape_type_hex = 34; +static const escape_syntax_type escape_type_unicode = 0; // not used +static const escape_syntax_type escape_type_identity = 0; // not used +static const escape_syntax_type escape_type_backref = syntax_digit; +static const escape_syntax_type escape_type_decimal = syntax_digit; // not used +static const escape_syntax_type escape_type_class = 22; +static const escape_syntax_type escape_type_not_class = 23; + +// extensions: + +static const escape_syntax_type escape_type_left_word = 20; +static const escape_syntax_type escape_type_right_word = 21; +static const escape_syntax_type escape_type_start_buffer = 24; // for \` +static const escape_syntax_type escape_type_end_buffer = 25; // for \' +static const escape_syntax_type escape_type_control_a = 28; // for \a +static const escape_syntax_type escape_type_e = 38; // for \e +static const escape_syntax_type escape_type_E = 47; // for \Q\E +static const escape_syntax_type escape_type_Q = 48; // for \Q\E +static const escape_syntax_type escape_type_X = 49; // for \X +static const escape_syntax_type escape_type_C = 50; // for \C +static const escape_syntax_type escape_type_Z = 51; // for \Z +static const escape_syntax_type escape_type_G = 52; // for \G + +static const escape_syntax_type escape_type_property = 54; // for \p +static const escape_syntax_type escape_type_not_property = 55; // for \P +static const escape_syntax_type escape_type_named_char = 56; // for \N +static const escape_syntax_type escape_type_extended_backref = 57; // for \g +static const escape_syntax_type escape_type_reset_start_mark = 58; // for \K +static const escape_syntax_type escape_type_line_ending = 59; // for \R + +static const escape_syntax_type syntax_max = 60; + +} +} + + +#endif diff --git a/boost/regex/v4/w32_regex_traits.hpp b/boost/regex/v4/w32_regex_traits.hpp new file mode 100644 index 00000000..e1ac5d5f --- /dev/null +++ b/boost/regex/v4/w32_regex_traits.hpp @@ -0,0 +1,1229 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE w32_regex_traits.hpp + * VERSION see + * DESCRIPTION: Declares regular expression traits class w32_regex_traits. + */ + +#ifndef BOOST_W32_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_W32_REGEX_TRAITS_HPP_INCLUDED + +#ifndef BOOST_REGEX_NO_WIN32_LOCALE + +#ifndef BOOST_RE_PAT_EXCEPT_HPP +#include +#endif +#ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED +#include +#endif +#ifdef BOOST_HAS_THREADS +#include +#endif +#ifndef BOOST_REGEX_PRIMARY_TRANSFORM +#include +#endif +#ifndef BOOST_REGEX_OBJECT_CACHE_HPP +#include +#endif + +#define VC_EXTRALEAN +#define WIN32_LEAN_AND_MEAN +#include + +#if defined(_MSC_VER) && !defined(_WIN32_WCE) && !defined(UNDER_CE) +#pragma comment(lib, "user32.lib") +#endif + + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4786) +#if BOOST_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +namespace boost{ + +// +// forward declaration is needed by some compilers: +// +template +class w32_regex_traits; + +namespace BOOST_REGEX_DETAIL_NS{ + +// +// start by typedeffing the types we'll need: +// +typedef ::boost::uint32_t lcid_type; // placeholder for LCID. +typedef ::boost::shared_ptr cat_type; // placeholder for dll HANDLE. + +// +// then add wrappers around the actual Win32 API's (ie implementation hiding): +// +lcid_type BOOST_REGEX_CALL w32_get_default_locale(); +bool BOOST_REGEX_CALL w32_is_lower(char, lcid_type); +#ifndef BOOST_NO_WREGEX +bool BOOST_REGEX_CALL w32_is_lower(wchar_t, lcid_type); +#endif +bool BOOST_REGEX_CALL w32_is_upper(char, lcid_type); +#ifndef BOOST_NO_WREGEX +bool BOOST_REGEX_CALL w32_is_upper(wchar_t, lcid_type); +#endif +cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name); +std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::string& def); +#ifndef BOOST_NO_WREGEX +std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::wstring& def); +#endif +std::string BOOST_REGEX_CALL w32_transform(lcid_type state_id, const char* p1, const char* p2); +#ifndef BOOST_NO_WREGEX +std::wstring BOOST_REGEX_CALL w32_transform(lcid_type state_id, const wchar_t* p1, const wchar_t* p2); +#endif +char BOOST_REGEX_CALL w32_tolower(char c, lcid_type); +#ifndef BOOST_NO_WREGEX +wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type); +#endif +char BOOST_REGEX_CALL w32_toupper(char c, lcid_type); +#ifndef BOOST_NO_WREGEX +wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type); +#endif +bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, char c); +#ifndef BOOST_NO_WREGEX +bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, wchar_t c); +#endif +// +// class w32_regex_traits_base: +// acts as a container for locale and the facets we are using. +// +template +struct w32_regex_traits_base +{ + w32_regex_traits_base(lcid_type l) + { imbue(l); } + lcid_type imbue(lcid_type l); + + lcid_type m_locale; +}; + +template +inline lcid_type w32_regex_traits_base::imbue(lcid_type l) +{ + lcid_type result(m_locale); + m_locale = l; + return result; +} + +// +// class w32_regex_traits_char_layer: +// implements methods that require specialisation for narrow characters: +// +template +class w32_regex_traits_char_layer : public w32_regex_traits_base +{ + typedef std::basic_string string_type; + typedef std::map map_type; + typedef typename map_type::const_iterator map_iterator_type; +public: + w32_regex_traits_char_layer(const lcid_type l); + + regex_constants::syntax_type syntax_type(charT c)const + { + map_iterator_type i = m_char_map.find(c); + return ((i == m_char_map.end()) ? 0 : i->second); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + map_iterator_type i = m_char_map.find(c); + if(i == m_char_map.end()) + { + if(::boost::BOOST_REGEX_DETAIL_NS::w32_is_lower(c, this->m_locale)) return regex_constants::escape_type_class; + if(::boost::BOOST_REGEX_DETAIL_NS::w32_is_upper(c, this->m_locale)) return regex_constants::escape_type_not_class; + return 0; + } + return i->second; + } + charT tolower(charT c)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::w32_tolower(c, this->m_locale); + } + bool isctype(boost::uint32_t mask, charT c)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, mask, c); + } + +private: + string_type get_default_message(regex_constants::syntax_type); + // TODO: use a hash table when available! + map_type m_char_map; +}; + +template +w32_regex_traits_char_layer::w32_regex_traits_char_layer(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l) + : w32_regex_traits_base(l) +{ + // we need to start by initialising our syntax map so we know which + // character is used for which purpose: + cat_type cat; + std::string cat_name(w32_regex_traits::get_catalog_name()); + if(cat_name.size()) + { + cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name); + if(!cat) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if(cat) + { + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + string_type mss = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i, get_default_message(i)); + for(typename string_type::size_type j = 0; j < mss.size(); ++j) + { + this->m_char_map[mss[j]] = i; + } + } + } + else + { + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + const char* ptr = get_default_syntax(i); + while(ptr && *ptr) + { + this->m_char_map[static_cast(*ptr)] = i; + ++ptr; + } + } + } +} + +template +typename w32_regex_traits_char_layer::string_type + w32_regex_traits_char_layer::get_default_message(regex_constants::syntax_type i) +{ + const char* ptr = get_default_syntax(i); + string_type result; + while(ptr && *ptr) + { + result.append(1, static_cast(*ptr)); + ++ptr; + } + return result; +} + +// +// specialised version for narrow characters: +// +template <> +class w32_regex_traits_char_layer : public w32_regex_traits_base +{ + typedef std::string string_type; +public: + w32_regex_traits_char_layer(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l) + : w32_regex_traits_base(l) + { + init(); + } + + regex_constants::syntax_type syntax_type(char c)const + { + return m_char_map[static_cast(c)]; + } + regex_constants::escape_syntax_type escape_syntax_type(char c) const + { + return m_char_map[static_cast(c)]; + } + char tolower(char c)const + { + return m_lower_map[static_cast(c)]; + } + bool isctype(boost::uint32_t mask, char c)const + { + return m_type_map[static_cast(c)] & mask; + } + +private: + regex_constants::syntax_type m_char_map[1u << CHAR_BIT]; + char m_lower_map[1u << CHAR_BIT]; + boost::uint16_t m_type_map[1u << CHAR_BIT]; + template + void init(); +}; + +// +// class w32_regex_traits_implementation: +// provides pimpl implementation for w32_regex_traits. +// +template +class w32_regex_traits_implementation : public w32_regex_traits_char_layer +{ +public: + typedef typename w32_regex_traits::char_class_type char_class_type; + BOOST_STATIC_CONSTANT(char_class_type, mask_word = 0x0400); // must be C1_DEFINED << 1 + BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 0x0800); // must be C1_DEFINED << 2 + BOOST_STATIC_CONSTANT(char_class_type, mask_horizontal = 0x1000); // must be C1_DEFINED << 3 + BOOST_STATIC_CONSTANT(char_class_type, mask_vertical = 0x2000); // must be C1_DEFINED << 4 + BOOST_STATIC_CONSTANT(char_class_type, mask_base = 0x3ff); // all the masks used by the CT_CTYPE1 group + + typedef std::basic_string string_type; + typedef charT char_type; + w32_regex_traits_implementation(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l); + std::string error_string(regex_constants::error_type n) const + { + if(!m_error_strings.empty()) + { + std::map::const_iterator p = m_error_strings.find(n); + return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second; + } + return get_default_error_string(n); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + char_class_type result = lookup_classname_imp(p1, p2); + if(result == 0) + { + typedef typename string_type::size_type size_type; + string_type temp(p1, p2); + for(size_type i = 0; i < temp.size(); ++i) + temp[i] = this->tolower(temp[i]); + result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size()); + } + return result; + } + string_type lookup_collatename(const charT* p1, const charT* p2) const; + string_type transform_primary(const charT* p1, const charT* p2) const; + string_type transform(const charT* p1, const charT* p2) const + { + return ::boost::BOOST_REGEX_DETAIL_NS::w32_transform(this->m_locale, p1, p2); + } +private: + std::map m_error_strings; // error messages indexed by numberic ID + std::map m_custom_class_names; // character class names + std::map m_custom_collate_names; // collating element names + unsigned m_collate_type; // the form of the collation string + charT m_collate_delim; // the collation group delimiter + // + // helpers: + // + char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const; +}; + +template +typename w32_regex_traits_implementation::string_type + w32_regex_traits_implementation::transform_primary(const charT* p1, const charT* p2) const +{ + string_type result; + // + // What we do here depends upon the format of the sort key returned by + // sort key returned by this->transform: + // + switch(m_collate_type) + { + case sort_C: + case sort_unknown: + // the best we can do is translate to lower case, then get a regular sort key: + { + result.assign(p1, p2); + typedef typename string_type::size_type size_type; + for(size_type i = 0; i < result.size(); ++i) + result[i] = this->tolower(result[i]); + result = this->transform(&*result.begin(), &*result.begin() + result.size()); + break; + } + case sort_fixed: + { + // get a regular sort key, and then truncate it: + result.assign(this->transform(p1, p2)); + result.erase(this->m_collate_delim); + break; + } + case sort_delim: + // get a regular sort key, and then truncate everything after the delim: + result.assign(this->transform(p1, p2)); + std::size_t i; + for(i = 0; i < result.size(); ++i) + { + if(result[i] == m_collate_delim) + break; + } + result.erase(i); + break; + } + if(result.empty()) + result = string_type(1, charT(0)); + return result; +} + +template +typename w32_regex_traits_implementation::string_type + w32_regex_traits_implementation::lookup_collatename(const charT* p1, const charT* p2) const +{ + typedef typename std::map::const_iterator iter_type; + if(m_custom_collate_names.size()) + { + iter_type pos = m_custom_collate_names.find(string_type(p1, p2)); + if(pos != m_custom_collate_names.end()) + return pos->second; + } +#if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\ + && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0551) + std::string name(p1, p2); +#else + std::string name; + const charT* p0 = p1; + while(p0 != p2) + name.append(1, char(*p0++)); +#endif + name = lookup_default_collate_name(name); +#if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)\ + && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x0551) + if(name.size()) + return string_type(name.begin(), name.end()); +#else + if(name.size()) + { + string_type result; + typedef std::string::const_iterator iter; + iter b = name.begin(); + iter e = name.end(); + while(b != e) + result.append(1, charT(*b++)); + return result; + } +#endif + if(p2 - p1 == 1) + return string_type(1, *p1); + return string_type(); +} + +template +w32_regex_traits_implementation::w32_regex_traits_implementation(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l) +: w32_regex_traits_char_layer(l) +{ + cat_type cat; + std::string cat_name(w32_regex_traits::get_catalog_name()); + if(cat_name.size()) + { + cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name); + if(!cat) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if(cat) + { + // + // Error messages: + // + for(boost::regex_constants::error_type i = static_cast(0); + i <= boost::regex_constants::error_unknown; + i = static_cast(i + 1)) + { + const char* p = get_default_error_string(i); + string_type default_message; + while(*p) + { + default_message.append(1, static_cast(*p)); + ++p; + } + string_type s = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i+200, default_message); + std::string result; + for(std::string::size_type j = 0; j < s.size(); ++j) + { + result.append(1, static_cast(s[j])); + } + m_error_strings[i] = result; + } + // + // Custom class names: + // + static const char_class_type masks[14] = + { + 0x0104u, // C1_ALPHA | C1_DIGIT + 0x0100u, // C1_ALPHA + 0x0020u, // C1_CNTRL + 0x0004u, // C1_DIGIT + (~(0x0020u|0x0008u) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE + 0x0002u, // C1_LOWER + (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL + 0x0010u, // C1_PUNCT + 0x0008u, // C1_SPACE + 0x0001u, // C1_UPPER + 0x0080u, // C1_XDIGIT + 0x0040u, // C1_BLANK + w32_regex_traits_implementation::mask_word, + w32_regex_traits_implementation::mask_unicode, + }; + static const string_type null_string; + for(unsigned int j = 0; j <= 13; ++j) + { + string_type s(::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, j+300, null_string)); + if(s.size()) + this->m_custom_class_names[s] = masks[j]; + } + } + // + // get the collation format used by m_pcollate: + // + m_collate_type = BOOST_REGEX_DETAIL_NS::find_sort_syntax(this, &m_collate_delim); +} + +template +typename w32_regex_traits_implementation::char_class_type + w32_regex_traits_implementation::lookup_classname_imp(const charT* p1, const charT* p2) const +{ + static const char_class_type masks[22] = + { + 0, + 0x0104u, // C1_ALPHA | C1_DIGIT + 0x0100u, // C1_ALPHA + 0x0040u, // C1_BLANK + 0x0020u, // C1_CNTRL + 0x0004u, // C1_DIGIT + 0x0004u, // C1_DIGIT + (~(0x0020u|0x0008u|0x0040) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE or C1_BLANK + w32_regex_traits_implementation::mask_horizontal, + 0x0002u, // C1_LOWER + 0x0002u, // C1_LOWER + (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL + 0x0010u, // C1_PUNCT + 0x0008u, // C1_SPACE + 0x0008u, // C1_SPACE + 0x0001u, // C1_UPPER + w32_regex_traits_implementation::mask_unicode, + 0x0001u, // C1_UPPER + w32_regex_traits_implementation::mask_vertical, + 0x0104u | w32_regex_traits_implementation::mask_word, + 0x0104u | w32_regex_traits_implementation::mask_word, + 0x0080u, // C1_XDIGIT + }; + if(m_custom_class_names.size()) + { + typedef typename std::map, char_class_type>::const_iterator map_iter; + map_iter pos = m_custom_class_names.find(string_type(p1, p2)); + if(pos != m_custom_class_names.end()) + return pos->second; + } + std::size_t state_id = 1u + (std::size_t)BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2); + if(state_id < sizeof(masks) / sizeof(masks[0])) + return masks[state_id]; + return masks[0]; +} + + +template +boost::shared_ptr > create_w32_regex_traits(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l) +{ + // TODO: create a cache for previously constructed objects. + return boost::object_cache< ::boost::BOOST_REGEX_DETAIL_NS::lcid_type, w32_regex_traits_implementation >::get(l, 5); +} + +} // BOOST_REGEX_DETAIL_NS + +template +class w32_regex_traits +{ +public: + typedef charT char_type; + typedef std::size_t size_type; + typedef std::basic_string string_type; + typedef ::boost::BOOST_REGEX_DETAIL_NS::lcid_type locale_type; + typedef boost::uint_least32_t char_class_type; + + struct boost_extensions_tag{}; + + w32_regex_traits() + : m_pimpl(BOOST_REGEX_DETAIL_NS::create_w32_regex_traits(::boost::BOOST_REGEX_DETAIL_NS::w32_get_default_locale())) + { } + static size_type length(const char_type* p) + { + return std::char_traits::length(p); + } + regex_constants::syntax_type syntax_type(charT c)const + { + return m_pimpl->syntax_type(c); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + return m_pimpl->escape_syntax_type(c); + } + charT translate(charT c) const + { + return c; + } + charT translate_nocase(charT c) const + { + return this->m_pimpl->tolower(c); + } + charT translate(charT c, bool icase) const + { + return icase ? this->m_pimpl->tolower(c) : c; + } + charT tolower(charT c) const + { + return this->m_pimpl->tolower(c); + } + charT toupper(charT c) const + { + return ::boost::BOOST_REGEX_DETAIL_NS::w32_toupper(c, this->m_pimpl->m_locale); + } + string_type transform(const charT* p1, const charT* p2) const + { + return ::boost::BOOST_REGEX_DETAIL_NS::w32_transform(this->m_pimpl->m_locale, p1, p2); + } + string_type transform_primary(const charT* p1, const charT* p2) const + { + return m_pimpl->transform_primary(p1, p2); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_classname(p1, p2); + } + string_type lookup_collatename(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_collatename(p1, p2); + } + bool isctype(charT c, char_class_type f) const + { + if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_base) + && (this->m_pimpl->isctype(f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_base, c))) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_unicode) && BOOST_REGEX_DETAIL_NS::is_extended(c)) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_word) && (c == '_')) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_vertical) + && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v'))) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_horizontal) + && this->isctype(c, 0x0008u) && !this->isctype(c, BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_vertical)) + return true; + return false; + } + boost::intmax_t toi(const charT*& p1, const charT* p2, int radix)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::global_toi(p1, p2, radix, *this); + } + int value(charT c, int radix)const + { + int result = (int)::boost::BOOST_REGEX_DETAIL_NS::global_value(c); + return result < radix ? result : -1; + } + locale_type imbue(locale_type l) + { + ::boost::BOOST_REGEX_DETAIL_NS::lcid_type result(getloc()); + m_pimpl = BOOST_REGEX_DETAIL_NS::create_w32_regex_traits(l); + return result; + } + locale_type getloc()const + { + return m_pimpl->m_locale; + } + std::string error_string(regex_constants::error_type n) const + { + return m_pimpl->error_string(n); + } + + // + // extension: + // set the name of the message catalog in use (defaults to "boost_regex"). + // + static std::string catalog_name(const std::string& name); + static std::string get_catalog_name(); + +private: + boost::shared_ptr > m_pimpl; + // + // catalog name handler: + // + static std::string& get_catalog_name_inst(); + +#ifdef BOOST_HAS_THREADS + static static_mutex& get_mutex_inst(); +#endif +}; + +template +std::string w32_regex_traits::catalog_name(const std::string& name) +{ +#ifdef BOOST_HAS_THREADS + static_mutex::scoped_lock lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + get_catalog_name_inst() = name; + return result; +} + +template +std::string& w32_regex_traits::get_catalog_name_inst() +{ + static std::string s_name; + return s_name; +} + +template +std::string w32_regex_traits::get_catalog_name() +{ +#ifdef BOOST_HAS_THREADS + static_mutex::scoped_lock lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + return result; +} + +#ifdef BOOST_HAS_THREADS +template +static_mutex& w32_regex_traits::get_mutex_inst() +{ + static static_mutex s_mutex = BOOST_STATIC_MUTEX_INIT; + return s_mutex; +} +#endif + +namespace BOOST_REGEX_DETAIL_NS { + +#ifdef BOOST_NO_ANSI_APIS + inline UINT get_code_page_for_locale_id(lcid_type idx) + { + WCHAR code_page_string[7]; + if (::GetLocaleInfoW(idx, LOCALE_IDEFAULTANSICODEPAGE, code_page_string, 7) == 0) + return 0; + + return static_cast(_wtol(code_page_string)); +} +#endif + + template + inline void w32_regex_traits_char_layer::init() + { + // we need to start by initialising our syntax map so we know which + // character is used for which purpose: + std::memset(m_char_map, 0, sizeof(m_char_map)); + cat_type cat; + std::string cat_name(w32_regex_traits::get_catalog_name()); + if (cat_name.size()) + { + cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name); + if (!cat) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + ::boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if (cat) + { + for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + string_type mss = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i, get_default_syntax(i)); + for (string_type::size_type j = 0; j < mss.size(); ++j) + { + m_char_map[static_cast(mss[j])] = i; + } + } + } + else + { + for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + const char* ptr = get_default_syntax(i); + while (ptr && *ptr) + { + m_char_map[static_cast(*ptr)] = i; + ++ptr; + } + } + } + // + // finish off by calculating our escape types: + // + unsigned char i = 'A'; + do + { + if (m_char_map[i] == 0) + { + if (::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, 0x0002u, (char)i)) + m_char_map[i] = regex_constants::escape_type_class; + else if (::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, 0x0001u, (char)i)) + m_char_map[i] = regex_constants::escape_type_not_class; + } + } while (0xFF != i++); + + // + // fill in lower case map: + // + char char_map[1 << CHAR_BIT]; + for (int ii = 0; ii < (1 << CHAR_BIT); ++ii) + char_map[ii] = static_cast(ii); +#ifndef BOOST_NO_ANSI_APIS + int r = ::LCMapStringA(this->m_locale, LCMAP_LOWERCASE, char_map, 1 << CHAR_BIT, this->m_lower_map, 1 << CHAR_BIT); + BOOST_REGEX_ASSERT(r != 0); +#else + UINT code_page = get_code_page_for_locale_id(this->m_locale); + BOOST_REGEX_ASSERT(code_page != 0); + + WCHAR wide_char_map[1 << CHAR_BIT]; + int conv_r = ::MultiByteToWideChar(code_page, 0, char_map, 1 << CHAR_BIT, wide_char_map, 1 << CHAR_BIT); + BOOST_REGEX_ASSERT(conv_r != 0); + + WCHAR wide_lower_map[1 << CHAR_BIT]; + int r = ::LCMapStringW(this->m_locale, LCMAP_LOWERCASE, wide_char_map, 1 << CHAR_BIT, wide_lower_map, 1 << CHAR_BIT); + BOOST_REGEX_ASSERT(r != 0); + + conv_r = ::WideCharToMultiByte(code_page, 0, wide_lower_map, r, this->m_lower_map, 1 << CHAR_BIT, NULL, NULL); + BOOST_REGEX_ASSERT(conv_r != 0); +#endif + if (r < (1 << CHAR_BIT)) + { + // if we have multibyte characters then not all may have been given + // a lower case mapping: + for (int jj = r; jj < (1 << CHAR_BIT); ++jj) + this->m_lower_map[jj] = static_cast(jj); + } + +#ifndef BOOST_NO_ANSI_APIS + r = ::GetStringTypeExA(this->m_locale, CT_CTYPE1, char_map, 1 << CHAR_BIT, this->m_type_map); +#else + r = ::GetStringTypeExW(this->m_locale, CT_CTYPE1, wide_char_map, 1 << CHAR_BIT, this->m_type_map); +#endif + BOOST_REGEX_ASSERT(0 != r); + } + + inline lcid_type BOOST_REGEX_CALL w32_get_default_locale() + { + return ::GetUserDefaultLCID(); + } + + inline bool BOOST_REGEX_CALL w32_is_lower(char c, lcid_type idx) + { +#ifndef BOOST_NO_ANSI_APIS + WORD mask; + if (::GetStringTypeExA(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_LOWER)) + return true; + return false; +#else + UINT code_page = get_code_page_for_locale_id(idx); + if (code_page == 0) + return false; + + WCHAR wide_c; + if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0) + return false; + + WORD mask; + if (::GetStringTypeExW(idx, CT_CTYPE1, &wide_c, 1, &mask) && (mask & C1_LOWER)) + return true; + return false; +#endif + } + + inline bool BOOST_REGEX_CALL w32_is_lower(wchar_t c, lcid_type idx) + { + WORD mask; + if (::GetStringTypeExW(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_LOWER)) + return true; + return false; + } + + inline bool BOOST_REGEX_CALL w32_is_upper(char c, lcid_type idx) + { +#ifndef BOOST_NO_ANSI_APIS + WORD mask; + if (::GetStringTypeExA(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_UPPER)) + return true; + return false; +#else + UINT code_page = get_code_page_for_locale_id(idx); + if (code_page == 0) + return false; + + WCHAR wide_c; + if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0) + return false; + + WORD mask; + if (::GetStringTypeExW(idx, CT_CTYPE1, &wide_c, 1, &mask) && (mask & C1_UPPER)) + return true; + return false; +#endif + } + + inline bool BOOST_REGEX_CALL w32_is_upper(wchar_t c, lcid_type idx) + { + WORD mask; + if (::GetStringTypeExW(idx, CT_CTYPE1, &c, 1, &mask) && (mask & C1_UPPER)) + return true; + return false; + } + + inline void free_module(void* mod) + { + ::FreeLibrary(static_cast(mod)); + } + + inline cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name) + { +#ifndef BOOST_NO_ANSI_APIS + cat_type result(::LoadLibraryA(name.c_str()), &free_module); + return result; +#else + LPWSTR wide_name = (LPWSTR)_alloca((name.size() + 1) * sizeof(WCHAR)); + if (::MultiByteToWideChar(CP_ACP, 0, name.c_str(), name.size(), wide_name, name.size() + 1) == 0) + return cat_type(); + + cat_type result(::LoadLibraryW(wide_name), &free_module); + return result; +#endif + } + + inline std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::string& def) + { +#ifndef BOOST_NO_ANSI_APIS + char buf[256]; + if (0 == ::LoadStringA( + static_cast(cat.get()), + i, + buf, + 256 + )) + { + return def; + } +#else + WCHAR wbuf[256]; + int r = ::LoadStringW( + static_cast(cat.get()), + i, + wbuf, + 256 + ); + if (r == 0) + return def; + + + int buf_size = 1 + ::WideCharToMultiByte(CP_ACP, 0, wbuf, r, NULL, 0, NULL, NULL); + LPSTR buf = (LPSTR)_alloca(buf_size); + if (::WideCharToMultiByte(CP_ACP, 0, wbuf, r, buf, buf_size, NULL, NULL) == 0) + return def; // failed conversion. +#endif + return std::string(buf); + } + +#ifndef BOOST_NO_WREGEX + inline std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type, int i, const std::wstring& def) + { + wchar_t buf[256]; + if (0 == ::LoadStringW( + static_cast(cat.get()), + i, + buf, + 256 + )) + { + return def; + } + return std::wstring(buf); + } +#endif + inline std::string BOOST_REGEX_CALL w32_transform(lcid_type idx, const char* p1, const char* p2) + { +#ifndef BOOST_NO_ANSI_APIS + int bytes = ::LCMapStringA( + idx, // locale identifier + LCMAP_SORTKEY, // mapping transformation type + p1, // source string + static_cast(p2 - p1), // number of characters in source string + 0, // destination buffer + 0 // size of destination buffer + ); + if (!bytes) + return std::string(p1, p2); + std::string result(++bytes, '\0'); + bytes = ::LCMapStringA( + idx, // locale identifier + LCMAP_SORTKEY, // mapping transformation type + p1, // source string + static_cast(p2 - p1), // number of characters in source string + &*result.begin(), // destination buffer + bytes // size of destination buffer + ); +#else + UINT code_page = get_code_page_for_locale_id(idx); + if (code_page == 0) + return std::string(p1, p2); + + int src_len = static_cast(p2 - p1); + LPWSTR wide_p1 = (LPWSTR)_alloca((src_len + 1) * 2); + if (::MultiByteToWideChar(code_page, 0, p1, src_len, wide_p1, src_len + 1) == 0) + return std::string(p1, p2); + + int bytes = ::LCMapStringW( + idx, // locale identifier + LCMAP_SORTKEY, // mapping transformation type + wide_p1, // source string + src_len, // number of characters in source string + 0, // destination buffer + 0 // size of destination buffer + ); + if (!bytes) + return std::string(p1, p2); + std::string result(++bytes, '\0'); + bytes = ::LCMapStringW( + idx, // locale identifier + LCMAP_SORTKEY, // mapping transformation type + wide_p1, // source string + src_len, // number of characters in source string + (LPWSTR) & *result.begin(), // destination buffer + bytes // size of destination buffer + ); +#endif + if (bytes > static_cast(result.size())) + return std::string(p1, p2); + while (result.size() && result[result.size() - 1] == '\0') + { + result.erase(result.size() - 1); + } + return result; + } + +#ifndef BOOST_NO_WREGEX + inline std::wstring BOOST_REGEX_CALL w32_transform(lcid_type idx, const wchar_t* p1, const wchar_t* p2) + { + int bytes = ::LCMapStringW( + idx, // locale identifier + LCMAP_SORTKEY, // mapping transformation type + p1, // source string + static_cast(p2 - p1), // number of characters in source string + 0, // destination buffer + 0 // size of destination buffer + ); + if (!bytes) + return std::wstring(p1, p2); + std::string result(++bytes, '\0'); + bytes = ::LCMapStringW( + idx, // locale identifier + LCMAP_SORTKEY, // mapping transformation type + p1, // source string + static_cast(p2 - p1), // number of characters in source string + reinterpret_cast(&*result.begin()), // destination buffer *of bytes* + bytes // size of destination buffer + ); + if (bytes > static_cast(result.size())) + return std::wstring(p1, p2); + while (result.size() && result[result.size() - 1] == L'\0') + { + result.erase(result.size() - 1); + } + std::wstring r2; + for (std::string::size_type i = 0; i < result.size(); ++i) + r2.append(1, static_cast(static_cast(result[i]))); + return r2; + } +#endif + inline char BOOST_REGEX_CALL w32_tolower(char c, lcid_type idx) + { + char result[2]; +#ifndef BOOST_NO_ANSI_APIS + int b = ::LCMapStringA( + idx, // locale identifier + LCMAP_LOWERCASE, // mapping transformation type + &c, // source string + 1, // number of characters in source string + result, // destination buffer + 1); // size of destination buffer + if (b == 0) + return c; +#else + UINT code_page = get_code_page_for_locale_id(idx); + if (code_page == 0) + return c; + + WCHAR wide_c; + if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0) + return c; + + WCHAR wide_result; + int b = ::LCMapStringW( + idx, // locale identifier + LCMAP_LOWERCASE, // mapping transformation type + &wide_c, // source string + 1, // number of characters in source string + &wide_result, // destination buffer + 1); // size of destination buffer + if (b == 0) + return c; + + if (::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0) + return c; // No single byte lower case equivalent available +#endif + return result[0]; + } + +#ifndef BOOST_NO_WREGEX + inline wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type idx) + { + wchar_t result[2]; + int b = ::LCMapStringW( + idx, // locale identifier + LCMAP_LOWERCASE, // mapping transformation type + &c, // source string + 1, // number of characters in source string + result, // destination buffer + 1); // size of destination buffer + if (b == 0) + return c; + return result[0]; + } +#endif + inline char BOOST_REGEX_CALL w32_toupper(char c, lcid_type idx) + { + char result[2]; +#ifndef BOOST_NO_ANSI_APIS + int b = ::LCMapStringA( + idx, // locale identifier + LCMAP_UPPERCASE, // mapping transformation type + &c, // source string + 1, // number of characters in source string + result, // destination buffer + 1); // size of destination buffer + if (b == 0) + return c; +#else + UINT code_page = get_code_page_for_locale_id(idx); + if (code_page == 0) + return c; + + WCHAR wide_c; + if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0) + return c; + + WCHAR wide_result; + int b = ::LCMapStringW( + idx, // locale identifier + LCMAP_UPPERCASE, // mapping transformation type + &wide_c, // source string + 1, // number of characters in source string + &wide_result, // destination buffer + 1); // size of destination buffer + if (b == 0) + return c; + + if (::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0) + return c; // No single byte upper case equivalent available. +#endif + return result[0]; + } + +#ifndef BOOST_NO_WREGEX + inline wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type idx) + { + wchar_t result[2]; + int b = ::LCMapStringW( + idx, // locale identifier + LCMAP_UPPERCASE, // mapping transformation type + &c, // source string + 1, // number of characters in source string + result, // destination buffer + 1); // size of destination buffer + if (b == 0) + return c; + return result[0]; + } +#endif + inline bool BOOST_REGEX_CALL w32_is(lcid_type idx, boost::uint32_t m, char c) + { + WORD mask; +#ifndef BOOST_NO_ANSI_APIS + if (::GetStringTypeExA(idx, CT_CTYPE1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation::mask_base)) + return true; +#else + UINT code_page = get_code_page_for_locale_id(idx); + if (code_page == 0) + return false; + + WCHAR wide_c; + if (::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0) + return false; + + if (::GetStringTypeExW(idx, CT_CTYPE1, &wide_c, 1, &mask) && (mask & m & w32_regex_traits_implementation::mask_base)) + return true; +#endif + if ((m & w32_regex_traits_implementation::mask_word) && (c == '_')) + return true; + return false; + } + +#ifndef BOOST_NO_WREGEX + inline bool BOOST_REGEX_CALL w32_is(lcid_type idx, boost::uint32_t m, wchar_t c) + { + WORD mask; + if (::GetStringTypeExW(idx, CT_CTYPE1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation::mask_base)) + return true; + if ((m & w32_regex_traits_implementation::mask_word) && (c == '_')) + return true; + if ((m & w32_regex_traits_implementation::mask_unicode) && (c > 0xff)) + return true; + return false; + } +#endif + +} // BOOST_REGEX_DETAIL_NS + + +} // boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4103) +#endif +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_REGEX_NO_WIN32_LOCALE + +#endif diff --git a/boost/regex/v5/basic_regex.hpp b/boost/regex/v5/basic_regex.hpp new file mode 100644 index 00000000..5c73775f --- /dev/null +++ b/boost/regex/v5/basic_regex.hpp @@ -0,0 +1,734 @@ +/* + * + * Copyright (c) 1998-2004 John Maddock + * Copyright 2011 Garmin Ltd. or its subsidiaries + * + * 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) + * + */ + + /* + * LOCATION: see http://www.boost.org/ for most recent version. + * FILE basic_regex.cpp + * VERSION see + * DESCRIPTION: Declares template class basic_regex. + */ + +#ifndef BOOST_REGEX_V5_BASIC_REGEX_HPP +#define BOOST_REGEX_V5_BASIC_REGEX_HPP + +#include + +namespace boost{ +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable : 4251) +#if BOOST_REGEX_MSVC < 1700 +# pragma warning(disable : 4231) +#endif +#if BOOST_REGEX_MSVC < 1600 +#pragma warning(disable : 4660) +#endif +#if BOOST_REGEX_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +namespace BOOST_REGEX_DETAIL_NS{ + +// +// forward declaration, we will need this one later: +// +template +class basic_regex_parser; + +template +void bubble_down_one(I first, I last) +{ + if(first != last) + { + I next = last - 1; + while((next != first) && (*next < *(next-1))) + { + (next-1)->swap(*next); + --next; + } + } +} + +static const int hash_value_mask = 1 << (std::numeric_limits::digits - 1); + +template +inline int hash_value_from_capture_name(Iterator i, Iterator j) +{ + std::size_t r = 0; + while (i != j) + { + r ^= *i + 0x9e3779b9 + (r << 6) + (r >> 2); + ++i; + } + r %= ((std::numeric_limits::max)()); + return static_cast(r) | hash_value_mask; +} + +class named_subexpressions +{ +public: + struct name + { + template + name(const charT* i, const charT* j, int idx) + : index(idx) + { + hash = hash_value_from_capture_name(i, j); + } + name(int h, int idx) + : index(idx), hash(h) + { + } + int index; + int hash; + bool operator < (const name& other)const + { + return hash < other.hash; + } + bool operator == (const name& other)const + { + return hash == other.hash; + } + void swap(name& other) + { + std::swap(index, other.index); + std::swap(hash, other.hash); + } + }; + + typedef std::vector::const_iterator const_iterator; + typedef std::pair range_type; + + named_subexpressions(){} + + template + void set_name(const charT* i, const charT* j, int index) + { + m_sub_names.push_back(name(i, j, index)); + bubble_down_one(m_sub_names.begin(), m_sub_names.end()); + } + template + int get_id(const charT* i, const charT* j)const + { + name t(i, j, 0); + typename std::vector::const_iterator pos = std::lower_bound(m_sub_names.begin(), m_sub_names.end(), t); + if((pos != m_sub_names.end()) && (*pos == t)) + { + return pos->index; + } + return -1; + } + template + range_type equal_range(const charT* i, const charT* j)const + { + name t(i, j, 0); + return std::equal_range(m_sub_names.begin(), m_sub_names.end(), t); + } + int get_id(int h)const + { + name t(h, 0); + std::vector::const_iterator pos = std::lower_bound(m_sub_names.begin(), m_sub_names.end(), t); + if((pos != m_sub_names.end()) && (*pos == t)) + { + return pos->index; + } + return -1; + } + range_type equal_range(int h)const + { + name t(h, 0); + return std::equal_range(m_sub_names.begin(), m_sub_names.end(), t); + } +private: + std::vector m_sub_names; +}; + +// +// class regex_data: +// represents the data we wish to expose to the matching algorithms. +// +template +struct regex_data : public named_subexpressions +{ + typedef regex_constants::syntax_option_type flag_type; + typedef std::size_t size_type; + + regex_data(const ::std::shared_ptr< + ::boost::regex_traits_wrapper >& t) + : m_ptraits(t), m_flags(0), m_status(0), m_expression(0), m_expression_len(0), + m_mark_count(0), m_first_state(0), m_restart_type(0), + m_startmap{ 0 }, + m_can_be_null(0), m_word_mask(0), m_has_recursions(false), m_disable_match_any(false) {} + regex_data() + : m_ptraits(new ::boost::regex_traits_wrapper()), m_flags(0), m_status(0), m_expression(0), m_expression_len(0), + m_mark_count(0), m_first_state(0), m_restart_type(0), + m_startmap{ 0 }, + m_can_be_null(0), m_word_mask(0), m_has_recursions(false), m_disable_match_any(false) {} + + ::std::shared_ptr< + ::boost::regex_traits_wrapper + > m_ptraits; // traits class instance + flag_type m_flags; // flags with which we were compiled + int m_status; // error code (0 implies OK). + const charT* m_expression; // the original expression + std::ptrdiff_t m_expression_len; // the length of the original expression + size_type m_mark_count; // the number of marked sub-expressions + BOOST_REGEX_DETAIL_NS::re_syntax_base* m_first_state; // the first state of the machine + unsigned m_restart_type; // search optimisation type + unsigned char m_startmap[1 << CHAR_BIT]; // which characters can start a match + unsigned int m_can_be_null; // whether we can match a null string + BOOST_REGEX_DETAIL_NS::raw_storage m_data; // the buffer in which our states are constructed + typename traits::char_class_type m_word_mask; // mask used to determine if a character is a word character + std::vector< + std::pair< + std::size_t, std::size_t> > m_subs; // Position of sub-expressions within the *string*. + bool m_has_recursions; // whether we have recursive expressions; + bool m_disable_match_any; // when set we need to disable the match_any flag as it causes different/buggy behaviour. +}; +// +// class basic_regex_implementation +// pimpl implementation class for basic_regex. +// +template +class basic_regex_implementation + : public regex_data +{ +public: + typedef regex_constants::syntax_option_type flag_type; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef typename traits::locale_type locale_type; + typedef const charT* const_iterator; + + basic_regex_implementation(){} + basic_regex_implementation(const ::std::shared_ptr< + ::boost::regex_traits_wrapper >& t) + : regex_data(t) {} + void assign(const charT* arg_first, + const charT* arg_last, + flag_type f) + { + regex_data* pdat = this; + basic_regex_parser parser(pdat); + parser.parse(arg_first, arg_last, f); + } + + locale_type imbue(locale_type l) + { + return this->m_ptraits->imbue(l); + } + locale_type getloc()const + { + return this->m_ptraits->getloc(); + } + std::basic_string str()const + { + std::basic_string result; + if(this->m_status == 0) + result = std::basic_string(this->m_expression, this->m_expression_len); + return result; + } + const_iterator expression()const + { + return this->m_expression; + } + std::pair subexpression(std::size_t n)const + { + const std::pair& pi = this->m_subs.at(n); + std::pair p(expression() + pi.first, expression() + pi.second); + return p; + } + // + // begin, end: + const_iterator begin()const + { + return (this->m_status ? 0 : this->m_expression); + } + const_iterator end()const + { + return (this->m_status ? 0 : this->m_expression + this->m_expression_len); + } + flag_type flags()const + { + return this->m_flags; + } + size_type size()const + { + return this->m_expression_len; + } + int status()const + { + return this->m_status; + } + size_type mark_count()const + { + return this->m_mark_count - 1; + } + const BOOST_REGEX_DETAIL_NS::re_syntax_base* get_first_state()const + { + return this->m_first_state; + } + unsigned get_restart_type()const + { + return this->m_restart_type; + } + const unsigned char* get_map()const + { + return this->m_startmap; + } + const ::boost::regex_traits_wrapper& get_traits()const + { + return *(this->m_ptraits); + } + bool can_be_null()const + { + return this->m_can_be_null; + } + const regex_data& get_data()const + { + basic_regex_implementation const* p = this; + return *static_cast*>(p); + } +}; + +} // namespace BOOST_REGEX_DETAIL_NS +// +// class basic_regex: +// represents the compiled +// regular expression: +// + +#ifdef BOOST_REGEX_NO_FWD +template > +#else +template +#endif +class basic_regex : public regbase +{ +public: + // typedefs: + typedef std::size_t traits_size_type; + typedef typename traits::string_type traits_string_type; + typedef charT char_type; + typedef traits traits_type; + + typedef charT value_type; + typedef charT& reference; + typedef const charT& const_reference; + typedef const charT* const_iterator; + typedef const_iterator iterator; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef regex_constants::syntax_option_type flag_type; + // locale_type + // placeholder for actual locale type used by the + // traits class to localise *this. + typedef typename traits::locale_type locale_type; + +public: + explicit basic_regex(){} + explicit basic_regex(const charT* p, flag_type f = regex_constants::normal) + { + assign(p, f); + } + basic_regex(const charT* p1, const charT* p2, flag_type f = regex_constants::normal) + { + assign(p1, p2, f); + } + basic_regex(const charT* p, size_type len, flag_type f) + { + assign(p, len, f); + } + basic_regex(const basic_regex& that) + : m_pimpl(that.m_pimpl) {} + ~basic_regex(){} + basic_regex& operator=(const basic_regex& that) + { + return assign(that); + } + basic_regex& operator=(const charT* ptr) + { + return assign(ptr); + } + + // + // assign: + basic_regex& assign(const basic_regex& that) + { + m_pimpl = that.m_pimpl; + return *this; + } + basic_regex& assign(const charT* p, flag_type f = regex_constants::normal) + { + return assign(p, p + traits::length(p), f); + } + basic_regex& assign(const charT* p, size_type len, flag_type f) + { + return assign(p, p + len, f); + } +private: + basic_regex& do_assign(const charT* p1, + const charT* p2, + flag_type f); +public: + basic_regex& assign(const charT* p1, + const charT* p2, + flag_type f = regex_constants::normal) + { + return do_assign(p1, p2, f); + } + + template + unsigned int set_expression(const std::basic_string& p, flag_type f = regex_constants::normal) + { + return set_expression(p.data(), p.data() + p.size(), f); + } + + template + explicit basic_regex(const std::basic_string& p, flag_type f = regex_constants::normal) + { + assign(p, f); + } + + template + basic_regex(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal) + { + typedef typename traits::string_type seq_type; + seq_type a(arg_first, arg_last); + if(!a.empty()) + assign(static_cast(&*a.begin()), static_cast(&*a.begin() + a.size()), f); + else + assign(static_cast(0), static_cast(0), f); + } + + template + basic_regex& operator=(const std::basic_string& p) + { + return assign(p.data(), p.data() + p.size(), regex_constants::normal); + } + + template + basic_regex& assign( + const std::basic_string& s, + flag_type f = regex_constants::normal) + { + return assign(s.data(), s.data() + s.size(), f); + } + + template + basic_regex& assign(InputIterator arg_first, + InputIterator arg_last, + flag_type f = regex_constants::normal) + { + typedef typename traits::string_type seq_type; + seq_type a(arg_first, arg_last); + if(a.size()) + { + const charT* p1 = &*a.begin(); + const charT* p2 = &*a.begin() + a.size(); + return assign(p1, p2, f); + } + return assign(static_cast(0), static_cast(0), f); + } + + // + // locale: + locale_type imbue(locale_type l); + locale_type getloc()const + { + return m_pimpl.get() ? m_pimpl->getloc() : locale_type(); + } + // + // getflags: + // retained for backwards compatibility only, "flags" + // is now the preferred name: + flag_type getflags()const + { + return flags(); + } + flag_type flags()const + { + return m_pimpl.get() ? m_pimpl->flags() : 0; + } + // + // str: + std::basic_string str()const + { + return m_pimpl.get() ? m_pimpl->str() : std::basic_string(); + } + // + // begin, end, subexpression: + std::pair subexpression(std::size_t n)const + { +#ifdef BOOST_REGEX_STANDALONE + if (!m_pimpl.get()) + throw std::logic_error("Can't access subexpressions in an invalid regex."); +#else + if(!m_pimpl.get()) + boost::throw_exception(std::logic_error("Can't access subexpressions in an invalid regex.")); +#endif + return m_pimpl->subexpression(n); + } + const_iterator begin()const + { + return (m_pimpl.get() ? m_pimpl->begin() : 0); + } + const_iterator end()const + { + return (m_pimpl.get() ? m_pimpl->end() : 0); + } + // + // swap: + void swap(basic_regex& that)throw() + { + m_pimpl.swap(that.m_pimpl); + } + // + // size: + size_type size()const + { + return (m_pimpl.get() ? m_pimpl->size() : 0); + } + // + // max_size: + size_type max_size()const + { + return UINT_MAX; + } + // + // empty: + bool empty()const + { + return (m_pimpl.get() ? 0 != m_pimpl->status() : true); + } + + size_type mark_count()const + { + return (m_pimpl.get() ? m_pimpl->mark_count() : 0); + } + + int status()const + { + return (m_pimpl.get() ? m_pimpl->status() : regex_constants::error_empty); + } + + int compare(const basic_regex& that) const + { + if(m_pimpl.get() == that.m_pimpl.get()) + return 0; + if(!m_pimpl.get()) + return -1; + if(!that.m_pimpl.get()) + return 1; + if(status() != that.status()) + return status() - that.status(); + if(flags() != that.flags()) + return flags() - that.flags(); + return str().compare(that.str()); + } + bool operator==(const basic_regex& e)const + { + return compare(e) == 0; + } + bool operator != (const basic_regex& e)const + { + return compare(e) != 0; + } + bool operator<(const basic_regex& e)const + { + return compare(e) < 0; + } + bool operator>(const basic_regex& e)const + { + return compare(e) > 0; + } + bool operator<=(const basic_regex& e)const + { + return compare(e) <= 0; + } + bool operator>=(const basic_regex& e)const + { + return compare(e) >= 0; + } + + // + // The following are deprecated as public interfaces + // but are available for compatibility with earlier versions. + const charT* expression()const + { + return (m_pimpl.get() && !m_pimpl->status() ? m_pimpl->expression() : 0); + } + unsigned int set_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal) + { + assign(p1, p2, f | regex_constants::no_except); + return status(); + } + unsigned int set_expression(const charT* p, flag_type f = regex_constants::normal) + { + assign(p, f | regex_constants::no_except); + return status(); + } + unsigned int error_code()const + { + return status(); + } + // + // private access methods: + // + const BOOST_REGEX_DETAIL_NS::re_syntax_base* get_first_state()const + { + BOOST_REGEX_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_first_state(); + } + unsigned get_restart_type()const + { + BOOST_REGEX_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_restart_type(); + } + const unsigned char* get_map()const + { + BOOST_REGEX_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_map(); + } + const ::boost::regex_traits_wrapper& get_traits()const + { + BOOST_REGEX_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_traits(); + } + bool can_be_null()const + { + BOOST_REGEX_ASSERT(0 != m_pimpl.get()); + return m_pimpl->can_be_null(); + } + const BOOST_REGEX_DETAIL_NS::regex_data& get_data()const + { + BOOST_REGEX_ASSERT(0 != m_pimpl.get()); + return m_pimpl->get_data(); + } + std::shared_ptr get_named_subs()const + { + return m_pimpl; + } + +private: + std::shared_ptr > m_pimpl; +}; + +// +// out of line members; +// these are the only members that mutate the basic_regex object, +// and are designed to provide the strong exception guarantee +// (in the event of a throw, the state of the object remains unchanged). +// +template +basic_regex& basic_regex::do_assign(const charT* p1, + const charT* p2, + flag_type f) +{ + std::shared_ptr > temp; + if(!m_pimpl.get()) + { + temp = std::shared_ptr >(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation()); + } + else + { + temp = std::shared_ptr >(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation(m_pimpl->m_ptraits)); + } + temp->assign(p1, p2, f); + temp.swap(m_pimpl); + return *this; +} + +template +typename basic_regex::locale_type basic_regex::imbue(locale_type l) +{ + std::shared_ptr > temp(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation()); + locale_type result = temp->imbue(l); + temp.swap(m_pimpl); + return result; +} + +// +// non-members: +// +template +void swap(basic_regex& e1, basic_regex& e2) +{ + e1.swap(e2); +} + +template +std::basic_ostream& + operator << (std::basic_ostream& os, + const basic_regex& e) +{ + return (os << e.str()); +} + +// +// class reg_expression: +// this is provided for backwards compatibility only, +// it is deprecated, no not use! +// +#ifdef BOOST_REGEX_NO_FWD +template > +#else +template +#endif +class reg_expression : public basic_regex +{ +public: + typedef typename basic_regex::flag_type flag_type; + typedef typename basic_regex::size_type size_type; + explicit reg_expression(){} + explicit reg_expression(const charT* p, flag_type f = regex_constants::normal) + : basic_regex(p, f){} + reg_expression(const charT* p1, const charT* p2, flag_type f = regex_constants::normal) + : basic_regex(p1, p2, f){} + reg_expression(const charT* p, size_type len, flag_type f) + : basic_regex(p, len, f){} + reg_expression(const reg_expression& that) + : basic_regex(that) {} + ~reg_expression(){} + reg_expression& operator=(const reg_expression& that) + { + return this->assign(that); + } + + template + explicit reg_expression(const std::basic_string& p, flag_type f = regex_constants::normal) + : basic_regex(p, f) + { + } + + template + reg_expression(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal) + : basic_regex(arg_first, arg_last, f) + { + } + + template + reg_expression& operator=(const std::basic_string& p) + { + this->assign(p); + return *this; + } + +}; + +#ifdef BOOST_REGEX_MSVC +#pragma warning (pop) +#endif + +} // namespace boost + +#endif diff --git a/boost/regex/v5/basic_regex_creator.hpp b/boost/regex/v5/basic_regex_creator.hpp new file mode 100644 index 00000000..bb76c7c1 --- /dev/null +++ b/boost/regex/v5/basic_regex_creator.hpp @@ -0,0 +1,1576 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE basic_regex_creator.cpp + * VERSION see + * DESCRIPTION: Declares template class basic_regex_creator which fills in + * the data members of a regex_data object. + */ + +#ifndef BOOST_REGEX_V5_BASIC_REGEX_CREATOR_HPP +#define BOOST_REGEX_V5_BASIC_REGEX_CREATOR_HPP + +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +#pragma warning(disable:4459) +#if BOOST_REGEX_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +#include + +namespace boost{ + +namespace BOOST_REGEX_DETAIL_NS{ + +template +struct digraph : public std::pair +{ + digraph() : std::pair(charT(0), charT(0)){} + digraph(charT c1) : std::pair(c1, charT(0)){} + digraph(charT c1, charT c2) : std::pair(c1, c2) + {} + digraph(const digraph& d) : std::pair(d.first, d.second){} + digraph& operator=(const digraph&) = default; + template + digraph(const Seq& s) : std::pair() + { + BOOST_REGEX_ASSERT(s.size() <= 2); + BOOST_REGEX_ASSERT(s.size()); + this->first = s[0]; + this->second = (s.size() > 1) ? s[1] : 0; + } +}; + +template +class basic_char_set +{ +public: + typedef digraph digraph_type; + typedef typename traits::string_type string_type; + typedef typename traits::char_class_type m_type; + + basic_char_set() + { + m_negate = false; + m_has_digraphs = false; + m_classes = 0; + m_negated_classes = 0; + m_empty = true; + } + + void add_single(const digraph_type& s) + { + m_singles.insert(s); + if(s.second) + m_has_digraphs = true; + m_empty = false; + } + void add_range(const digraph_type& first, const digraph_type& end) + { + m_ranges.push_back(first); + m_ranges.push_back(end); + if(first.second) + { + m_has_digraphs = true; + add_single(first); + } + if(end.second) + { + m_has_digraphs = true; + add_single(end); + } + m_empty = false; + } + void add_class(m_type m) + { + m_classes |= m; + m_empty = false; + } + void add_negated_class(m_type m) + { + m_negated_classes |= m; + m_empty = false; + } + void add_equivalent(const digraph_type& s) + { + m_equivalents.insert(s); + if(s.second) + { + m_has_digraphs = true; + add_single(s); + } + m_empty = false; + } + void negate() + { + m_negate = true; + //m_empty = false; + } + + // + // accessor functions: + // + bool has_digraphs()const + { + return m_has_digraphs; + } + bool is_negated()const + { + return m_negate; + } + typedef typename std::vector::const_iterator list_iterator; + typedef typename std::set::const_iterator set_iterator; + set_iterator singles_begin()const + { + return m_singles.begin(); + } + set_iterator singles_end()const + { + return m_singles.end(); + } + list_iterator ranges_begin()const + { + return m_ranges.begin(); + } + list_iterator ranges_end()const + { + return m_ranges.end(); + } + set_iterator equivalents_begin()const + { + return m_equivalents.begin(); + } + set_iterator equivalents_end()const + { + return m_equivalents.end(); + } + m_type classes()const + { + return m_classes; + } + m_type negated_classes()const + { + return m_negated_classes; + } + bool empty()const + { + return m_empty; + } +private: + std::set m_singles; // a list of single characters to match + std::vector m_ranges; // a list of end points of our ranges + bool m_negate; // true if the set is to be negated + bool m_has_digraphs; // true if we have digraphs present + m_type m_classes; // character classes to match + m_type m_negated_classes; // negated character classes to match + bool m_empty; // whether we've added anything yet + std::set m_equivalents; // a list of equivalence classes +}; + +template +class basic_regex_creator +{ +public: + basic_regex_creator(regex_data* data); + std::ptrdiff_t getoffset(void* addr) + { + return getoffset(addr, m_pdata->m_data.data()); + } + std::ptrdiff_t getoffset(const void* addr, const void* base) + { + return static_cast(addr) - static_cast(base); + } + re_syntax_base* getaddress(std::ptrdiff_t off) + { + return getaddress(off, m_pdata->m_data.data()); + } + re_syntax_base* getaddress(std::ptrdiff_t off, void* base) + { + return static_cast(static_cast(static_cast(base) + off)); + } + void init(unsigned l_flags) + { + m_pdata->m_flags = l_flags; + m_icase = l_flags & regex_constants::icase; + } + regbase::flag_type flags() + { + return m_pdata->m_flags; + } + void flags(regbase::flag_type f) + { + m_pdata->m_flags = f; + if(m_icase != static_cast(f & regbase::icase)) + { + m_icase = static_cast(f & regbase::icase); + } + } + re_syntax_base* append_state(syntax_element_type t, std::size_t s = sizeof(re_syntax_base)); + re_syntax_base* insert_state(std::ptrdiff_t pos, syntax_element_type t, std::size_t s = sizeof(re_syntax_base)); + re_literal* append_literal(charT c); + re_syntax_base* append_set(const basic_char_set& char_set); + re_syntax_base* append_set(const basic_char_set& char_set, std::integral_constant*); + re_syntax_base* append_set(const basic_char_set& char_set, std::integral_constant*); + void finalize(const charT* p1, const charT* p2); +protected: + regex_data* m_pdata; // pointer to the basic_regex_data struct we are filling in + const ::boost::regex_traits_wrapper& + m_traits; // convenience reference to traits class + re_syntax_base* m_last_state; // the last state we added + bool m_icase; // true for case insensitive matches + unsigned m_repeater_id; // the state_id of the next repeater + bool m_has_backrefs; // true if there are actually any backrefs + std::uintmax_t m_bad_repeats; // bitmask of repeats we can't deduce a startmap for; + bool m_has_recursions; // set when we have recursive expressions to fixup + std::vector m_recursion_checks; // notes which recursions we've followed while analysing this expression + typename traits::char_class_type m_word_mask; // mask used to determine if a character is a word character + typename traits::char_class_type m_mask_space; // mask used to determine if a character is a word character + typename traits::char_class_type m_lower_mask; // mask used to determine if a character is a lowercase character + typename traits::char_class_type m_upper_mask; // mask used to determine if a character is an uppercase character + typename traits::char_class_type m_alpha_mask; // mask used to determine if a character is an alphabetic character +private: + basic_regex_creator& operator=(const basic_regex_creator&); + basic_regex_creator(const basic_regex_creator&); + + void fixup_pointers(re_syntax_base* state); + void fixup_recursions(re_syntax_base* state); + void create_startmaps(re_syntax_base* state); + int calculate_backstep(re_syntax_base* state); + void create_startmap(re_syntax_base* state, unsigned char* l_map, unsigned int* pnull, unsigned char mask); + unsigned get_restart_type(re_syntax_base* state); + void set_all_masks(unsigned char* bits, unsigned char); + bool is_bad_repeat(re_syntax_base* pt); + void set_bad_repeat(re_syntax_base* pt); + syntax_element_type get_repeat_type(re_syntax_base* state); + void probe_leading_repeat(re_syntax_base* state); +}; + +template +basic_regex_creator::basic_regex_creator(regex_data* data) + : m_pdata(data), m_traits(*(data->m_ptraits)), m_last_state(0), m_icase(false), m_repeater_id(0), + m_has_backrefs(false), m_bad_repeats(0), m_has_recursions(false), m_word_mask(0), m_mask_space(0), m_lower_mask(0), m_upper_mask(0), m_alpha_mask(0) +{ + m_pdata->m_data.clear(); + m_pdata->m_status = ::boost::regex_constants::error_ok; + static const charT w = 'w'; + static const charT s = 's'; + static const charT l[5] = { 'l', 'o', 'w', 'e', 'r', }; + static const charT u[5] = { 'u', 'p', 'p', 'e', 'r', }; + static const charT a[5] = { 'a', 'l', 'p', 'h', 'a', }; + m_word_mask = m_traits.lookup_classname(&w, &w +1); + m_mask_space = m_traits.lookup_classname(&s, &s +1); + m_lower_mask = m_traits.lookup_classname(l, l + 5); + m_upper_mask = m_traits.lookup_classname(u, u + 5); + m_alpha_mask = m_traits.lookup_classname(a, a + 5); + m_pdata->m_word_mask = m_word_mask; + BOOST_REGEX_ASSERT(m_word_mask != 0); + BOOST_REGEX_ASSERT(m_mask_space != 0); + BOOST_REGEX_ASSERT(m_lower_mask != 0); + BOOST_REGEX_ASSERT(m_upper_mask != 0); + BOOST_REGEX_ASSERT(m_alpha_mask != 0); +} + +template +re_syntax_base* basic_regex_creator::append_state(syntax_element_type t, std::size_t s) +{ + // if the state is a backref then make a note of it: + if(t == syntax_element_backref) + this->m_has_backrefs = true; + // append a new state, start by aligning our last one: + m_pdata->m_data.align(); + // set the offset to the next state in our last one: + if(m_last_state) + m_last_state->next.i = m_pdata->m_data.size() - getoffset(m_last_state); + // now actually extend our data: + m_last_state = static_cast(m_pdata->m_data.extend(s)); + // fill in boilerplate options in the new state: + m_last_state->next.i = 0; + m_last_state->type = t; + return m_last_state; +} + +template +re_syntax_base* basic_regex_creator::insert_state(std::ptrdiff_t pos, syntax_element_type t, std::size_t s) +{ + // append a new state, start by aligning our last one: + m_pdata->m_data.align(); + // set the offset to the next state in our last one: + if(m_last_state) + m_last_state->next.i = m_pdata->m_data.size() - getoffset(m_last_state); + // remember the last state position: + std::ptrdiff_t off = getoffset(m_last_state) + s; + // now actually insert our data: + re_syntax_base* new_state = static_cast(m_pdata->m_data.insert(pos, s)); + // fill in boilerplate options in the new state: + new_state->next.i = s; + new_state->type = t; + m_last_state = getaddress(off); + return new_state; +} + +template +re_literal* basic_regex_creator::append_literal(charT c) +{ + re_literal* result; + // start by seeing if we have an existing re_literal we can extend: + if((0 == m_last_state) || (m_last_state->type != syntax_element_literal)) + { + // no existing re_literal, create a new one: + result = static_cast(append_state(syntax_element_literal, sizeof(re_literal) + sizeof(charT))); + result->length = 1; + *static_cast(static_cast(result+1)) = m_traits.translate(c, m_icase); + } + else + { + // we have an existing re_literal, extend it: + std::ptrdiff_t off = getoffset(m_last_state); + m_pdata->m_data.extend(sizeof(charT)); + m_last_state = result = static_cast(getaddress(off)); + charT* characters = static_cast(static_cast(result+1)); + characters[result->length] = m_traits.translate(c, m_icase); + result->length += 1; + } + return result; +} + +template +inline re_syntax_base* basic_regex_creator::append_set( + const basic_char_set& char_set) +{ + typedef std::integral_constant truth_type; + return char_set.has_digraphs() + ? append_set(char_set, static_cast*>(0)) + : append_set(char_set, static_cast(0)); +} + +template +re_syntax_base* basic_regex_creator::append_set( + const basic_char_set& char_set, std::integral_constant*) +{ + typedef typename traits::string_type string_type; + typedef typename basic_char_set::list_iterator item_iterator; + typedef typename basic_char_set::set_iterator set_iterator; + typedef typename traits::char_class_type m_type; + + re_set_long* result = static_cast*>(append_state(syntax_element_long_set, sizeof(re_set_long))); + // + // fill in the basics: + // + result->csingles = static_cast(std::distance(char_set.singles_begin(), char_set.singles_end())); + result->cranges = static_cast(std::distance(char_set.ranges_begin(), char_set.ranges_end())) / 2; + result->cequivalents = static_cast(std::distance(char_set.equivalents_begin(), char_set.equivalents_end())); + result->cclasses = char_set.classes(); + result->cnclasses = char_set.negated_classes(); + if(flags() & regbase::icase) + { + // adjust classes as needed: + if(((result->cclasses & m_lower_mask) == m_lower_mask) || ((result->cclasses & m_upper_mask) == m_upper_mask)) + result->cclasses |= m_alpha_mask; + if(((result->cnclasses & m_lower_mask) == m_lower_mask) || ((result->cnclasses & m_upper_mask) == m_upper_mask)) + result->cnclasses |= m_alpha_mask; + } + + result->isnot = char_set.is_negated(); + result->singleton = !char_set.has_digraphs(); + // + // remember where the state is for later: + // + std::ptrdiff_t offset = getoffset(result); + // + // now extend with all the singles: + // + item_iterator first, last; + set_iterator sfirst, slast; + sfirst = char_set.singles_begin(); + slast = char_set.singles_end(); + while(sfirst != slast) + { + charT* p = static_cast(this->m_pdata->m_data.extend(sizeof(charT) * (sfirst->first == static_cast(0) ? 1 : sfirst->second ? 3 : 2))); + p[0] = m_traits.translate(sfirst->first, m_icase); + if(sfirst->first == static_cast(0)) + { + p[0] = 0; + } + else if(sfirst->second) + { + p[1] = m_traits.translate(sfirst->second, m_icase); + p[2] = 0; + } + else + p[1] = 0; + ++sfirst; + } + // + // now extend with all the ranges: + // + first = char_set.ranges_begin(); + last = char_set.ranges_end(); + while(first != last) + { + // first grab the endpoints of the range: + digraph c1 = *first; + c1.first = this->m_traits.translate(c1.first, this->m_icase); + c1.second = this->m_traits.translate(c1.second, this->m_icase); + ++first; + digraph c2 = *first; + c2.first = this->m_traits.translate(c2.first, this->m_icase); + c2.second = this->m_traits.translate(c2.second, this->m_icase); + ++first; + string_type s1, s2; + // different actions now depending upon whether collation is turned on: + if(flags() & regex_constants::collate) + { + // we need to transform our range into sort keys: + charT a1[3] = { c1.first, c1.second, charT(0), }; + charT a2[3] = { c2.first, c2.second, charT(0), }; + s1 = this->m_traits.transform(a1, (a1[1] ? a1+2 : a1+1)); + s2 = this->m_traits.transform(a2, (a2[1] ? a2+2 : a2+1)); + if(s1.empty()) + s1 = string_type(1, charT(0)); + if(s2.empty()) + s2 = string_type(1, charT(0)); + } + else + { + if(c1.second) + { + s1.insert(s1.end(), c1.first); + s1.insert(s1.end(), c1.second); + } + else + s1 = string_type(1, c1.first); + if(c2.second) + { + s2.insert(s2.end(), c2.first); + s2.insert(s2.end(), c2.second); + } + else + s2.insert(s2.end(), c2.first); + } + if(s1 > s2) + { + // Oops error: + return 0; + } + charT* p = static_cast(this->m_pdata->m_data.extend(sizeof(charT) * (s1.size() + s2.size() + 2) ) ); + BOOST_REGEX_DETAIL_NS::copy(s1.begin(), s1.end(), p); + p[s1.size()] = charT(0); + p += s1.size() + 1; + BOOST_REGEX_DETAIL_NS::copy(s2.begin(), s2.end(), p); + p[s2.size()] = charT(0); + } + // + // now process the equivalence classes: + // + sfirst = char_set.equivalents_begin(); + slast = char_set.equivalents_end(); + while(sfirst != slast) + { + string_type s; + if(sfirst->second) + { + charT cs[3] = { sfirst->first, sfirst->second, charT(0), }; + s = m_traits.transform_primary(cs, cs+2); + } + else + s = m_traits.transform_primary(&sfirst->first, &sfirst->first+1); + if(s.empty()) + return 0; // invalid or unsupported equivalence class + charT* p = static_cast(this->m_pdata->m_data.extend(sizeof(charT) * (s.size()+1) ) ); + BOOST_REGEX_DETAIL_NS::copy(s.begin(), s.end(), p); + p[s.size()] = charT(0); + ++sfirst; + } + // + // finally reset the address of our last state: + // + m_last_state = result = static_cast*>(getaddress(offset)); + return result; +} + +template +inline bool char_less(T t1, T t2) +{ + return t1 < t2; +} +inline bool char_less(char t1, char t2) +{ + return static_cast(t1) < static_cast(t2); +} +inline bool char_less(signed char t1, signed char t2) +{ + return static_cast(t1) < static_cast(t2); +} + +template +re_syntax_base* basic_regex_creator::append_set( + const basic_char_set& char_set, std::integral_constant*) +{ + typedef typename traits::string_type string_type; + typedef typename basic_char_set::list_iterator item_iterator; + typedef typename basic_char_set::set_iterator set_iterator; + + re_set* result = static_cast(append_state(syntax_element_set, sizeof(re_set))); + bool negate = char_set.is_negated(); + std::memset(result->_map, 0, sizeof(result->_map)); + // + // handle singles first: + // + item_iterator first, last; + set_iterator sfirst, slast; + sfirst = char_set.singles_begin(); + slast = char_set.singles_end(); + while(sfirst != slast) + { + for(unsigned int i = 0; i < (1 << CHAR_BIT); ++i) + { + if(this->m_traits.translate(static_cast(i), this->m_icase) + == this->m_traits.translate(sfirst->first, this->m_icase)) + result->_map[i] = true; + } + ++sfirst; + } + // + // OK now handle ranges: + // + first = char_set.ranges_begin(); + last = char_set.ranges_end(); + while(first != last) + { + // first grab the endpoints of the range: + charT c1 = this->m_traits.translate(first->first, this->m_icase); + ++first; + charT c2 = this->m_traits.translate(first->first, this->m_icase); + ++first; + // different actions now depending upon whether collation is turned on: + if(flags() & regex_constants::collate) + { + // we need to transform our range into sort keys: + charT c3[2] = { c1, charT(0), }; + string_type s1 = this->m_traits.transform(c3, c3+1); + c3[0] = c2; + string_type s2 = this->m_traits.transform(c3, c3+1); + if(s1 > s2) + { + // Oops error: + return 0; + } + BOOST_REGEX_ASSERT(c3[1] == charT(0)); + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + c3[0] = static_cast(i); + string_type s3 = this->m_traits.transform(c3, c3 +1); + if((s1 <= s3) && (s3 <= s2)) + result->_map[i] = true; + } + } + else + { + if(char_less(c2, c1)) + { + // Oops error: + return 0; + } + // everything in range matches: + std::memset(result->_map + static_cast(c1), true, static_cast(1u) + static_cast(static_cast(c2) - static_cast(c1))); + } + } + // + // and now the classes: + // + typedef typename traits::char_class_type m_type; + m_type m = char_set.classes(); + if(flags() & regbase::icase) + { + // adjust m as needed: + if(((m & m_lower_mask) == m_lower_mask) || ((m & m_upper_mask) == m_upper_mask)) + m |= m_alpha_mask; + } + if(m != 0) + { + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + if(this->m_traits.isctype(static_cast(i), m)) + result->_map[i] = true; + } + } + // + // and now the negated classes: + // + m = char_set.negated_classes(); + if(flags() & regbase::icase) + { + // adjust m as needed: + if(((m & m_lower_mask) == m_lower_mask) || ((m & m_upper_mask) == m_upper_mask)) + m |= m_alpha_mask; + } + if(m != 0) + { + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + if(0 == this->m_traits.isctype(static_cast(i), m)) + result->_map[i] = true; + } + } + // + // now process the equivalence classes: + // + sfirst = char_set.equivalents_begin(); + slast = char_set.equivalents_end(); + while(sfirst != slast) + { + string_type s; + BOOST_REGEX_ASSERT(static_cast(0) == sfirst->second); + s = m_traits.transform_primary(&sfirst->first, &sfirst->first+1); + if(s.empty()) + return 0; // invalid or unsupported equivalence class + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + charT c[2] = { (static_cast(i)), charT(0), }; + string_type s2 = this->m_traits.transform_primary(c, c+1); + if(s == s2) + result->_map[i] = true; + } + ++sfirst; + } + if(negate) + { + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + { + result->_map[i] = !(result->_map[i]); + } + } + return result; +} + +template +void basic_regex_creator::finalize(const charT* p1, const charT* p2) +{ + if(this->m_pdata->m_status) + return; + // we've added all the states we need, now finish things off. + // start by adding a terminating state: + append_state(syntax_element_match); + // extend storage to store original expression: + std::ptrdiff_t len = p2 - p1; + m_pdata->m_expression_len = len; + charT* ps = static_cast(m_pdata->m_data.extend(sizeof(charT) * (1 + (p2 - p1)))); + m_pdata->m_expression = ps; + BOOST_REGEX_DETAIL_NS::copy(p1, p2, ps); + ps[p2 - p1] = 0; + // fill in our other data... + // successful parsing implies a zero status: + m_pdata->m_status = 0; + // get the first state of the machine: + m_pdata->m_first_state = static_cast(m_pdata->m_data.data()); + // fixup pointers in the machine: + fixup_pointers(m_pdata->m_first_state); + if(m_has_recursions) + { + m_pdata->m_has_recursions = true; + fixup_recursions(m_pdata->m_first_state); + if(this->m_pdata->m_status) + return; + } + else + m_pdata->m_has_recursions = false; + // create nested startmaps: + create_startmaps(m_pdata->m_first_state); + // create main startmap: + std::memset(m_pdata->m_startmap, 0, sizeof(m_pdata->m_startmap)); + m_pdata->m_can_be_null = 0; + + m_bad_repeats = 0; + if(m_has_recursions) + m_recursion_checks.assign(1 + m_pdata->m_mark_count, 0u); + create_startmap(m_pdata->m_first_state, m_pdata->m_startmap, &(m_pdata->m_can_be_null), mask_all); + // get the restart type: + m_pdata->m_restart_type = get_restart_type(m_pdata->m_first_state); + // optimise a leading repeat if there is one: + probe_leading_repeat(m_pdata->m_first_state); +} + +template +void basic_regex_creator::fixup_pointers(re_syntax_base* state) +{ + while(state) + { + switch(state->type) + { + case syntax_element_recurse: + m_has_recursions = true; + if(state->next.i) + state->next.p = getaddress(state->next.i, state); + else + state->next.p = 0; + break; + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + // set the state_id of this repeat: + static_cast(state)->state_id = m_repeater_id++; + BOOST_REGEX_FALLTHROUGH; + case syntax_element_alt: + std::memset(static_cast(state)->_map, 0, sizeof(static_cast(state)->_map)); + static_cast(state)->can_be_null = 0; + BOOST_REGEX_FALLTHROUGH; + case syntax_element_jump: + static_cast(state)->alt.p = getaddress(static_cast(state)->alt.i, state); + BOOST_REGEX_FALLTHROUGH; + default: + if(state->next.i) + state->next.p = getaddress(state->next.i, state); + else + state->next.p = 0; + } + state = state->next.p; + } +} + +template +void basic_regex_creator::fixup_recursions(re_syntax_base* state) +{ + re_syntax_base* base = state; + while(state) + { + switch(state->type) + { + case syntax_element_assert_backref: + { + // just check that the index is valid: + int idx = static_cast(state)->index; + if(idx < 0) + { + idx = -idx-1; + if(idx >= hash_value_mask) + { + idx = m_pdata->get_id(idx); + if(idx <= 0) + { + // check of sub-expression that doesn't exist: + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = boost::regex_constants::error_bad_pattern; + // + // clear the expression, we should be empty: + // + this->m_pdata->m_expression = 0; + this->m_pdata->m_expression_len = 0; + // + // and throw if required: + // + if(0 == (this->flags() & regex_constants::no_except)) + { + std::string message = "Encountered a forward reference to a marked sub-expression that does not exist."; + boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0); + e.raise(); + } + } + } + } + } + break; + case syntax_element_recurse: + { + bool ok = false; + re_syntax_base* p = base; + std::ptrdiff_t idx = static_cast(state)->alt.i; + if(idx >= hash_value_mask) + { + // + // There may be more than one capture group with this hash, just do what Perl + // does and recurse to the leftmost: + // + idx = m_pdata->get_id(static_cast(idx)); + } + if(idx < 0) + { + ok = false; + } + else + { + while(p) + { + if((p->type == syntax_element_startmark) && (static_cast(p)->index == idx)) + { + // + // We've found the target of the recursion, set the jump target: + // + static_cast(state)->alt.p = p; + ok = true; + // + // Now scan the target for nested repeats: + // + p = p->next.p; + int next_rep_id = 0; + while(p) + { + switch(p->type) + { + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + next_rep_id = static_cast(p)->state_id; + break; + case syntax_element_endmark: + if(static_cast(p)->index == idx) + next_rep_id = -1; + break; + default: + break; + } + if(next_rep_id) + break; + p = p->next.p; + } + if(next_rep_id > 0) + { + static_cast(state)->state_id = next_rep_id - 1; + } + + break; + } + p = p->next.p; + } + } + if(!ok) + { + // recursion to sub-expression that doesn't exist: + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = boost::regex_constants::error_bad_pattern; + // + // clear the expression, we should be empty: + // + this->m_pdata->m_expression = 0; + this->m_pdata->m_expression_len = 0; + // + // and throw if required: + // + if(0 == (this->flags() & regex_constants::no_except)) + { + std::string message = "Encountered a forward reference to a recursive sub-expression that does not exist."; + boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0); + e.raise(); + } + } + } + break; + default: + break; + } + state = state->next.p; + } +} + +template +void basic_regex_creator::create_startmaps(re_syntax_base* state) +{ + // non-recursive implementation: + // create the last map in the machine first, so that earlier maps + // can make use of the result... + // + // This was originally a recursive implementation, but that caused stack + // overflows with complex expressions on small stacks (think COM+). + + // start by saving the case setting: + bool l_icase = m_icase; + std::vector > v; + + while(state) + { + switch(state->type) + { + case syntax_element_toggle_case: + // we need to track case changes here: + m_icase = static_cast(state)->icase; + state = state->next.p; + continue; + case syntax_element_alt: + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + // just push the state onto our stack for now: + v.push_back(std::pair(m_icase, state)); + state = state->next.p; + break; + case syntax_element_backstep: + // we need to calculate how big the backstep is: + static_cast(state)->index + = this->calculate_backstep(state->next.p); + if(static_cast(state)->index < 0) + { + // Oops error: + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = boost::regex_constants::error_bad_pattern; + // + // clear the expression, we should be empty: + // + this->m_pdata->m_expression = 0; + this->m_pdata->m_expression_len = 0; + // + // and throw if required: + // + if(0 == (this->flags() & regex_constants::no_except)) + { + std::string message = "Invalid lookbehind assertion encountered in the regular expression."; + boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0); + e.raise(); + } + } + BOOST_REGEX_FALLTHROUGH; + default: + state = state->next.p; + } + } + + // now work through our list, building all the maps as we go: + while(!v.empty()) + { + // Initialize m_recursion_checks if we need it: + if(m_has_recursions) + m_recursion_checks.assign(1 + m_pdata->m_mark_count, 0u); + + const std::pair& p = v.back(); + m_icase = p.first; + state = p.second; + v.pop_back(); + + // Build maps: + m_bad_repeats = 0; + create_startmap(state->next.p, static_cast(state)->_map, &static_cast(state)->can_be_null, mask_take); + m_bad_repeats = 0; + + if(m_has_recursions) + m_recursion_checks.assign(1 + m_pdata->m_mark_count, 0u); + create_startmap(static_cast(state)->alt.p, static_cast(state)->_map, &static_cast(state)->can_be_null, mask_skip); + // adjust the type of the state to allow for faster matching: + state->type = this->get_repeat_type(state); + } + // restore case sensitivity: + m_icase = l_icase; +} + +template +int basic_regex_creator::calculate_backstep(re_syntax_base* state) +{ + typedef typename traits::char_class_type m_type; + int result = 0; + while(state) + { + switch(state->type) + { + case syntax_element_startmark: + if((static_cast(state)->index == -1) + || (static_cast(state)->index == -2)) + { + state = static_cast(state->next.p)->alt.p->next.p; + continue; + } + else if(static_cast(state)->index == -3) + { + state = state->next.p->next.p; + continue; + } + break; + case syntax_element_endmark: + if((static_cast(state)->index == -1) + || (static_cast(state)->index == -2)) + return result; + break; + case syntax_element_literal: + result += static_cast(state)->length; + break; + case syntax_element_wild: + case syntax_element_set: + result += 1; + break; + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_backref: + case syntax_element_rep: + case syntax_element_combining: + case syntax_element_long_set_rep: + case syntax_element_backstep: + { + re_repeat* rep = static_cast(state); + // adjust the type of the state to allow for faster matching: + state->type = this->get_repeat_type(state); + if((state->type == syntax_element_dot_rep) + || (state->type == syntax_element_char_rep) + || (state->type == syntax_element_short_set_rep)) + { + if(rep->max != rep->min) + return -1; + if (static_cast((std::numeric_limits::max)() - result) < rep->min) + return -1; // protection against overflow, we can't calculate a backstep in this case and the expression is probably ill-formed. + result += static_cast(rep->min); + state = rep->alt.p; + continue; + } + else if(state->type == syntax_element_long_set_rep) + { + BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_long_set); + if(static_cast*>(rep->next.p)->singleton == 0) + return -1; + if(rep->max != rep->min) + return -1; + result += static_cast(rep->min); + state = rep->alt.p; + continue; + } + } + return -1; + case syntax_element_long_set: + if(static_cast*>(state)->singleton == 0) + return -1; + result += 1; + break; + case syntax_element_jump: + state = static_cast(state)->alt.p; + continue; + case syntax_element_alt: + { + int r1 = calculate_backstep(state->next.p); + int r2 = calculate_backstep(static_cast(state)->alt.p); + if((r1 < 0) || (r1 != r2)) + return -1; + return result + r1; + } + default: + break; + } + state = state->next.p; + } + return -1; +} + +struct recursion_saver +{ + std::vector saved_state; + std::vector* state; + recursion_saver(std::vector* p) : saved_state(*p), state(p) {} + ~recursion_saver() + { + state->swap(saved_state); + } +}; + +template +void basic_regex_creator::create_startmap(re_syntax_base* state, unsigned char* l_map, unsigned int* pnull, unsigned char mask) +{ + recursion_saver saved_recursions(&m_recursion_checks); + int not_last_jump = 1; + re_syntax_base* recursion_start = 0; + int recursion_sub = 0; + re_syntax_base* recursion_restart = 0; + + // track case sensitivity: + bool l_icase = m_icase; + + while(state) + { + switch(state->type) + { + case syntax_element_toggle_case: + l_icase = static_cast(state)->icase; + state = state->next.p; + break; + case syntax_element_literal: + { + // don't set anything in *pnull, set each element in l_map + // that could match the first character in the literal: + if(l_map) + { + l_map[0] |= mask_init; + charT first_char = *static_cast(static_cast(static_cast(state) + 1)); + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + if(m_traits.translate(static_cast(i), l_icase) == first_char) + l_map[i] |= mask; + } + } + return; + } + case syntax_element_end_line: + { + // next character must be a line separator (if there is one): + if(l_map) + { + l_map[0] |= mask_init; + l_map[static_cast('\n')] |= mask; + l_map[static_cast('\r')] |= mask; + l_map[static_cast('\f')] |= mask; + l_map[0x85] |= mask; + } + // now figure out if we can match a NULL string at this point: + if(pnull) + create_startmap(state->next.p, 0, pnull, mask); + return; + } + case syntax_element_recurse: + { + BOOST_REGEX_ASSERT(static_cast(state)->alt.p->type == syntax_element_startmark); + recursion_sub = static_cast(static_cast(state)->alt.p)->index; + if(m_recursion_checks[recursion_sub] & 1u) + { + // Infinite recursion!! + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = boost::regex_constants::error_bad_pattern; + // + // clear the expression, we should be empty: + // + this->m_pdata->m_expression = 0; + this->m_pdata->m_expression_len = 0; + // + // and throw if required: + // + if(0 == (this->flags() & regex_constants::no_except)) + { + std::string message = "Encountered an infinite recursion."; + boost::regex_error e(message, boost::regex_constants::error_bad_pattern, 0); + e.raise(); + } + } + else if(recursion_start == 0) + { + recursion_start = state; + recursion_restart = state->next.p; + state = static_cast(state)->alt.p; + m_recursion_checks[recursion_sub] |= 1u; + break; + } + m_recursion_checks[recursion_sub] |= 1u; + // can't handle nested recursion here... + BOOST_REGEX_FALLTHROUGH; + } + case syntax_element_backref: + // can be null, and any character can match: + if(pnull) + *pnull |= mask; + BOOST_REGEX_FALLTHROUGH; + case syntax_element_wild: + { + // can't be null, any character can match: + set_all_masks(l_map, mask); + return; + } + case syntax_element_accept: + case syntax_element_match: + { + // must be null, any character can match: + set_all_masks(l_map, mask); + if(pnull) + *pnull |= mask; + return; + } + case syntax_element_word_start: + { + // recurse, then AND with all the word characters: + create_startmap(state->next.p, l_map, pnull, mask); + if(l_map) + { + l_map[0] |= mask_init; + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + if(!m_traits.isctype(static_cast(i), m_word_mask)) + l_map[i] &= static_cast(~mask); + } + } + return; + } + case syntax_element_word_end: + { + // recurse, then AND with all the word characters: + create_startmap(state->next.p, l_map, pnull, mask); + if(l_map) + { + l_map[0] |= mask_init; + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + if(m_traits.isctype(static_cast(i), m_word_mask)) + l_map[i] &= static_cast(~mask); + } + } + return; + } + case syntax_element_buffer_end: + { + // we *must be null* : + if(pnull) + *pnull |= mask; + return; + } + case syntax_element_long_set: + if(l_map) + { + typedef typename traits::char_class_type m_type; + if(static_cast*>(state)->singleton) + { + l_map[0] |= mask_init; + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + charT c = static_cast(i); + if(&c != re_is_set_member(&c, &c + 1, static_cast*>(state), *m_pdata, l_icase)) + l_map[i] |= mask; + } + } + else + set_all_masks(l_map, mask); + } + return; + case syntax_element_set: + if(l_map) + { + l_map[0] |= mask_init; + for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) + { + if(static_cast(state)->_map[ + static_cast(m_traits.translate(static_cast(i), l_icase))]) + l_map[i] |= mask; + } + } + return; + case syntax_element_jump: + // take the jump: + state = static_cast(state)->alt.p; + not_last_jump = -1; + break; + case syntax_element_alt: + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + { + re_alt* rep = static_cast(state); + if(rep->_map[0] & mask_init) + { + if(l_map) + { + // copy previous results: + l_map[0] |= mask_init; + for(unsigned int i = 0; i <= UCHAR_MAX; ++i) + { + if(rep->_map[i] & mask_any) + l_map[i] |= mask; + } + } + if(pnull) + { + if(rep->can_be_null & mask_any) + *pnull |= mask; + } + } + else + { + // we haven't created a startmap for this alternative yet + // so take the union of the two options: + if(is_bad_repeat(state)) + { + set_all_masks(l_map, mask); + if(pnull) + *pnull |= mask; + return; + } + set_bad_repeat(state); + create_startmap(state->next.p, l_map, pnull, mask); + if((state->type == syntax_element_alt) + || (static_cast(state)->min == 0) + || (not_last_jump == 0)) + create_startmap(rep->alt.p, l_map, pnull, mask); + } + } + return; + case syntax_element_soft_buffer_end: + // match newline or null: + if(l_map) + { + l_map[0] |= mask_init; + l_map[static_cast('\n')] |= mask; + l_map[static_cast('\r')] |= mask; + } + if(pnull) + *pnull |= mask; + return; + case syntax_element_endmark: + // need to handle independent subs as a special case: + if(static_cast(state)->index < 0) + { + // can be null, any character can match: + set_all_masks(l_map, mask); + if(pnull) + *pnull |= mask; + return; + } + else if(recursion_start && (recursion_sub != 0) && (recursion_sub == static_cast(state)->index)) + { + // recursion termination: + recursion_start = 0; + state = recursion_restart; + break; + } + + // + // Normally we just go to the next state... but if this sub-expression is + // the target of a recursion, then we might be ending a recursion, in which + // case we should check whatever follows that recursion, as well as whatever + // follows this state: + // + if(m_pdata->m_has_recursions && static_cast(state)->index) + { + bool ok = false; + re_syntax_base* p = m_pdata->m_first_state; + while(p) + { + if(p->type == syntax_element_recurse) + { + re_brace* p2 = static_cast(static_cast(p)->alt.p); + if((p2->type == syntax_element_startmark) && (p2->index == static_cast(state)->index)) + { + ok = true; + break; + } + } + p = p->next.p; + } + if(ok && ((m_recursion_checks[static_cast(state)->index] & 2u) == 0)) + { + m_recursion_checks[static_cast(state)->index] |= 2u; + create_startmap(p->next.p, l_map, pnull, mask); + } + } + state = state->next.p; + break; + + case syntax_element_commit: + set_all_masks(l_map, mask); + // Continue scanning so we can figure out whether we can be null: + state = state->next.p; + break; + case syntax_element_startmark: + // need to handle independent subs as a special case: + if(static_cast(state)->index == -3) + { + state = state->next.p->next.p; + break; + } + BOOST_REGEX_FALLTHROUGH; + default: + state = state->next.p; + } + ++not_last_jump; + } +} + +template +unsigned basic_regex_creator::get_restart_type(re_syntax_base* state) +{ + // + // find out how the machine starts, so we can optimise the search: + // + while(state) + { + switch(state->type) + { + case syntax_element_startmark: + case syntax_element_endmark: + state = state->next.p; + continue; + case syntax_element_start_line: + return regbase::restart_line; + case syntax_element_word_start: + return regbase::restart_word; + case syntax_element_buffer_start: + return regbase::restart_buf; + case syntax_element_restart_continue: + return regbase::restart_continue; + default: + state = 0; + continue; + } + } + return regbase::restart_any; +} + +template +void basic_regex_creator::set_all_masks(unsigned char* bits, unsigned char mask) +{ + // + // set mask in all of bits elements, + // if bits[0] has mask_init not set then we can + // optimise this to a call to memset: + // + if(bits) + { + if(bits[0] == 0) + (std::memset)(bits, mask, 1u << CHAR_BIT); + else + { + for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) + bits[i] |= mask; + } + bits[0] |= mask_init; + } +} + +template +bool basic_regex_creator::is_bad_repeat(re_syntax_base* pt) +{ + switch(pt->type) + { + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + { + unsigned state_id = static_cast(pt)->state_id; + if(state_id >= sizeof(m_bad_repeats) * CHAR_BIT) + return true; // run out of bits, assume we can't traverse this one. + static const std::uintmax_t one = 1uL; + return m_bad_repeats & (one << state_id); + } + default: + return false; + } +} + +template +void basic_regex_creator::set_bad_repeat(re_syntax_base* pt) +{ + switch(pt->type) + { + case syntax_element_rep: + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + { + unsigned state_id = static_cast(pt)->state_id; + static const std::uintmax_t one = 1uL; + if(state_id <= sizeof(m_bad_repeats) * CHAR_BIT) + m_bad_repeats |= (one << state_id); + } + break; + default: + break; + } +} + +template +syntax_element_type basic_regex_creator::get_repeat_type(re_syntax_base* state) +{ + typedef typename traits::char_class_type m_type; + if(state->type == syntax_element_rep) + { + // check to see if we are repeating a single state: + if(state->next.p->next.p->next.p == static_cast(state)->alt.p) + { + switch(state->next.p->type) + { + case BOOST_REGEX_DETAIL_NS::syntax_element_wild: + return BOOST_REGEX_DETAIL_NS::syntax_element_dot_rep; + case BOOST_REGEX_DETAIL_NS::syntax_element_literal: + return BOOST_REGEX_DETAIL_NS::syntax_element_char_rep; + case BOOST_REGEX_DETAIL_NS::syntax_element_set: + return BOOST_REGEX_DETAIL_NS::syntax_element_short_set_rep; + case BOOST_REGEX_DETAIL_NS::syntax_element_long_set: + if(static_cast*>(state->next.p)->singleton) + return BOOST_REGEX_DETAIL_NS::syntax_element_long_set_rep; + break; + default: + break; + } + } + } + return state->type; +} + +template +void basic_regex_creator::probe_leading_repeat(re_syntax_base* state) +{ + // enumerate our states, and see if we have a leading repeat + // for which failed search restarts can be optimized; + do + { + switch(state->type) + { + case syntax_element_startmark: + if(static_cast(state)->index >= 0) + { + state = state->next.p; + continue; + } +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +#pragma warning(disable:6011) +#endif + if((static_cast(state)->index == -1) + || (static_cast(state)->index == -2)) + { + // skip past the zero width assertion: + state = static_cast(state->next.p)->alt.p->next.p; + continue; + } +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif + if(static_cast(state)->index == -3) + { + // Have to skip the leading jump state: + state = state->next.p->next.p; + continue; + } + return; + case syntax_element_endmark: + case syntax_element_start_line: + case syntax_element_end_line: + case syntax_element_word_boundary: + case syntax_element_within_word: + case syntax_element_word_start: + case syntax_element_word_end: + case syntax_element_buffer_start: + case syntax_element_buffer_end: + case syntax_element_restart_continue: + state = state->next.p; + break; + case syntax_element_dot_rep: + case syntax_element_char_rep: + case syntax_element_short_set_rep: + case syntax_element_long_set_rep: + if(this->m_has_backrefs == 0) + static_cast(state)->leading = true; + BOOST_REGEX_FALLTHROUGH; + default: + return; + } + }while(state); +} + +} // namespace BOOST_REGEX_DETAIL_NS + +} // namespace boost + +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif + +#endif diff --git a/boost/regex/v5/basic_regex_parser.hpp b/boost/regex/v5/basic_regex_parser.hpp new file mode 100644 index 00000000..34d775ef --- /dev/null +++ b/boost/regex/v5/basic_regex_parser.hpp @@ -0,0 +1,3130 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE basic_regex_parser.cpp + * VERSION see + * DESCRIPTION: Declares template class basic_regex_parser. + */ + +#ifndef BOOST_REGEX_V5_BASIC_REGEX_PARSER_HPP +#define BOOST_REGEX_V5_BASIC_REGEX_PARSER_HPP + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4244 4459) +#if BOOST_REGEX_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +inline std::intmax_t umax(std::integral_constant const&) +{ + // Get out clause here, just in case numeric_limits is unspecialized: + return std::numeric_limits::is_specialized ? (std::numeric_limits::max)() : INT_MAX; +} +inline std::intmax_t umax(std::integral_constant const&) +{ + return (std::numeric_limits::max)(); +} + +inline std::intmax_t umax() +{ + return umax(std::integral_constant::digits >= std::numeric_limits::digits>()); +} + +template +class basic_regex_parser : public basic_regex_creator +{ +public: + basic_regex_parser(regex_data* data); + void parse(const charT* p1, const charT* p2, unsigned flags); + void fail(regex_constants::error_type error_code, std::ptrdiff_t position); + void fail(regex_constants::error_type error_code, std::ptrdiff_t position, std::string message, std::ptrdiff_t start_pos); + void fail(regex_constants::error_type error_code, std::ptrdiff_t position, const std::string& message) + { + fail(error_code, position, message, position); + } + + bool parse_all(); + bool parse_basic(); + bool parse_extended(); + bool parse_literal(); + bool parse_open_paren(); + bool parse_basic_escape(); + bool parse_extended_escape(); + bool parse_match_any(); + bool parse_repeat(std::size_t low = 0, std::size_t high = (std::numeric_limits::max)()); + bool parse_repeat_range(bool isbasic); + bool parse_alt(); + bool parse_set(); + bool parse_backref(); + void parse_set_literal(basic_char_set& char_set); + bool parse_inner_set(basic_char_set& char_set); + bool parse_QE(); + bool parse_perl_extension(); + bool parse_perl_verb(); + bool match_verb(const char*); + bool add_emacs_code(bool negate); + bool unwind_alts(std::ptrdiff_t last_paren_start); + digraph get_next_set_literal(basic_char_set& char_set); + charT unescape_character(); + regex_constants::syntax_option_type parse_options(); + +private: + typedef bool (basic_regex_parser::*parser_proc_type)(); + typedef typename traits::string_type string_type; + typedef typename traits::char_class_type char_class_type; + parser_proc_type m_parser_proc; // the main parser to use + const charT* m_base; // the start of the string being parsed + const charT* m_end; // the end of the string being parsed + const charT* m_position; // our current parser position + unsigned m_mark_count; // how many sub-expressions we have + int m_mark_reset; // used to indicate that we're inside a (?|...) block. + unsigned m_max_mark; // largest mark count seen inside a (?|...) block. + std::ptrdiff_t m_paren_start; // where the last seen ')' began (where repeats are inserted). + std::ptrdiff_t m_alt_insert_point; // where to insert the next alternative + bool m_has_case_change; // true if somewhere in the current block the case has changed + unsigned m_recursion_count; // How many times we've called parse_all. + unsigned m_max_backref; // Largest index of any backref. +#if defined(BOOST_REGEX_MSVC) && defined(_M_IX86) + // This is an ugly warning suppression workaround (for warnings *inside* std::vector + // that can not otherwise be suppressed)... + static_assert(sizeof(long) >= sizeof(void*), "Long isn't long enough!"); + std::vector m_alt_jumps; // list of alternative in the current scope. +#else + std::vector m_alt_jumps; // list of alternative in the current scope. +#endif + + basic_regex_parser& operator=(const basic_regex_parser&); + basic_regex_parser(const basic_regex_parser&); +}; + +template +basic_regex_parser::basic_regex_parser(regex_data* data) + : basic_regex_creator(data), m_parser_proc(), m_base(0), m_end(0), m_position(0), + m_mark_count(0), m_mark_reset(-1), m_max_mark(0), m_paren_start(0), m_alt_insert_point(0), m_has_case_change(false), m_recursion_count(0), m_max_backref(0) +{ +} + +template +void basic_regex_parser::parse(const charT* p1, const charT* p2, unsigned l_flags) +{ + // pass l_flags on to base class: + this->init(l_flags); + // set up pointers: + m_position = m_base = p1; + m_end = p2; + // empty strings are errors: + if((p1 == p2) && + ( + ((l_flags & regbase::main_option_type) != regbase::perl_syntax_group) + || (l_flags & regbase::no_empty_expressions) + ) + ) + { + fail(regex_constants::error_empty, 0); + return; + } + // select which parser to use: + switch(l_flags & regbase::main_option_type) + { + case regbase::perl_syntax_group: + { + m_parser_proc = &basic_regex_parser::parse_extended; + // + // Add a leading paren with index zero to give recursions a target: + // + re_brace* br = static_cast(this->append_state(syntax_element_startmark, sizeof(re_brace))); + br->index = 0; + br->icase = this->flags() & regbase::icase; + break; + } + case regbase::basic_syntax_group: + m_parser_proc = &basic_regex_parser::parse_basic; + break; + case regbase::literal: + m_parser_proc = &basic_regex_parser::parse_literal; + break; + default: + // Oops, someone has managed to set more than one of the main option flags, + // so this must be an error: + fail(regex_constants::error_unknown, 0, "An invalid combination of regular expression syntax flags was used."); + return; + } + + // parse all our characters: + bool result = parse_all(); + // + // Unwind our alternatives: + // + unwind_alts(-1); + // reset l_flags as a global scope (?imsx) may have altered them: + this->flags(l_flags); + // if we haven't gobbled up all the characters then we must + // have had an unexpected ')' : + if(!result) + { + fail(regex_constants::error_paren, std::distance(m_base, m_position), "Found a closing ) with no corresponding opening parenthesis."); + return; + } + // if an error has been set then give up now: + if(this->m_pdata->m_status) + return; + // fill in our sub-expression count: + this->m_pdata->m_mark_count = 1u + (std::size_t)m_mark_count; + // + // Check we don't have backreferences to sub-expressions which don't exist: + // + if (m_max_backref > m_mark_count) + { + fail(regex_constants::error_backref, std::distance(m_base, m_position), "Found a backreference to a non-existant sub-expression."); + } + this->finalize(p1, p2); +} + +template +void basic_regex_parser::fail(regex_constants::error_type error_code, std::ptrdiff_t position) +{ + // get the error message: + std::string message = this->m_pdata->m_ptraits->error_string(error_code); + fail(error_code, position, message); +} + +template +void basic_regex_parser::fail(regex_constants::error_type error_code, std::ptrdiff_t position, std::string message, std::ptrdiff_t start_pos) +{ + if(0 == this->m_pdata->m_status) // update the error code if not already set + this->m_pdata->m_status = error_code; + m_position = m_end; // don't bother parsing anything else + + // + // Augment error message with the regular expression text: + // + if(start_pos == position) + start_pos = (std::max)(static_cast(0), position - static_cast(10)); + std::ptrdiff_t end_pos = (std::min)(position + static_cast(10), static_cast(m_end - m_base)); + if(error_code != regex_constants::error_empty) + { + if((start_pos != 0) || (end_pos != (m_end - m_base))) + message += " The error occurred while parsing the regular expression fragment: '"; + else + message += " The error occurred while parsing the regular expression: '"; + if(start_pos != end_pos) + { + message += std::string(m_base + start_pos, m_base + position); + message += ">>>HERE>>>"; + message += std::string(m_base + position, m_base + end_pos); + } + message += "'."; + } + +#ifndef BOOST_NO_EXCEPTIONS + if(0 == (this->flags() & regex_constants::no_except)) + { + boost::regex_error e(message, error_code, position); + e.raise(); + } +#else + (void)position; // suppress warnings. +#endif +} + +template +bool basic_regex_parser::parse_all() +{ + if (++m_recursion_count > 400) + { + // exceeded internal limits + fail(boost::regex_constants::error_complexity, m_position - m_base, "Exceeded nested brace limit."); + } + bool result = true; + while(result && (m_position != m_end)) + { + result = (this->*m_parser_proc)(); + } + --m_recursion_count; + return result; +} + +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4702) +#endif +template +bool basic_regex_parser::parse_basic() +{ + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_escape: + return parse_basic_escape(); + case regex_constants::syntax_dot: + return parse_match_any(); + case regex_constants::syntax_caret: + ++m_position; + this->append_state(syntax_element_start_line); + break; + case regex_constants::syntax_dollar: + ++m_position; + this->append_state(syntax_element_end_line); + break; + case regex_constants::syntax_star: + if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line)) + return parse_literal(); + else + { + ++m_position; + return parse_repeat(); + } + case regex_constants::syntax_plus: + if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line) || !(this->flags() & regbase::emacs_ex)) + return parse_literal(); + else + { + ++m_position; + return parse_repeat(1); + } + case regex_constants::syntax_question: + if(!(this->m_last_state) || (this->m_last_state->type == syntax_element_start_line) || !(this->flags() & regbase::emacs_ex)) + return parse_literal(); + else + { + ++m_position; + return parse_repeat(0, 1); + } + case regex_constants::syntax_open_set: + return parse_set(); + case regex_constants::syntax_newline: + if(this->flags() & regbase::newline_alt) + return parse_alt(); + else + return parse_literal(); + default: + return parse_literal(); + } + return true; +} + +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +#if BOOST_REGEX_MSVC >= 1800 +#pragma warning(disable:26812) +#endif +#endif +template +bool basic_regex_parser::parse_extended() +{ + bool result = true; + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_open_mark: + return parse_open_paren(); + case regex_constants::syntax_close_mark: + return false; + case regex_constants::syntax_escape: + return parse_extended_escape(); + case regex_constants::syntax_dot: + return parse_match_any(); + case regex_constants::syntax_caret: + ++m_position; + this->append_state( + (this->flags() & regex_constants::no_mod_m ? syntax_element_buffer_start : syntax_element_start_line)); + break; + case regex_constants::syntax_dollar: + ++m_position; + this->append_state( + (this->flags() & regex_constants::no_mod_m ? syntax_element_buffer_end : syntax_element_end_line)); + break; + case regex_constants::syntax_star: + if(m_position == this->m_base) + { + fail(regex_constants::error_badrepeat, 0, "The repeat operator \"*\" cannot start a regular expression."); + return false; + } + ++m_position; + return parse_repeat(); + case regex_constants::syntax_question: + if(m_position == this->m_base) + { + fail(regex_constants::error_badrepeat, 0, "The repeat operator \"?\" cannot start a regular expression."); + return false; + } + ++m_position; + return parse_repeat(0,1); + case regex_constants::syntax_plus: + if(m_position == this->m_base) + { + fail(regex_constants::error_badrepeat, 0, "The repeat operator \"+\" cannot start a regular expression."); + return false; + } + ++m_position; + return parse_repeat(1); + case regex_constants::syntax_open_brace: + ++m_position; + return parse_repeat_range(false); + case regex_constants::syntax_close_brace: + if((this->flags() & regbase::no_perl_ex) == regbase::no_perl_ex) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, "Found a closing repetition operator } with no corresponding {."); + return false; + } + result = parse_literal(); + break; + case regex_constants::syntax_or: + return parse_alt(); + case regex_constants::syntax_open_set: + return parse_set(); + case regex_constants::syntax_newline: + if(this->flags() & regbase::newline_alt) + return parse_alt(); + else + return parse_literal(); + case regex_constants::syntax_hash: + // + // If we have a mod_x flag set, then skip until + // we get to a newline character: + // + if((this->flags() + & (regbase::no_perl_ex|regbase::mod_x)) + == regbase::mod_x) + { + while((m_position != m_end) && !is_separator(*m_position++)){} + return true; + } + BOOST_REGEX_FALLTHROUGH; + default: + result = parse_literal(); + break; + } + return result; +} +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif + +template +bool basic_regex_parser::parse_literal() +{ + // append this as a literal provided it's not a space character + // or the perl option regbase::mod_x is not set: + if( + ((this->flags() + & (regbase::main_option_type|regbase::mod_x|regbase::no_perl_ex)) + != regbase::mod_x) + || !this->m_traits.isctype(*m_position, this->m_mask_space)) + this->append_literal(*m_position); + ++m_position; + return true; +} + +template +bool basic_regex_parser::parse_open_paren() +{ + // + // skip the '(' and error check: + // + if(++m_position == m_end) + { + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + // + // begin by checking for a perl-style (?...) extension: + // + if( + ((this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) == 0) + || ((this->flags() & (regbase::main_option_type | regbase::emacs_ex)) == (regbase::basic_syntax_group|regbase::emacs_ex)) + ) + { + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_question) + return parse_perl_extension(); + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_star) + return parse_perl_verb(); + } + // + // update our mark count, and append the required state: + // + unsigned markid = 0; + if(0 == (this->flags() & regbase::nosubs)) + { + markid = ++m_mark_count; + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.push_back(std::pair(std::distance(m_base, m_position) - 1, 0)); + } + re_brace* pb = static_cast(this->append_state(syntax_element_startmark, sizeof(re_brace))); + pb->index = markid; + pb->icase = this->flags() & regbase::icase; + std::ptrdiff_t last_paren_start = this->getoffset(pb); + // back up insertion point for alternations, and set new point: + std::ptrdiff_t last_alt_point = m_alt_insert_point; + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + // + // back up the current flags in case we have a nested (?imsx) group: + // + regex_constants::syntax_option_type opts = this->flags(); + bool old_case_change = m_has_case_change; + m_has_case_change = false; // no changes to this scope as yet... + // + // Back up branch reset data in case we have a nested (?|...) + // + int mark_reset = m_mark_reset; + m_mark_reset = -1; + // + // now recursively add more states, this will terminate when we get to a + // matching ')' : + // + parse_all(); + // + // Unwind pushed alternatives: + // + if(0 == unwind_alts(last_paren_start)) + return false; + // + // restore flags: + // + if(m_has_case_change) + { + // the case has changed in one or more of the alternatives + // within the scoped (...) block: we have to add a state + // to reset the case sensitivity: + static_cast( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = opts & regbase::icase; + } + this->flags(opts); + m_has_case_change = old_case_change; + // + // restore branch reset: + // + m_mark_reset = mark_reset; + // + // we either have a ')' or we have run out of characters prematurely: + // + if(m_position == m_end) + { + this->fail(regex_constants::error_paren, std::distance(m_base, m_end)); + return false; + } + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + return false; + if(markid && (this->flags() & regbase::save_subexpression_location)) + this->m_pdata->m_subs.at(markid - 1).second = std::distance(m_base, m_position); + ++m_position; + // + // append closing parenthesis state: + // + pb = static_cast(this->append_state(syntax_element_endmark, sizeof(re_brace))); + pb->index = markid; + pb->icase = this->flags() & regbase::icase; + this->m_paren_start = last_paren_start; + // + // restore the alternate insertion point: + // + this->m_alt_insert_point = last_alt_point; + + return true; +} + +template +bool basic_regex_parser::parse_basic_escape() +{ + if(++m_position == m_end) + { + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + bool result = true; + switch(this->m_traits.escape_syntax_type(*m_position)) + { + case regex_constants::syntax_open_mark: + return parse_open_paren(); + case regex_constants::syntax_close_mark: + return false; + case regex_constants::syntax_plus: + if(this->flags() & regex_constants::bk_plus_qm) + { + ++m_position; + return parse_repeat(1); + } + else + return parse_literal(); + case regex_constants::syntax_question: + if(this->flags() & regex_constants::bk_plus_qm) + { + ++m_position; + return parse_repeat(0, 1); + } + else + return parse_literal(); + case regex_constants::syntax_open_brace: + if(this->flags() & regbase::no_intervals) + return parse_literal(); + ++m_position; + return parse_repeat_range(true); + case regex_constants::syntax_close_brace: + if(this->flags() & regbase::no_intervals) + return parse_literal(); + fail(regex_constants::error_brace, this->m_position - this->m_base, "Found a closing repetition operator } with no corresponding {."); + return false; + case regex_constants::syntax_or: + if(this->flags() & regbase::bk_vbar) + return parse_alt(); + else + result = parse_literal(); + break; + case regex_constants::syntax_digit: + return parse_backref(); + case regex_constants::escape_type_start_buffer: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_buffer_start); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_end_buffer: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_buffer_end); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_word_assert: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_word_boundary); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_not_word_assert: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_within_word); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_left_word: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_word_start); + } + else + result = parse_literal(); + break; + case regex_constants::escape_type_right_word: + if(this->flags() & regbase::emacs_ex) + { + ++m_position; + this->append_state(syntax_element_word_end); + } + else + result = parse_literal(); + break; + default: + if(this->flags() & regbase::emacs_ex) + { + bool negate = true; + switch(*m_position) + { + case 'w': + negate = false; + BOOST_REGEX_FALLTHROUGH; + case 'W': + { + basic_char_set char_set; + if(negate) + char_set.negate(); + char_set.add_class(this->m_word_mask); + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + ++m_position; + return true; + } + case 's': + negate = false; + BOOST_REGEX_FALLTHROUGH; + case 'S': + return add_emacs_code(negate); + case 'c': + case 'C': + // not supported yet: + fail(regex_constants::error_escape, m_position - m_base, "The \\c and \\C escape sequences are not supported by POSIX basic regular expressions: try the Perl syntax instead."); + return false; + default: + break; + } + } + result = parse_literal(); + break; + } + return result; +} + +template +bool basic_regex_parser::parse_extended_escape() +{ + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base, "Incomplete escape sequence found."); + return false; + } + bool negate = false; // in case this is a character class escape: \w \d etc + switch(this->m_traits.escape_syntax_type(*m_position)) + { + case regex_constants::escape_type_not_class: + negate = true; + BOOST_REGEX_FALLTHROUGH; + case regex_constants::escape_type_class: + { +escape_type_class_jump: + typedef typename traits::char_class_type m_type; + m_type m = this->m_traits.lookup_classname(m_position, m_position+1); + if(m != 0) + { + basic_char_set char_set; + if(negate) + char_set.negate(); + char_set.add_class(m); + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + ++m_position; + return true; + } + // + // not a class, just a regular unknown escape: + // + this->append_literal(unescape_character()); + break; + } + case regex_constants::syntax_digit: + return parse_backref(); + case regex_constants::escape_type_left_word: + ++m_position; + this->append_state(syntax_element_word_start); + break; + case regex_constants::escape_type_right_word: + ++m_position; + this->append_state(syntax_element_word_end); + break; + case regex_constants::escape_type_start_buffer: + ++m_position; + this->append_state(syntax_element_buffer_start); + break; + case regex_constants::escape_type_end_buffer: + ++m_position; + this->append_state(syntax_element_buffer_end); + break; + case regex_constants::escape_type_word_assert: + ++m_position; + this->append_state(syntax_element_word_boundary); + break; + case regex_constants::escape_type_not_word_assert: + ++m_position; + this->append_state(syntax_element_within_word); + break; + case regex_constants::escape_type_Z: + ++m_position; + this->append_state(syntax_element_soft_buffer_end); + break; + case regex_constants::escape_type_Q: + return parse_QE(); + case regex_constants::escape_type_C: + return parse_match_any(); + case regex_constants::escape_type_X: + ++m_position; + this->append_state(syntax_element_combining); + break; + case regex_constants::escape_type_G: + ++m_position; + this->append_state(syntax_element_restart_continue); + break; + case regex_constants::escape_type_not_property: + negate = true; + BOOST_REGEX_FALLTHROUGH; + case regex_constants::escape_type_property: + { + ++m_position; + char_class_type m; + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base, "Incomplete property escape found."); + return false; + } + // maybe have \p{ddd} + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace) + { + const charT* base = m_position; + // skip forward until we find enclosing brace: + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace)) + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base, "Closing } missing from property escape sequence."); + return false; + } + m = this->m_traits.lookup_classname(++base, m_position++); + } + else + { + m = this->m_traits.lookup_classname(m_position, m_position+1); + ++m_position; + } + if(m != 0) + { + basic_char_set char_set; + if(negate) + char_set.negate(); + char_set.add_class(m); + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + return true; + } + fail(regex_constants::error_ctype, m_position - m_base, "Escape sequence was neither a valid property nor a valid character class name."); + return false; + } + case regex_constants::escape_type_reset_start_mark: + if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + { + re_brace* pb = static_cast(this->append_state(syntax_element_startmark, sizeof(re_brace))); + pb->index = -5; + pb->icase = this->flags() & regbase::icase; + this->m_pdata->m_data.align(); + ++m_position; + return true; + } + goto escape_type_class_jump; + case regex_constants::escape_type_line_ending: + if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + { + const charT* e = get_escape_R_string(); + const charT* old_position = m_position; + const charT* old_end = m_end; + const charT* old_base = m_base; + m_position = e; + m_base = e; + m_end = e + traits::length(e); + bool r = parse_all(); + m_position = ++old_position; + m_end = old_end; + m_base = old_base; + return r; + } + goto escape_type_class_jump; + case regex_constants::escape_type_extended_backref: + if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + { + bool have_brace = false; + bool negative = false; + static const char incomplete_message[] = "Incomplete \\g escape found."; + if(++m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base, incomplete_message); + return false; + } + // maybe have \g{ddd} + regex_constants::syntax_type syn = this->m_traits.syntax_type(*m_position); + regex_constants::syntax_type syn_end = 0; + if((syn == regex_constants::syntax_open_brace) + || (syn == regex_constants::escape_type_left_word) + || (syn == regex_constants::escape_type_end_buffer)) + { + if(++m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base, incomplete_message); + return false; + } + have_brace = true; + switch(syn) + { + case regex_constants::syntax_open_brace: + syn_end = regex_constants::syntax_close_brace; + break; + case regex_constants::escape_type_left_word: + syn_end = regex_constants::escape_type_right_word; + break; + default: + syn_end = regex_constants::escape_type_end_buffer; + break; + } + } + negative = (*m_position == static_cast('-')); + if((negative) && (++m_position == m_end)) + { + fail(regex_constants::error_escape, m_position - m_base, incomplete_message); + return false; + } + const charT* pc = m_position; + std::intmax_t i = this->m_traits.toi(pc, m_end, 10); + if((i < 0) && syn_end) + { + // Check for a named capture, get the leftmost one if there is more than one: + const charT* base = m_position; + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != syn_end)) + { + ++m_position; + } + i = hash_value_from_capture_name(base, m_position); + pc = m_position; + } + if(negative) + i = 1 + (static_cast(m_mark_count) - i); + if(((i < hash_value_mask) && (i > 0)) || ((i >= hash_value_mask) && (this->m_pdata->get_id((int)i) > 0))) + { + m_position = pc; + re_brace* pb = static_cast(this->append_state(syntax_element_backref, sizeof(re_brace))); + pb->index = (int)i; + pb->icase = this->flags() & regbase::icase; + if ((i > m_max_backref) && (i < hash_value_mask)) + m_max_backref = i; + } + else + { + fail(regex_constants::error_backref, m_position - m_base); + return false; + } + m_position = pc; + if(have_brace) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != syn_end)) + { + fail(regex_constants::error_escape, m_position - m_base, incomplete_message); + return false; + } + ++m_position; + } + return true; + } + goto escape_type_class_jump; + case regex_constants::escape_type_control_v: + if(0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + goto escape_type_class_jump; + BOOST_REGEX_FALLTHROUGH; + default: + this->append_literal(unescape_character()); + break; + } + return true; +} + +template +bool basic_regex_parser::parse_match_any() +{ + // + // we have a '.' that can match any character: + // + ++m_position; + static_cast( + this->append_state(syntax_element_wild, sizeof(re_dot)) + )->mask = static_cast(this->flags() & regbase::no_mod_s + ? BOOST_REGEX_DETAIL_NS::force_not_newline + : this->flags() & regbase::mod_s ? + BOOST_REGEX_DETAIL_NS::force_newline : BOOST_REGEX_DETAIL_NS::dont_care); + return true; +} + +template +bool basic_regex_parser::parse_repeat(std::size_t low, std::size_t high) +{ + bool greedy = true; + bool possessive = false; + std::size_t insert_point; + // + // when we get to here we may have a non-greedy ? mark still to come: + // + if((m_position != m_end) + && ( + (0 == (this->flags() & (regbase::main_option_type | regbase::no_perl_ex))) + || ((regbase::basic_syntax_group|regbase::emacs_ex) == (this->flags() & (regbase::main_option_type | regbase::emacs_ex))) + ) + ) + { + // OK we have a perl or emacs regex, check for a '?': + if ((this->flags() & (regbase::main_option_type | regbase::mod_x | regbase::no_perl_ex)) == regbase::mod_x) + { + // whitespace skip: + while ((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + } + if((m_position != m_end) && (this->m_traits.syntax_type(*m_position) == regex_constants::syntax_question)) + { + greedy = false; + ++m_position; + } + // for perl regexes only check for possessive ++ repeats. + if((m_position != m_end) + && (0 == (this->flags() & regbase::main_option_type)) + && (this->m_traits.syntax_type(*m_position) == regex_constants::syntax_plus)) + { + possessive = true; + ++m_position; + } + } + if(0 == this->m_last_state) + { + fail(regex_constants::error_badrepeat, std::distance(m_base, m_position), "Nothing to repeat."); + return false; + } + if(this->m_last_state->type == syntax_element_endmark) + { + // insert a repeat before the '(' matching the last ')': + insert_point = this->m_paren_start; + } + else if((this->m_last_state->type == syntax_element_literal) && (static_cast(this->m_last_state)->length > 1)) + { + // the last state was a literal with more than one character, split it in two: + re_literal* lit = static_cast(this->m_last_state); + charT c = (static_cast(static_cast(lit+1)))[lit->length - 1]; + lit->length -= 1; + // now append new state: + lit = static_cast(this->append_state(syntax_element_literal, sizeof(re_literal) + sizeof(charT))); + lit->length = 1; + (static_cast(static_cast(lit+1)))[0] = c; + insert_point = this->getoffset(this->m_last_state); + } + else + { + // repeat the last state whatever it was, need to add some error checking here: + switch(this->m_last_state->type) + { + case syntax_element_start_line: + case syntax_element_end_line: + case syntax_element_word_boundary: + case syntax_element_within_word: + case syntax_element_word_start: + case syntax_element_word_end: + case syntax_element_buffer_start: + case syntax_element_buffer_end: + case syntax_element_alt: + case syntax_element_soft_buffer_end: + case syntax_element_restart_continue: + case syntax_element_jump: + case syntax_element_startmark: + case syntax_element_backstep: + case syntax_element_toggle_case: + // can't legally repeat any of the above: + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + default: + // do nothing... + break; + } + insert_point = this->getoffset(this->m_last_state); + } + // + // OK we now know what to repeat, so insert the repeat around it: + // + re_repeat* rep = static_cast(this->insert_state(insert_point, syntax_element_rep, re_repeater_size)); + rep->min = low; + rep->max = high; + rep->greedy = greedy; + rep->leading = false; + // store our repeater position for later: + std::ptrdiff_t rep_off = this->getoffset(rep); + // and append a back jump to the repeat: + re_jump* jmp = static_cast(this->append_state(syntax_element_jump, sizeof(re_jump))); + jmp->alt.i = rep_off - this->getoffset(jmp); + this->m_pdata->m_data.align(); + // now fill in the alt jump for the repeat: + rep = static_cast(this->getaddress(rep_off)); + rep->alt.i = this->m_pdata->m_data.size() - rep_off; + // + // If the repeat is possessive then bracket the repeat with a (?>...) + // independent sub-expression construct: + // + if(possessive) + { + if(m_position != m_end) + { + // + // Check for illegal following quantifier, we have to do this here, because + // the extra states we insert below circumvents our usual error checking :-( + // + bool contin = false; + do + { + if ((this->flags() & (regbase::main_option_type | regbase::mod_x | regbase::no_perl_ex)) == regbase::mod_x) + { + // whitespace skip: + while ((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + } + if (m_position != m_end) + { + switch (this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_star: + case regex_constants::syntax_plus: + case regex_constants::syntax_question: + case regex_constants::syntax_open_brace: + fail(regex_constants::error_badrepeat, m_position - m_base); + return false; + case regex_constants::syntax_open_mark: + // Do we have a comment? If so we need to skip it here... + if ((m_position + 2 < m_end) && this->m_traits.syntax_type(*(m_position + 1)) == regex_constants::syntax_question + && this->m_traits.syntax_type(*(m_position + 2)) == regex_constants::syntax_hash) + { + while ((m_position != m_end) + && (this->m_traits.syntax_type(*m_position++) != regex_constants::syntax_close_mark)) { + } + contin = true; + } + else + contin = false; + break; + default: + contin = false; + } + } + else + contin = false; + } while (contin); + } + re_brace* pb = static_cast(this->insert_state(insert_point, syntax_element_startmark, sizeof(re_brace))); + pb->index = -3; + pb->icase = this->flags() & regbase::icase; + jmp = static_cast(this->insert_state(insert_point + sizeof(re_brace), syntax_element_jump, sizeof(re_jump))); + this->m_pdata->m_data.align(); + jmp->alt.i = this->m_pdata->m_data.size() - this->getoffset(jmp); + pb = static_cast(this->append_state(syntax_element_endmark, sizeof(re_brace))); + pb->index = -3; + pb->icase = this->flags() & regbase::icase; + } + return true; +} + +template +bool basic_regex_parser::parse_repeat_range(bool isbasic) +{ + static const char incomplete_message[] = "Missing } in quantified repetition."; + // + // parse a repeat-range: + // + std::size_t min, max; + std::intmax_t v; + // skip whitespace: + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + if(this->m_position == this->m_end) + { + if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + // Treat the opening '{' as a literal character, rewind to start of error: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position; + return parse_literal(); + } + // get min: + v = this->m_traits.toi(m_position, m_end, 10); + // skip whitespace: + if((v < 0) || (v > umax())) + { + if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + // Treat the opening '{' as a literal character, rewind to start of error: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position; + return parse_literal(); + } + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + if(this->m_position == this->m_end) + { + if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + // Treat the opening '{' as a literal character, rewind to start of error: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position; + return parse_literal(); + } + min = static_cast(v); + // see if we have a comma: + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_comma) + { + // move on and error check: + ++m_position; + // skip whitespace: + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + if(this->m_position == this->m_end) + { + if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + // Treat the opening '{' as a literal character, rewind to start of error: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position; + return parse_literal(); + } + // get the value if any: + v = this->m_traits.toi(m_position, m_end, 10); + max = ((v >= 0) && (v < umax())) ? (std::size_t)v : (std::numeric_limits::max)(); + } + else + { + // no comma, max = min: + max = min; + } + // skip whitespace: + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) + ++m_position; + // OK now check trailing }: + if(this->m_position == this->m_end) + { + if(this->flags() & (regbase::main_option_type | regbase::no_perl_ex)) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + // Treat the opening '{' as a literal character, rewind to start of error: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position; + return parse_literal(); + } + if(isbasic) + { + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_escape) + { + ++m_position; + if(this->m_position == this->m_end) + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + } + else + { + fail(regex_constants::error_brace, this->m_position - this->m_base, incomplete_message); + return false; + } + } + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_brace) + ++m_position; + else + { + // Treat the opening '{' as a literal character, rewind to start of error: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_brace) --m_position; + return parse_literal(); + } + // + // finally go and add the repeat, unless error: + // + if(min > max) + { + // Backtrack to error location: + m_position -= 2; + while(this->m_traits.isctype(*m_position, this->m_word_mask)) --m_position; + ++m_position; + fail(regex_constants::error_badbrace, m_position - m_base); + return false; + } + return parse_repeat(min, max); +} + +template +bool basic_regex_parser::parse_alt() +{ + // + // error check: if there have been no previous states, + // or if the last state was a '(' then error: + // + if( + ((this->m_last_state == 0) || (this->m_last_state->type == syntax_element_startmark)) + && + !( + ((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) + && + ((this->flags() & regbase::no_empty_expressions) == 0) + ) + ) + { + fail(regex_constants::error_empty, this->m_position - this->m_base, "A regular expression cannot start with the alternation operator |."); + return false; + } + // + // Reset mark count if required: + // + if(m_max_mark < m_mark_count) + m_max_mark = m_mark_count; + if(m_mark_reset >= 0) + m_mark_count = m_mark_reset; + + ++m_position; + // + // we need to append a trailing jump: + // + re_syntax_base* pj = this->append_state(BOOST_REGEX_DETAIL_NS::syntax_element_jump, sizeof(re_jump)); + std::ptrdiff_t jump_offset = this->getoffset(pj); + // + // now insert the alternative: + // + re_alt* palt = static_cast(this->insert_state(this->m_alt_insert_point, syntax_element_alt, re_alt_size)); + jump_offset += re_alt_size; + this->m_pdata->m_data.align(); + palt->alt.i = this->m_pdata->m_data.size() - this->getoffset(palt); + // + // update m_alt_insert_point so that the next alternate gets + // inserted at the start of the second of the two we've just created: + // + this->m_alt_insert_point = this->m_pdata->m_data.size(); + // + // the start of this alternative must have a case changes state + // if the current block has messed around with case changes: + // + if(m_has_case_change) + { + static_cast( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = this->m_icase; + } + // + // push the alternative onto our stack, a recursive + // implementation here is easier to understand (and faster + // as it happens), but causes all kinds of stack overflow problems + // on programs with small stacks (COM+). + // + m_alt_jumps.push_back(jump_offset); + return true; +} + +template +bool basic_regex_parser::parse_set() +{ + static const char incomplete_message[] = "Character set declaration starting with [ terminated prematurely - either no ] was found or the set had no content."; + ++m_position; + if(m_position == m_end) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + basic_char_set char_set; + + const charT* base = m_position; // where the '[' was + const charT* item_base = m_position; // where the '[' or '^' was + + while(m_position != m_end) + { + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_caret: + if(m_position == base) + { + char_set.negate(); + ++m_position; + item_base = m_position; + } + else + parse_set_literal(char_set); + break; + case regex_constants::syntax_close_set: + if(m_position == item_base) + { + parse_set_literal(char_set); + break; + } + else + { + ++m_position; + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + } + return true; + case regex_constants::syntax_open_set: + if(parse_inner_set(char_set)) + break; + return true; + case regex_constants::syntax_escape: + { + // + // look ahead and see if this is a character class shortcut + // \d \w \s etc... + // + ++m_position; + if(this->m_traits.escape_syntax_type(*m_position) + == regex_constants::escape_type_class) + { + char_class_type m = this->m_traits.lookup_classname(m_position, m_position+1); + if(m != 0) + { + char_set.add_class(m); + ++m_position; + break; + } + } + else if(this->m_traits.escape_syntax_type(*m_position) + == regex_constants::escape_type_not_class) + { + // negated character class: + char_class_type m = this->m_traits.lookup_classname(m_position, m_position+1); + if(m != 0) + { + char_set.add_negated_class(m); + ++m_position; + break; + } + } + // not a character class, just a regular escape: + --m_position; + parse_set_literal(char_set); + break; + } + default: + parse_set_literal(char_set); + break; + } + } + return m_position != m_end; +} + +template +bool basic_regex_parser::parse_inner_set(basic_char_set& char_set) +{ + static const char incomplete_message[] = "Character class declaration starting with [ terminated prematurely - either no ] was found or the set had no content."; + // + // we have either a character class [:name:] + // a collating element [.name.] + // or an equivalence class [=name=] + // + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_dot: + // + // a collating element is treated as a literal: + // + --m_position; + parse_set_literal(char_set); + return true; + case regex_constants::syntax_colon: + { + // check that character classes are actually enabled: + if((this->flags() & (regbase::main_option_type | regbase::no_char_classes)) + == (regbase::basic_syntax_group | regbase::no_char_classes)) + { + --m_position; + parse_set_literal(char_set); + return true; + } + // skip the ':' + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + const charT* name_first = m_position; + // skip at least one character, then find the matching ':]' + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_colon)) + ++m_position; + const charT* name_last = m_position; + if(m_end == m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + if((m_end == ++m_position) + || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + // + // check for negated class: + // + bool negated = false; + if(this->m_traits.syntax_type(*name_first) == regex_constants::syntax_caret) + { + ++name_first; + negated = true; + } + typedef typename traits::char_class_type m_type; + m_type m = this->m_traits.lookup_classname(name_first, name_last); + if(m == 0) + { + if(char_set.empty() && (name_last - name_first == 1)) + { + // maybe a special case: + ++m_position; + if( (m_position != m_end) + && (this->m_traits.syntax_type(*m_position) + == regex_constants::syntax_close_set)) + { + if(this->m_traits.escape_syntax_type(*name_first) + == regex_constants::escape_type_left_word) + { + ++m_position; + this->append_state(syntax_element_word_start); + return false; + } + if(this->m_traits.escape_syntax_type(*name_first) + == regex_constants::escape_type_right_word) + { + ++m_position; + this->append_state(syntax_element_word_end); + return false; + } + } + } + fail(regex_constants::error_ctype, name_first - m_base); + return false; + } + if(!negated) + char_set.add_class(m); + else + char_set.add_negated_class(m); + ++m_position; + break; + } + case regex_constants::syntax_equal: + { + // skip the '=' + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + const charT* name_first = m_position; + // skip at least one character, then find the matching '=]' + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal)) + ++m_position; + const charT* name_last = m_position; + if(m_end == m_position) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + if((m_end == ++m_position) + || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)) + { + fail(regex_constants::error_brack, m_position - m_base, incomplete_message); + return false; + } + string_type m = this->m_traits.lookup_collatename(name_first, name_last); + if(m.empty() || (m.size() > 2)) + { + fail(regex_constants::error_collate, name_first - m_base); + return false; + } + digraph d; + d.first = m[0]; + if(m.size() > 1) + d.second = m[1]; + else + d.second = 0; + char_set.add_equivalent(d); + ++m_position; + break; + } + default: + --m_position; + parse_set_literal(char_set); + break; + } + return true; +} + +template +void basic_regex_parser::parse_set_literal(basic_char_set& char_set) +{ + digraph start_range(get_next_set_literal(char_set)); + if(m_end == m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return; + } + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_dash) + { + // we have a range: + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return; + } + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set) + { + digraph end_range = get_next_set_literal(char_set); + char_set.add_range(start_range, end_range); + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_dash) + { + if(m_end == ++m_position) + { + fail(regex_constants::error_brack, m_position - m_base); + return; + } + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_set) + { + // trailing - : + --m_position; + return; + } + fail(regex_constants::error_range, m_position - m_base); + return; + } + return; + } + --m_position; + } + char_set.add_single(start_range); +} + +template +digraph basic_regex_parser::get_next_set_literal(basic_char_set& char_set) +{ + digraph result; + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_dash: + if(!char_set.empty()) + { + // see if we are at the end of the set: + if((++m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)) + { + fail(regex_constants::error_range, m_position - m_base); + return result; + } + --m_position; + } + result.first = *m_position++; + return result; + case regex_constants::syntax_escape: + // check to see if escapes are supported first: + if(this->flags() & regex_constants::no_escape_in_lists) + { + result = *m_position++; + break; + } + ++m_position; + result = unescape_character(); + break; + case regex_constants::syntax_open_set: + { + if(m_end == ++m_position) + { + fail(regex_constants::error_collate, m_position - m_base); + return result; + } + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_dot) + { + --m_position; + result.first = *m_position; + ++m_position; + return result; + } + if(m_end == ++m_position) + { + fail(regex_constants::error_collate, m_position - m_base); + return result; + } + const charT* name_first = m_position; + // skip at least one character, then find the matching ':]' + if(m_end == ++m_position) + { + fail(regex_constants::error_collate, name_first - m_base); + return result; + } + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_dot)) + ++m_position; + const charT* name_last = m_position; + if(m_end == m_position) + { + fail(regex_constants::error_collate, name_first - m_base); + return result; + } + if((m_end == ++m_position) + || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_set)) + { + fail(regex_constants::error_collate, name_first - m_base); + return result; + } + ++m_position; + string_type s = this->m_traits.lookup_collatename(name_first, name_last); + if(s.empty() || (s.size() > 2)) + { + fail(regex_constants::error_collate, name_first - m_base); + return result; + } + result.first = s[0]; + if(s.size() > 1) + result.second = s[1]; + else + result.second = 0; + return result; + } + default: + result = *m_position++; + } + return result; +} + +// +// does a value fit in the specified charT type? +// +template +bool valid_value(charT, std::intmax_t v, const std::integral_constant&) +{ + return (v >> (sizeof(charT) * CHAR_BIT)) == 0; +} +template +bool valid_value(charT, std::intmax_t, const std::integral_constant&) +{ + return true; // v will alsways fit in a charT +} +template +bool valid_value(charT c, std::intmax_t v) +{ + return valid_value(c, v, std::integral_constant()); +} + +template +charT basic_regex_parser::unescape_character() +{ +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + charT result(0); + if(m_position == m_end) + { + fail(regex_constants::error_escape, m_position - m_base, "Escape sequence terminated prematurely."); + return false; + } + switch(this->m_traits.escape_syntax_type(*m_position)) + { + case regex_constants::escape_type_control_a: + result = charT('\a'); + break; + case regex_constants::escape_type_e: + result = charT(27); + break; + case regex_constants::escape_type_control_f: + result = charT('\f'); + break; + case regex_constants::escape_type_control_n: + result = charT('\n'); + break; + case regex_constants::escape_type_control_r: + result = charT('\r'); + break; + case regex_constants::escape_type_control_t: + result = charT('\t'); + break; + case regex_constants::escape_type_control_v: + result = charT('\v'); + break; + case regex_constants::escape_type_word_assert: + result = charT('\b'); + break; + case regex_constants::escape_type_ascii_control: + ++m_position; + if(m_position == m_end) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base, "ASCII escape sequence terminated prematurely."); + return result; + } + result = static_cast(*m_position % 32); + break; + case regex_constants::escape_type_hex: + ++m_position; + if(m_position == m_end) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base, "Hexadecimal escape sequence terminated prematurely."); + return result; + } + // maybe have \x{ddd} + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace) + { + ++m_position; + if(m_position == m_end) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base, "Missing } in hexadecimal escape sequence."); + return result; + } + std::intmax_t i = this->m_traits.toi(m_position, m_end, 16); + if((m_position == m_end) + || (i < 0) + || ((std::numeric_limits::is_specialized) && (i > (std::intmax_t)(std::numeric_limits::max)())) + || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace)) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_badbrace, m_position - m_base, "Hexadecimal escape sequence was invalid."); + return result; + } + ++m_position; + result = charT(i); + } + else + { + std::ptrdiff_t len = (std::min)(static_cast(2), static_cast(m_end - m_position)); + std::intmax_t i = this->m_traits.toi(m_position, m_position + len, 16); + if((i < 0) + || !valid_value(charT(0), i)) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base, "Escape sequence did not encode a valid character."); + return result; + } + result = charT(i); + } + return result; + case regex_constants::syntax_digit: + { + // an octal escape sequence, the first character must be a zero + // followed by up to 3 octal digits: + std::ptrdiff_t len = (std::min)(std::distance(m_position, m_end), static_cast(4)); + const charT* bp = m_position; + std::intmax_t val = this->m_traits.toi(bp, bp + 1, 8); + if(val != 0) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + // Oops not an octal escape after all: + fail(regex_constants::error_escape, m_position - m_base, "Invalid octal escape sequence."); + return result; + } + val = this->m_traits.toi(m_position, m_position + len, 8); + if((val < 0) || (val > (std::intmax_t)(std::numeric_limits::max)())) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base, "Octal escape sequence is invalid."); + return result; + } + return static_cast(val); + } + case regex_constants::escape_type_named_char: + { + ++m_position; + if(m_position == m_end) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + // maybe have \N{name} + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_open_brace) + { + const charT* base = m_position; + // skip forward until we find enclosing brace: + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_brace)) + ++m_position; + if(m_position == m_end) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + string_type s = this->m_traits.lookup_collatename(++base, m_position++); + if(s.empty()) + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_collate, m_position - m_base); + return false; + } + if(s.size() == 1) + { + return s[0]; + } + } + // fall through is a failure: + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + default: + result = *m_position; + break; + } + ++m_position; + return result; +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif +} + +template +bool basic_regex_parser::parse_backref() +{ + BOOST_REGEX_ASSERT(m_position != m_end); + const charT* pc = m_position; + std::intmax_t i = this->m_traits.toi(pc, pc + 1, 10); + if((i == 0) || (((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) && (this->flags() & regbase::no_bk_refs))) + { + // not a backref at all but an octal escape sequence: + charT c = unescape_character(); + this->append_literal(c); + } + else if((i > 0)) + { + m_position = pc; + re_brace* pb = static_cast(this->append_state(syntax_element_backref, sizeof(re_brace))); + pb->index = (int)i; + pb->icase = this->flags() & regbase::icase; + if(i > m_max_backref) + m_max_backref = i; + } + else + { + // Rewind to start of escape: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_backref, m_position - m_base); + return false; + } + return true; +} + +template +bool basic_regex_parser::parse_QE() +{ +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + // + // parse a \Q...\E sequence: + // + ++m_position; // skip the Q + const charT* start = m_position; + const charT* end; + do + { + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape)) + ++m_position; + if(m_position == m_end) + { + // a \Q...\E sequence may terminate with the end of the expression: + end = m_position; + break; + } + if(++m_position == m_end) // skip the escape + { + fail(regex_constants::error_escape, m_position - m_base, "Unterminated \\Q...\\E sequence."); + return false; + } + // check to see if it's a \E: + if(this->m_traits.escape_syntax_type(*m_position) == regex_constants::escape_type_E) + { + ++m_position; + end = m_position - 2; + break; + } + // otherwise go round again: + }while(true); + // + // now add all the character between the two escapes as literals: + // + while(start != end) + { + this->append_literal(*start); + ++start; + } + return true; +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif +} + +template +bool basic_regex_parser::parse_perl_extension() +{ + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + // + // treat comments as a special case, as these + // are the only ones that don't start with a leading + // startmark state: + // + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_hash) + { + while((m_position != m_end) + && (this->m_traits.syntax_type(*m_position++) != regex_constants::syntax_close_mark)) + {} + return true; + } + // + // backup some state, and prepare the way: + // + int markid = 0; + std::ptrdiff_t jump_offset = 0; + re_brace* pb = static_cast(this->append_state(syntax_element_startmark, sizeof(re_brace))); + pb->icase = this->flags() & regbase::icase; + std::ptrdiff_t last_paren_start = this->getoffset(pb); + // back up insertion point for alternations, and set new point: + std::ptrdiff_t last_alt_point = m_alt_insert_point; + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + std::ptrdiff_t expected_alt_point = m_alt_insert_point; + bool restore_flags = true; + regex_constants::syntax_option_type old_flags = this->flags(); + bool old_case_change = m_has_case_change; + m_has_case_change = false; + charT name_delim; + int mark_reset = m_mark_reset; + int max_mark = m_max_mark; + m_mark_reset = -1; + m_max_mark = m_mark_count; + std::intmax_t v; + // + // select the actual extension used: + // + switch(this->m_traits.syntax_type(*m_position)) + { + case regex_constants::syntax_or: + m_mark_reset = m_mark_count; + BOOST_REGEX_FALLTHROUGH; + case regex_constants::syntax_colon: + // + // a non-capturing mark: + // + pb->index = markid = 0; + ++m_position; + break; + case regex_constants::syntax_digit: + { + // + // a recursive subexpression: + // + v = this->m_traits.toi(m_position, m_end, 10); + if((v < 0) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base, "The recursive sub-expression refers to an invalid marking group, or is unterminated."); + return false; + } +insert_recursion: + pb->index = markid = 0; + re_recurse* pr = static_cast(this->append_state(syntax_element_recurse, sizeof(re_recurse))); + pr->alt.i = (std::ptrdiff_t)v; + pr->state_id = 0; + static_cast( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = this->flags() & regbase::icase; + break; + } + case regex_constants::syntax_plus: + // + // A forward-relative recursive subexpression: + // + ++m_position; + v = this->m_traits.toi(m_position, m_end, 10); + if((v <= 0) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base, "An invalid or unterminated recursive sub-expression."); + return false; + } + if ((std::numeric_limits::max)() - m_mark_count < v) + { + fail(regex_constants::error_perl_extension, m_position - m_base, "An invalid or unterminated recursive sub-expression."); + return false; + } + v += m_mark_count; + goto insert_recursion; + case regex_constants::syntax_dash: + // + // Possibly a backward-relative recursive subexpression: + // + ++m_position; + v = this->m_traits.toi(m_position, m_end, 10); + if(v <= 0) + { + --m_position; + // Oops not a relative recursion at all, but a (?-imsx) group: + goto option_group_jump; + } + v = static_cast(m_mark_count) + 1 - v; + if(v <= 0) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base, "An invalid or unterminated recursive sub-expression."); + return false; + } + goto insert_recursion; + case regex_constants::syntax_equal: + pb->index = markid = -1; + ++m_position; + jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump))); + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + break; + case regex_constants::syntax_not: + pb->index = markid = -2; + ++m_position; + jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump))); + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + break; + case regex_constants::escape_type_left_word: + { + // a lookbehind assertion: + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + regex_constants::syntax_type t = this->m_traits.syntax_type(*m_position); + if(t == regex_constants::syntax_not) + pb->index = markid = -2; + else if(t == regex_constants::syntax_equal) + pb->index = markid = -1; + else + { + // Probably a named capture which also starts (?< : + name_delim = '>'; + --m_position; + goto named_capture_jump; + } + ++m_position; + jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump))); + this->append_state(syntax_element_backstep, sizeof(re_brace)); + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + break; + } + case regex_constants::escape_type_right_word: + // + // an independent sub-expression: + // + pb->index = markid = -3; + ++m_position; + jump_offset = this->getoffset(this->append_state(syntax_element_jump, sizeof(re_jump))); + this->m_pdata->m_data.align(); + m_alt_insert_point = this->m_pdata->m_data.size(); + break; + case regex_constants::syntax_open_mark: + { + // a conditional expression: + pb->index = markid = -4; + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + v = this->m_traits.toi(m_position, m_end, 10); + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(*m_position == charT('R')) + { + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(*m_position == charT('&')) + { + const charT* base = ++m_position; + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + v = -static_cast(hash_value_from_capture_name(base, m_position)); + } + else + { + v = -this->m_traits.toi(m_position, m_end, 10); + } + re_brace* br = static_cast(this->append_state(syntax_element_assert_backref, sizeof(re_brace))); + br->index = v < 0 ? (int)(v - 1) : 0; + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + } + else if((*m_position == charT('\'')) || (*m_position == charT('<'))) + { + const charT* base = ++m_position; + while((m_position != m_end) && (*m_position != charT('>')) && (*m_position != charT('\''))) + ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + v = static_cast(hash_value_from_capture_name(base, m_position)); + re_brace* br = static_cast(this->append_state(syntax_element_assert_backref, sizeof(re_brace))); + br->index = (int)v; + if(((*m_position != charT('>')) && (*m_position != charT('\''))) || (++m_position == m_end)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base, "Unterminated named capture."); + return false; + } + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + } + else if(*m_position == charT('D')) + { + const char* def = "DEFINE"; + while(*def && (m_position != m_end) && (*m_position == charT(*def))) + ++m_position, ++def; + if((m_position == m_end) || *def) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + re_brace* br = static_cast(this->append_state(syntax_element_assert_backref, sizeof(re_brace))); + br->index = 9999; // special magic value! + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + } + else if(v > 0) + { + re_brace* br = static_cast(this->append_state(syntax_element_assert_backref, sizeof(re_brace))); + br->index = (int)v; + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + } + else + { + // verify that we have a lookahead or lookbehind assert: + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_question) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(this->m_traits.syntax_type(*m_position) == regex_constants::escape_type_left_word) + { + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + m_position -= 3; + } + else + { + if((this->m_traits.syntax_type(*m_position) != regex_constants::syntax_equal) + && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_not)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + m_position -= 2; + } + } + break; + } + case regex_constants::syntax_close_mark: + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + case regex_constants::escape_type_end_buffer: + { + name_delim = *m_position; +named_capture_jump: + markid = 0; + if(0 == (this->flags() & regbase::nosubs)) + { + markid = ++m_mark_count; + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.push_back(std::pair(std::distance(m_base, m_position) - 2, 0)); + } + pb->index = markid; + const charT* base = ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + while((m_position != m_end) && (*m_position != name_delim)) + ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + this->m_pdata->set_name(base, m_position, markid); + ++m_position; + break; + } + default: + if(*m_position == charT('R')) + { + ++m_position; + v = 0; + if(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + goto insert_recursion; + } + if(*m_position == charT('&')) + { + ++m_position; + const charT* base = m_position; + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + v = static_cast(hash_value_from_capture_name(base, m_position)); + goto insert_recursion; + } + if(*m_position == charT('P')) + { + ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(*m_position == charT('>')) + { + ++m_position; + const charT* base = m_position; + while((m_position != m_end) && (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + ++m_position; + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + v = static_cast(hash_value_from_capture_name(base, m_position)); + goto insert_recursion; + } + } + // + // lets assume that we have a (?imsx) group and try and parse it: + // +option_group_jump: + regex_constants::syntax_option_type opts = parse_options(); + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + // make a note of whether we have a case change: + m_has_case_change = ((opts & regbase::icase) != (this->flags() & regbase::icase)); + pb->index = markid = 0; + if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark) + { + // update flags and carry on as normal: + this->flags(opts); + restore_flags = false; + old_case_change |= m_has_case_change; // defer end of scope by one ')' + } + else if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_colon) + { + // update flags and carry on until the matching ')' is found: + this->flags(opts); + ++m_position; + } + else + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + + // finally append a case change state if we need it: + if(m_has_case_change) + { + static_cast( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = opts & regbase::icase; + } + + } + // + // now recursively add more states, this will terminate when we get to a + // matching ')' : + // + parse_all(); + // + // Unwind alternatives: + // + if(0 == unwind_alts(last_paren_start)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base, "Invalid alternation operators within (?...) block."); + return false; + } + // + // we either have a ')' or we have run out of characters prematurely: + // + if(m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + this->fail(regex_constants::error_paren, std::distance(m_base, m_end)); + return false; + } + BOOST_REGEX_ASSERT(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark); + ++m_position; + // + // restore the flags: + // + if(restore_flags) + { + // append a case change state if we need it: + if(m_has_case_change) + { + static_cast( + this->append_state(syntax_element_toggle_case, sizeof(re_case)) + )->icase = old_flags & regbase::icase; + } + this->flags(old_flags); + } + // + // set up the jump pointer if we have one: + // + if(jump_offset) + { + this->m_pdata->m_data.align(); + re_jump* jmp = static_cast(this->getaddress(jump_offset)); + jmp->alt.i = this->m_pdata->m_data.size() - this->getoffset(jmp); + if((this->m_last_state == jmp) && (markid != -2)) + { + // Oops... we didn't have anything inside the assertion. + // Note we don't get here for negated forward lookahead as (?!) + // does have some uses. + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base, "Invalid or empty zero width assertion."); + return false; + } + } + // + // verify that if this is conditional expression, that we do have + // an alternative, if not add one: + // + if(markid == -4) + { + re_syntax_base* b = this->getaddress(expected_alt_point); + // Make sure we have exactly one alternative following this state: + if(b->type != syntax_element_alt) + { + re_alt* alt = static_cast(this->insert_state(expected_alt_point, syntax_element_alt, sizeof(re_alt))); + alt->alt.i = this->m_pdata->m_data.size() - this->getoffset(alt); + } + else if(((std::ptrdiff_t)this->m_pdata->m_data.size() > (static_cast(b)->alt.i + this->getoffset(b))) && (static_cast(b)->alt.i > 0) && this->getaddress(static_cast(b)->alt.i, b)->type == syntax_element_alt) + { + // Can't have seen more than one alternative: + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_bad_pattern, m_position - m_base, "More than one alternation operator | was encountered inside a conditional expression."); + return false; + } + else + { + // We must *not* have seen an alternative inside a (DEFINE) block: + b = this->getaddress(b->next.i, b); + if((b->type == syntax_element_assert_backref) && (static_cast(b)->index == 9999)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_bad_pattern, m_position - m_base, "Alternation operators are not allowed inside a DEFINE block."); + return false; + } + } + // check for invalid repetition of next state: + b = this->getaddress(expected_alt_point); + b = this->getaddress(static_cast(b)->next.i, b); + if((b->type != syntax_element_assert_backref) + && (b->type != syntax_element_startmark)) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_badrepeat, m_position - m_base, "A repetition operator cannot be applied to a zero-width assertion."); + return false; + } + } + // + // append closing parenthesis state: + // + pb = static_cast(this->append_state(syntax_element_endmark, sizeof(re_brace))); + pb->index = markid; + pb->icase = this->flags() & regbase::icase; + this->m_paren_start = last_paren_start; + // + // restore the alternate insertion point: + // + this->m_alt_insert_point = last_alt_point; + // + // and the case change data: + // + m_has_case_change = old_case_change; + // + // And the mark_reset data: + // + if(m_max_mark > m_mark_count) + { + m_mark_count = m_max_mark; + } + m_mark_reset = mark_reset; + m_max_mark = max_mark; + + + if(markid > 0) + { + if(this->flags() & regbase::save_subexpression_location) + this->m_pdata->m_subs.at((std::size_t)markid - 1).second = std::distance(m_base, m_position) - 1; + } + return true; +} + +template +bool basic_regex_parser::match_verb(const char* verb) +{ + while(*verb) + { + if(static_cast(*verb) != *m_position) + { + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(++m_position == m_end) + { + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++verb; + } + return true; +} + +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +#if BOOST_REGEX_MSVC >= 1800 +#pragma warning(disable:26812) +#endif +#endif +template +bool basic_regex_parser::parse_perl_verb() +{ + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + switch(*m_position) + { + case 'F': + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if((this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark) || match_verb("AIL")) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++m_position; + this->append_state(syntax_element_fail); + return true; + } + break; + case 'A': + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(match_verb("CCEPT")) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++m_position; + this->append_state(syntax_element_accept); + return true; + } + break; + case 'C': + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(match_verb("OMMIT")) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++m_position; + static_cast(this->append_state(syntax_element_commit, sizeof(re_commit)))->action = commit_commit; + this->m_pdata->m_disable_match_any = true; + return true; + } + break; + case 'P': + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(match_verb("RUNE")) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++m_position; + static_cast(this->append_state(syntax_element_commit, sizeof(re_commit)))->action = commit_prune; + this->m_pdata->m_disable_match_any = true; + return true; + } + break; + case 'S': + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(match_verb("KIP")) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++m_position; + static_cast(this->append_state(syntax_element_commit, sizeof(re_commit)))->action = commit_skip; + this->m_pdata->m_disable_match_any = true; + return true; + } + break; + case 'T': + if(++m_position == m_end) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + if(match_verb("HEN")) + { + if((m_position == m_end) || (this->m_traits.syntax_type(*m_position) != regex_constants::syntax_close_mark)) + { + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; + } + ++m_position; + this->append_state(syntax_element_then); + this->m_pdata->m_disable_match_any = true; + return true; + } + break; + } + // Rewind to start of (* sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_perl_extension, m_position - m_base); + return false; +} +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif + +template +bool basic_regex_parser::add_emacs_code(bool negate) +{ + // + // parses an emacs style \sx or \Sx construct. + // + if(++m_position == m_end) + { + // Rewind to start of sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_escape) --m_position; + fail(regex_constants::error_escape, m_position - m_base); + return false; + } + basic_char_set char_set; + if(negate) + char_set.negate(); + + static const charT s_punct[5] = { 'p', 'u', 'n', 'c', 't', }; + + switch(*m_position) + { + case 's': + case ' ': + char_set.add_class(this->m_mask_space); + break; + case 'w': + char_set.add_class(this->m_word_mask); + break; + case '_': + char_set.add_single(digraph(charT('$'))); + char_set.add_single(digraph(charT('&'))); + char_set.add_single(digraph(charT('*'))); + char_set.add_single(digraph(charT('+'))); + char_set.add_single(digraph(charT('-'))); + char_set.add_single(digraph(charT('_'))); + char_set.add_single(digraph(charT('<'))); + char_set.add_single(digraph(charT('>'))); + break; + case '.': + char_set.add_class(this->m_traits.lookup_classname(s_punct, s_punct+5)); + break; + case '(': + char_set.add_single(digraph(charT('('))); + char_set.add_single(digraph(charT('['))); + char_set.add_single(digraph(charT('{'))); + break; + case ')': + char_set.add_single(digraph(charT(')'))); + char_set.add_single(digraph(charT(']'))); + char_set.add_single(digraph(charT('}'))); + break; + case '"': + char_set.add_single(digraph(charT('"'))); + char_set.add_single(digraph(charT('\''))); + char_set.add_single(digraph(charT('`'))); + break; + case '\'': + char_set.add_single(digraph(charT('\''))); + char_set.add_single(digraph(charT(','))); + char_set.add_single(digraph(charT('#'))); + break; + case '<': + char_set.add_single(digraph(charT(';'))); + break; + case '>': + char_set.add_single(digraph(charT('\n'))); + char_set.add_single(digraph(charT('\f'))); + break; + default: + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + if(0 == this->append_set(char_set)) + { + fail(regex_constants::error_ctype, m_position - m_base); + return false; + } + ++m_position; + return true; +} + +template +regex_constants::syntax_option_type basic_regex_parser::parse_options() +{ + // we have a (?imsx-imsx) group, convert it into a set of flags: + regex_constants::syntax_option_type f = this->flags(); + bool breakout = false; + do + { + switch(*m_position) + { + case 's': + f |= regex_constants::mod_s; + f &= ~regex_constants::no_mod_s; + break; + case 'm': + f &= ~regex_constants::no_mod_m; + break; + case 'i': + f |= regex_constants::icase; + break; + case 'x': + f |= regex_constants::mod_x; + break; + default: + breakout = true; + continue; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + } + while(!breakout); + + breakout = false; + + if(*m_position == static_cast('-')) + { + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + do + { + switch(*m_position) + { + case 's': + f &= ~regex_constants::mod_s; + f |= regex_constants::no_mod_s; + break; + case 'm': + f |= regex_constants::no_mod_m; + break; + case 'i': + f &= ~regex_constants::icase; + break; + case 'x': + f &= ~regex_constants::mod_x; + break; + default: + breakout = true; + continue; + } + if(++m_position == m_end) + { + // Rewind to start of (? sequence: + --m_position; + while(this->m_traits.syntax_type(*m_position) != regex_constants::syntax_open_mark) --m_position; + fail(regex_constants::error_paren, m_position - m_base); + return false; + } + } + while(!breakout); + } + return f; +} + +template +bool basic_regex_parser::unwind_alts(std::ptrdiff_t last_paren_start) +{ + // + // If we didn't actually add any states after the last + // alternative then that's an error: + // + if((this->m_alt_insert_point == static_cast(this->m_pdata->m_data.size())) + && (!m_alt_jumps.empty()) && (m_alt_jumps.back() > last_paren_start) + && + !( + ((this->flags() & regbase::main_option_type) == regbase::perl_syntax_group) + && + ((this->flags() & regbase::no_empty_expressions) == 0) + ) + ) + { + fail(regex_constants::error_empty, this->m_position - this->m_base, "Can't terminate a sub-expression with an alternation operator |."); + return false; + } + // + // Fix up our alternatives: + // + while((!m_alt_jumps.empty()) && (m_alt_jumps.back() > last_paren_start)) + { + // + // fix up the jump to point to the end of the states + // that we've just added: + // + std::ptrdiff_t jump_offset = m_alt_jumps.back(); + m_alt_jumps.pop_back(); + this->m_pdata->m_data.align(); + re_jump* jmp = static_cast(this->getaddress(jump_offset)); + if (jmp->type != syntax_element_jump) + { + // Something really bad happened, this used to be an assert, + // but we'll make it an error just in case we should ever get here. + fail(regex_constants::error_unknown, this->m_position - this->m_base, "Internal logic failed while compiling the expression, probably you added a repeat to something non-repeatable!"); + return false; + } + jmp->alt.i = this->m_pdata->m_data.size() - jump_offset; + } + return true; +} + +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif + +} // namespace BOOST_REGEX_DETAIL_NS +} // namespace boost + +#endif diff --git a/boost/regex/v5/c_regex_traits.hpp b/boost/regex/v5/c_regex_traits.hpp new file mode 100644 index 00000000..9de34632 --- /dev/null +++ b/boost/regex/v5/c_regex_traits.hpp @@ -0,0 +1,474 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE c_regex_traits.hpp + * VERSION see + * DESCRIPTION: Declares regular expression traits class that wraps the global C locale. + */ + +#ifndef BOOST_C_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_C_REGEX_TRAITS_HPP_INCLUDED + +#include +#include +#include + +namespace boost{ + + namespace BOOST_REGEX_DETAIL_NS { + + enum + { + char_class_space = 1 << 0, + char_class_print = 1 << 1, + char_class_cntrl = 1 << 2, + char_class_upper = 1 << 3, + char_class_lower = 1 << 4, + char_class_alpha = 1 << 5, + char_class_digit = 1 << 6, + char_class_punct = 1 << 7, + char_class_xdigit = 1 << 8, + char_class_alnum = char_class_alpha | char_class_digit, + char_class_graph = char_class_alnum | char_class_punct, + char_class_blank = 1 << 9, + char_class_word = 1 << 10, + char_class_unicode = 1 << 11, + char_class_horizontal = 1 << 12, + char_class_vertical = 1 << 13 + }; + + } + +template +struct c_regex_traits; + +template<> +struct c_regex_traits +{ + c_regex_traits(){} + typedef char char_type; + typedef std::size_t size_type; + typedef std::string string_type; + struct locale_type{}; + typedef std::uint32_t char_class_type; + + static size_type length(const char_type* p) + { + return (std::strlen)(p); + } + + char translate(char c) const + { + return c; + } + char translate_nocase(char c) const + { + return static_cast((std::tolower)(static_cast(c))); + } + + static string_type transform(const char* p1, const char* p2); + static string_type transform_primary(const char* p1, const char* p2); + + static char_class_type lookup_classname(const char* p1, const char* p2); + static string_type lookup_collatename(const char* p1, const char* p2); + + static bool isctype(char, char_class_type); + static int value(char, int); + + locale_type imbue(locale_type l) + { return l; } + locale_type getloc()const + { return locale_type(); } + +private: + // this type is not copyable: + c_regex_traits(const c_regex_traits&); + c_regex_traits& operator=(const c_regex_traits&); +}; + +#ifndef BOOST_NO_WREGEX +template<> +struct c_regex_traits +{ + c_regex_traits(){} + typedef wchar_t char_type; + typedef std::size_t size_type; + typedef std::wstring string_type; + struct locale_type{}; + typedef std::uint32_t char_class_type; + + static size_type length(const char_type* p) + { + return (std::wcslen)(p); + } + + wchar_t translate(wchar_t c) const + { + return c; + } + wchar_t translate_nocase(wchar_t c) const + { + return (std::towlower)(c); + } + + static string_type transform(const wchar_t* p1, const wchar_t* p2); + static string_type transform_primary(const wchar_t* p1, const wchar_t* p2); + + static char_class_type lookup_classname(const wchar_t* p1, const wchar_t* p2); + static string_type lookup_collatename(const wchar_t* p1, const wchar_t* p2); + + static bool isctype(wchar_t, char_class_type); + static int value(wchar_t, int); + + locale_type imbue(locale_type l) + { return l; } + locale_type getloc()const + { return locale_type(); } + +private: + // this type is not copyable: + c_regex_traits(const c_regex_traits&); + c_regex_traits& operator=(const c_regex_traits&); +}; + +#endif // BOOST_NO_WREGEX + +inline c_regex_traits::string_type c_regex_traits::transform(const char* p1, const char* p2) +{ + std::string result(10, ' '); + std::size_t s = result.size(); + std::size_t r; + std::string src(p1, p2); + while (s < (r = std::strxfrm(&*result.begin(), src.c_str(), s))) + { +#if defined(_CPPLIB_VER) + // + // A bug in VC11 and 12 causes the program to hang if we pass a null-string + // to std::strxfrm, but only for certain locales :-( + // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware). + // + if (r == INT_MAX) + { + result.erase(); + result.insert(result.begin(), static_cast(0)); + return result; + } +#endif + result.append(r - s + 3, ' '); + s = result.size(); + } + result.erase(r); + return result; +} + +inline c_regex_traits::string_type c_regex_traits::transform_primary(const char* p1, const char* p2) +{ + static char s_delim; + static const int s_collate_type = ::boost::BOOST_REGEX_DETAIL_NS::find_sort_syntax(static_cast*>(0), &s_delim); + std::string result; + // + // What we do here depends upon the format of the sort key returned by + // sort key returned by this->transform: + // + switch (s_collate_type) + { + case ::boost::BOOST_REGEX_DETAIL_NS::sort_C: + case ::boost::BOOST_REGEX_DETAIL_NS::sort_unknown: + // the best we can do is translate to lower case, then get a regular sort key: + { + result.assign(p1, p2); + for (std::string::size_type i = 0; i < result.size(); ++i) + result[i] = static_cast((std::tolower)(static_cast(result[i]))); + result = transform(&*result.begin(), &*result.begin() + result.size()); + break; + } + case ::boost::BOOST_REGEX_DETAIL_NS::sort_fixed: + { + // get a regular sort key, and then truncate it: + result = transform(p1, p2); + result.erase(s_delim); + break; + } + case ::boost::BOOST_REGEX_DETAIL_NS::sort_delim: + // get a regular sort key, and then truncate everything after the delim: + result = transform(p1, p2); + if ((!result.empty()) && (result[0] == s_delim)) + break; + std::size_t i; + for (i = 0; i < result.size(); ++i) + { + if (result[i] == s_delim) + break; + } + result.erase(i); + break; + } + if (result.empty()) + result = std::string(1, char(0)); + return result; +} + +inline c_regex_traits::char_class_type c_regex_traits::lookup_classname(const char* p1, const char* p2) +{ + using namespace BOOST_REGEX_DETAIL_NS; + static const char_class_type masks[] = + { + 0, + char_class_alnum, + char_class_alpha, + char_class_blank, + char_class_cntrl, + char_class_digit, + char_class_digit, + char_class_graph, + char_class_horizontal, + char_class_lower, + char_class_lower, + char_class_print, + char_class_punct, + char_class_space, + char_class_space, + char_class_upper, + char_class_unicode, + char_class_upper, + char_class_vertical, + char_class_alnum | char_class_word, + char_class_alnum | char_class_word, + char_class_xdigit, + }; + + int idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2); + if (idx < 0) + { + std::string s(p1, p2); + for (std::string::size_type i = 0; i < s.size(); ++i) + s[i] = static_cast((std::tolower)(static_cast(s[i]))); + idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(&*s.begin(), &*s.begin() + s.size()); + } + BOOST_REGEX_ASSERT(std::size_t(idx) + 1u < sizeof(masks) / sizeof(masks[0])); + return masks[idx + 1]; +} + +inline bool c_regex_traits::isctype(char c, char_class_type mask) +{ + using namespace BOOST_REGEX_DETAIL_NS; + return + ((mask & char_class_space) && (std::isspace)(static_cast(c))) + || ((mask & char_class_print) && (std::isprint)(static_cast(c))) + || ((mask & char_class_cntrl) && (std::iscntrl)(static_cast(c))) + || ((mask & char_class_upper) && (std::isupper)(static_cast(c))) + || ((mask & char_class_lower) && (std::islower)(static_cast(c))) + || ((mask & char_class_alpha) && (std::isalpha)(static_cast(c))) + || ((mask & char_class_digit) && (std::isdigit)(static_cast(c))) + || ((mask & char_class_punct) && (std::ispunct)(static_cast(c))) + || ((mask & char_class_xdigit) && (std::isxdigit)(static_cast(c))) + || ((mask & char_class_blank) && (std::isspace)(static_cast(c)) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c)) + || ((mask & char_class_word) && (c == '_')) + || ((mask & char_class_vertical) && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v'))) + || ((mask & char_class_horizontal) && (std::isspace)(static_cast(c)) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) && (c != '\v')); +} + +inline c_regex_traits::string_type c_regex_traits::lookup_collatename(const char* p1, const char* p2) +{ + std::string s(p1, p2); + s = ::boost::BOOST_REGEX_DETAIL_NS::lookup_default_collate_name(s); + if (s.empty() && (p2 - p1 == 1)) + s.append(1, *p1); + return s; +} + +inline int c_regex_traits::value(char c, int radix) +{ + char b[2] = { c, '\0', }; + char* ep; + int result = std::strtol(b, &ep, radix); + if (ep == b) + return -1; + return result; +} + +#ifndef BOOST_NO_WREGEX + +inline c_regex_traits::string_type c_regex_traits::transform(const wchar_t* p1, const wchar_t* p2) +{ + std::size_t r; + std::size_t s = 10; + std::wstring src(p1, p2); + std::wstring result(s, L' '); + while (s < (r = std::wcsxfrm(&*result.begin(), src.c_str(), s))) + { +#if defined(_CPPLIB_VER) + // + // A bug in VC11 and 12 causes the program to hang if we pass a null-string + // to std::strxfrm, but only for certain locales :-( + // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware). + // + if (r == INT_MAX) + { + result.erase(); + result.insert(result.begin(), static_cast(0)); + return result; + } +#endif + result.append(r - s + 3, L' '); + s = result.size(); + } + result.erase(r); + return result; +} + +inline c_regex_traits::string_type c_regex_traits::transform_primary(const wchar_t* p1, const wchar_t* p2) +{ + static wchar_t s_delim; + static const int s_collate_type = ::boost::BOOST_REGEX_DETAIL_NS::find_sort_syntax(static_cast*>(0), &s_delim); + std::wstring result; + // + // What we do here depends upon the format of the sort key returned by + // sort key returned by this->transform: + // + switch (s_collate_type) + { + case ::boost::BOOST_REGEX_DETAIL_NS::sort_C: + case ::boost::BOOST_REGEX_DETAIL_NS::sort_unknown: + // the best we can do is translate to lower case, then get a regular sort key: + { + result.assign(p1, p2); + for (std::wstring::size_type i = 0; i < result.size(); ++i) + result[i] = (std::towlower)(result[i]); + result = c_regex_traits::transform(&*result.begin(), &*result.begin() + result.size()); + break; + } + case ::boost::BOOST_REGEX_DETAIL_NS::sort_fixed: + { + // get a regular sort key, and then truncate it: + result = c_regex_traits::transform(&*result.begin(), &*result.begin() + result.size()); + result.erase(s_delim); + break; + } + case ::boost::BOOST_REGEX_DETAIL_NS::sort_delim: + // get a regular sort key, and then truncate everything after the delim: + result = c_regex_traits::transform(&*result.begin(), &*result.begin() + result.size()); + if ((!result.empty()) && (result[0] == s_delim)) + break; + std::size_t i; + for (i = 0; i < result.size(); ++i) + { + if (result[i] == s_delim) + break; + } + result.erase(i); + break; + } + if (result.empty()) + result = std::wstring(1, char(0)); + return result; +} + +inline c_regex_traits::char_class_type c_regex_traits::lookup_classname(const wchar_t* p1, const wchar_t* p2) +{ + using namespace BOOST_REGEX_DETAIL_NS; + static const char_class_type masks[] = + { + 0, + char_class_alnum, + char_class_alpha, + char_class_blank, + char_class_cntrl, + char_class_digit, + char_class_digit, + char_class_graph, + char_class_horizontal, + char_class_lower, + char_class_lower, + char_class_print, + char_class_punct, + char_class_space, + char_class_space, + char_class_upper, + char_class_unicode, + char_class_upper, + char_class_vertical, + char_class_alnum | char_class_word, + char_class_alnum | char_class_word, + char_class_xdigit, + }; + + int idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2); + if (idx < 0) + { + std::wstring s(p1, p2); + for (std::wstring::size_type i = 0; i < s.size(); ++i) + s[i] = (std::towlower)(s[i]); + idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(&*s.begin(), &*s.begin() + s.size()); + } + BOOST_REGEX_ASSERT(idx + 1 < static_cast(sizeof(masks) / sizeof(masks[0]))); + return masks[idx + 1]; +} + +inline bool c_regex_traits::isctype(wchar_t c, char_class_type mask) +{ + using namespace BOOST_REGEX_DETAIL_NS; + return + ((mask & char_class_space) && (std::iswspace)(c)) + || ((mask & char_class_print) && (std::iswprint)(c)) + || ((mask & char_class_cntrl) && (std::iswcntrl)(c)) + || ((mask & char_class_upper) && (std::iswupper)(c)) + || ((mask & char_class_lower) && (std::iswlower)(c)) + || ((mask & char_class_alpha) && (std::iswalpha)(c)) + || ((mask & char_class_digit) && (std::iswdigit)(c)) + || ((mask & char_class_punct) && (std::iswpunct)(c)) + || ((mask & char_class_xdigit) && (std::iswxdigit)(c)) + || ((mask & char_class_blank) && (std::iswspace)(c) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c)) + || ((mask & char_class_word) && (c == '_')) + || ((mask & char_class_unicode) && (c & ~static_cast(0xff))) + || ((mask & char_class_vertical) && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == L'\v'))) + || ((mask & char_class_horizontal) && (std::iswspace)(c) && !::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) && (c != L'\v')); +} + +inline c_regex_traits::string_type c_regex_traits::lookup_collatename(const wchar_t* p1, const wchar_t* p2) +{ + std::string name; + // Usual msvc warning suppression does not work here with std::string template constructor.... use a workaround instead: + for (const wchar_t* pos = p1; pos != p2; ++pos) + name.push_back((char)*pos); + name = ::boost::BOOST_REGEX_DETAIL_NS::lookup_default_collate_name(name); + if (!name.empty()) + return string_type(name.begin(), name.end()); + if (p2 - p1 == 1) + return string_type(1, *p1); + return string_type(); +} + +inline int c_regex_traits::value(wchar_t c, int radix) +{ +#ifdef BOOST_BORLANDC + // workaround for broken wcstol: + if ((std::iswxdigit)(c) == 0) + return -1; +#endif + wchar_t b[2] = { c, '\0', }; + wchar_t* ep; + int result = std::wcstol(b, &ep, radix); + if (ep == b) + return -1; + return result; +} + +#endif + +} + +#endif + + + diff --git a/boost/regex/v5/char_regex_traits.hpp b/boost/regex/v5/char_regex_traits.hpp new file mode 100644 index 00000000..aeed86f8 --- /dev/null +++ b/boost/regex/v5/char_regex_traits.hpp @@ -0,0 +1,59 @@ +/* + * + * Copyright (c) 2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE char_regex_traits.cpp + * VERSION see + * DESCRIPTION: Declares deprecated traits classes char_regex_traits<>. + */ + + +#ifndef BOOST_REGEX_V5_CHAR_REGEX_TRAITS_HPP +#define BOOST_REGEX_V5_CHAR_REGEX_TRAITS_HPP + +namespace boost{ + +namespace deprecated{ +// +// class char_regex_traits_i +// provides case insensitive traits classes (deprecated): +template +class char_regex_traits_i : public regex_traits {}; + +template<> +class char_regex_traits_i : public regex_traits +{ +public: + typedef char char_type; + typedef unsigned char uchar_type; + typedef unsigned int size_type; + typedef regex_traits base_type; + +}; + +#ifndef BOOST_NO_WREGEX +template<> +class char_regex_traits_i : public regex_traits +{ +public: + typedef wchar_t char_type; + typedef unsigned short uchar_type; + typedef unsigned int size_type; + typedef regex_traits base_type; + +}; +#endif +} // namespace deprecated +} // namespace boost + +#endif // include + diff --git a/boost/regex/v5/cpp_regex_traits.hpp b/boost/regex/v5/cpp_regex_traits.hpp new file mode 100644 index 00000000..26b6f503 --- /dev/null +++ b/boost/regex/v5/cpp_regex_traits.hpp @@ -0,0 +1,1040 @@ +/* + * + * Copyright (c) 2004 John Maddock + * Copyright 2011 Garmin Ltd. or its subsidiaries + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE cpp_regex_traits.hpp + * VERSION see + * DESCRIPTION: Declares regular expression traits class cpp_regex_traits. + */ + +#ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED + +#include +#include +#include +#include + +#include +#include + +#ifdef BOOST_HAS_THREADS +#include +#endif +#include +#include + +#include +#include +#include + +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4786 4251) +#endif + +namespace boost{ + +// +// forward declaration is needed by some compilers: +// +template +class cpp_regex_traits; + +namespace BOOST_REGEX_DETAIL_NS{ + +// +// class parser_buf: +// acts as a stream buffer which wraps around a pair of pointers: +// +template > +class parser_buf : public ::std::basic_streambuf +{ + typedef ::std::basic_streambuf base_type; + typedef typename base_type::int_type int_type; + typedef typename base_type::char_type char_type; + typedef typename base_type::pos_type pos_type; + typedef ::std::streamsize streamsize; + typedef typename base_type::off_type off_type; +public: + parser_buf() : base_type() { setbuf(0, 0); } + const charT* getnext() { return this->gptr(); } +protected: + std::basic_streambuf* setbuf(char_type* s, streamsize n) override; + typename parser_buf::pos_type seekpos(pos_type sp, ::std::ios_base::openmode which) override; + typename parser_buf::pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) override; +private: + parser_buf& operator=(const parser_buf&); + parser_buf(const parser_buf&); +}; + +template +std::basic_streambuf* +parser_buf::setbuf(char_type* s, streamsize n) +{ + this->setg(s, s, s + n); + return this; +} + +template +typename parser_buf::pos_type +parser_buf::seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) +{ + if(which & ::std::ios_base::out) + return pos_type(off_type(-1)); + std::ptrdiff_t size = this->egptr() - this->eback(); + std::ptrdiff_t pos = this->gptr() - this->eback(); + charT* g = this->eback(); + switch(static_cast(way)) + { + case ::std::ios_base::beg: + if((off < 0) || (off > size)) + return pos_type(off_type(-1)); + else + this->setg(g, g + off, g + size); + break; + case ::std::ios_base::end: + if((off < 0) || (off > size)) + return pos_type(off_type(-1)); + else + this->setg(g, g + size - off, g + size); + break; + case ::std::ios_base::cur: + { + std::ptrdiff_t newpos = static_cast(pos + off); + if((newpos < 0) || (newpos > size)) + return pos_type(off_type(-1)); + else + this->setg(g, g + newpos, g + size); + break; + } + default: ; + } +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4244) +#endif + return static_cast(this->gptr() - this->eback()); +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif +} + +template +typename parser_buf::pos_type +parser_buf::seekpos(pos_type sp, ::std::ios_base::openmode which) +{ + if(which & ::std::ios_base::out) + return pos_type(off_type(-1)); + off_type size = static_cast(this->egptr() - this->eback()); + charT* g = this->eback(); + if(off_type(sp) <= size) + { + this->setg(g, g + off_type(sp), g + size); + } + return pos_type(off_type(-1)); +} + +// +// class cpp_regex_traits_base: +// acts as a container for locale and the facets we are using. +// +template +struct cpp_regex_traits_base +{ + cpp_regex_traits_base(const std::locale& l) + { (void)imbue(l); } + std::locale imbue(const std::locale& l); + + std::locale m_locale; + std::ctype const* m_pctype; + std::messages const* m_pmessages; + std::collate const* m_pcollate; + + bool operator<(const cpp_regex_traits_base& b)const + { + if(m_pctype == b.m_pctype) + { + if(m_pmessages == b.m_pmessages) + { + return m_pcollate < b.m_pcollate; + } + return m_pmessages < b.m_pmessages; + } + return m_pctype < b.m_pctype; + } + bool operator==(const cpp_regex_traits_base& b)const + { + return (m_pctype == b.m_pctype) + && (m_pmessages == b.m_pmessages) + && (m_pcollate == b.m_pcollate); + } +}; + +template +std::locale cpp_regex_traits_base::imbue(const std::locale& l) +{ + std::locale result(m_locale); + m_locale = l; + m_pctype = &std::use_facet>(l); + m_pmessages = std::has_facet >(l) ? &std::use_facet >(l) : 0; + m_pcollate = &std::use_facet >(l); + return result; +} + +// +// class cpp_regex_traits_char_layer: +// implements methods that require specialization for narrow characters: +// +template +class cpp_regex_traits_char_layer : public cpp_regex_traits_base +{ + typedef std::basic_string string_type; + typedef std::map map_type; + typedef typename map_type::const_iterator map_iterator_type; +public: + cpp_regex_traits_char_layer(const std::locale& l) + : cpp_regex_traits_base(l) + { + init(); + } + cpp_regex_traits_char_layer(const cpp_regex_traits_base& b) + : cpp_regex_traits_base(b) + { + init(); + } + void init(); + + regex_constants::syntax_type syntax_type(charT c)const + { + map_iterator_type i = m_char_map.find(c); + return ((i == m_char_map.end()) ? 0 : i->second); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + map_iterator_type i = m_char_map.find(c); + if(i == m_char_map.end()) + { + if(this->m_pctype->is(std::ctype_base::lower, c)) return regex_constants::escape_type_class; + if(this->m_pctype->is(std::ctype_base::upper, c)) return regex_constants::escape_type_not_class; + return 0; + } + return i->second; + } + +private: + string_type get_default_message(regex_constants::syntax_type); + // TODO: use a hash table when available! + map_type m_char_map; +}; + +template +void cpp_regex_traits_char_layer::init() +{ + // we need to start by initialising our syntax map so we know which + // character is used for which purpose: +#ifndef __IBMCPP__ + typename std::messages::catalog cat = static_cast::catalog>(-1); +#else + typename std::messages::catalog cat = reinterpret_cast::catalog>(-1); +#endif + std::string cat_name(cpp_regex_traits::get_catalog_name()); + if((!cat_name.empty()) && (this->m_pmessages != 0)) + { + cat = this->m_pmessages->open( + cat_name, + this->m_locale); + if((int)cat < 0) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if((int)cat >= 0) + { +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + string_type mss = this->m_pmessages->get(cat, 0, i, get_default_message(i)); + for(typename string_type::size_type j = 0; j < mss.size(); ++j) + { + m_char_map[mss[j]] = i; + } + } + this->m_pmessages->close(cat); +#ifndef BOOST_NO_EXCEPTIONS + } + catch(...) + { + if(this->m_pmessages) + this->m_pmessages->close(cat); + throw; + } +#endif + } + else + { + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + const char* ptr = get_default_syntax(i); + while(ptr && *ptr) + { + m_char_map[this->m_pctype->widen(*ptr)] = i; + ++ptr; + } + } + } +} + +template +typename cpp_regex_traits_char_layer::string_type + cpp_regex_traits_char_layer::get_default_message(regex_constants::syntax_type i) +{ + const char* ptr = get_default_syntax(i); + string_type result; + while(ptr && *ptr) + { + result.append(1, this->m_pctype->widen(*ptr)); + ++ptr; + } + return result; +} + +// +// specialized version for narrow characters: +// +template <> +class cpp_regex_traits_char_layer : public cpp_regex_traits_base +{ + typedef std::string string_type; +public: + cpp_regex_traits_char_layer(const std::locale& l) + : cpp_regex_traits_base(l) + { + init(); + } + cpp_regex_traits_char_layer(const cpp_regex_traits_base& l) + : cpp_regex_traits_base(l) + { + init(); + } + + regex_constants::syntax_type syntax_type(char c)const + { + return m_char_map[static_cast(c)]; + } + regex_constants::escape_syntax_type escape_syntax_type(char c) const + { + return m_char_map[static_cast(c)]; + } + +private: + regex_constants::syntax_type m_char_map[1u << CHAR_BIT]; + void init(); +}; + +// +// class cpp_regex_traits_implementation: +// provides pimpl implementation for cpp_regex_traits. +// +template +class cpp_regex_traits_implementation : public cpp_regex_traits_char_layer +{ +public: + typedef typename cpp_regex_traits::char_class_type char_class_type; + typedef typename std::ctype::mask native_mask_type; + typedef typename std::make_unsigned::type unsigned_native_mask_type; + static const char_class_type mask_blank = 1u << 24; + static const char_class_type mask_word = 1u << 25; + static const char_class_type mask_unicode = 1u << 26; + static const char_class_type mask_horizontal = 1u << 27; + static const char_class_type mask_vertical = 1u << 28; + + typedef std::basic_string string_type; + typedef charT char_type; + //cpp_regex_traits_implementation(); + cpp_regex_traits_implementation(const std::locale& l) + : cpp_regex_traits_char_layer(l) + { + init(); + } + cpp_regex_traits_implementation(const cpp_regex_traits_base& l) + : cpp_regex_traits_char_layer(l) + { + init(); + } + std::string error_string(regex_constants::error_type n) const + { + if(!m_error_strings.empty()) + { + std::map::const_iterator p = m_error_strings.find(n); + return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second; + } + return get_default_error_string(n); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + char_class_type result = lookup_classname_imp(p1, p2); + if(result == 0) + { + string_type temp(p1, p2); + this->m_pctype->tolower(&*temp.begin(), &*temp.begin() + temp.size()); + result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size()); + } + return result; + } + string_type lookup_collatename(const charT* p1, const charT* p2) const; + string_type transform_primary(const charT* p1, const charT* p2) const; + string_type transform(const charT* p1, const charT* p2) const; +private: + std::map m_error_strings; // error messages indexed by numberic ID + std::map m_custom_class_names; // character class names + std::map m_custom_collate_names; // collating element names + unsigned m_collate_type; // the form of the collation string + charT m_collate_delim; // the collation group delimiter + // + // helpers: + // + char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const; + void init(); +}; + +template +typename cpp_regex_traits_implementation::char_class_type const cpp_regex_traits_implementation::mask_blank; +template +typename cpp_regex_traits_implementation::char_class_type const cpp_regex_traits_implementation::mask_word; +template +typename cpp_regex_traits_implementation::char_class_type const cpp_regex_traits_implementation::mask_unicode; +template +typename cpp_regex_traits_implementation::char_class_type const cpp_regex_traits_implementation::mask_vertical; +template +typename cpp_regex_traits_implementation::char_class_type const cpp_regex_traits_implementation::mask_horizontal; + +template +typename cpp_regex_traits_implementation::string_type + cpp_regex_traits_implementation::transform_primary(const charT* p1, const charT* p2) const +{ + // + // PRECONDITIONS: + // + // A bug in gcc 3.2 (and maybe other versions as well) treats + // p1 as a null terminated string, for efficiency reasons + // we work around this elsewhere, but just assert here that + // we adhere to gcc's (buggy) preconditions... + // + BOOST_REGEX_ASSERT(*p2 == 0); + string_type result; +#if defined(_CPPLIB_VER) + // + // A bug in VC11 and 12 causes the program to hang if we pass a null-string + // to std::collate::transform, but only for certain locales :-( + // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware). + // + if(*p1 == 0) + { + return string_type(1, charT(0)); + } +#endif + // + // swallowing all exceptions here is a bad idea + // however at least one std lib will always throw + // std::bad_alloc for certain arguments... + // +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + // + // What we do here depends upon the format of the sort key returned by + // sort key returned by this->transform: + // + switch(m_collate_type) + { + case sort_C: + case sort_unknown: + // the best we can do is translate to lower case, then get a regular sort key: + { + result.assign(p1, p2); + this->m_pctype->tolower(&*result.begin(), &*result.begin() + result.size()); + result = this->m_pcollate->transform(&*result.begin(), &*result.begin() + result.size()); + break; + } + case sort_fixed: + { + // get a regular sort key, and then truncate it: + result.assign(this->m_pcollate->transform(p1, p2)); + result.erase(this->m_collate_delim); + break; + } + case sort_delim: + // get a regular sort key, and then truncate everything after the delim: + result.assign(this->m_pcollate->transform(p1, p2)); + std::size_t i; + for(i = 0; i < result.size(); ++i) + { + if(result[i] == m_collate_delim) + break; + } + result.erase(i); + break; + } +#ifndef BOOST_NO_EXCEPTIONS + }catch(...){} +#endif + while((!result.empty()) && (charT(0) == *result.rbegin())) + result.erase(result.size() - 1); + if(result.empty()) + { + // character is ignorable at the primary level: + result = string_type(1, charT(0)); + } + return result; +} + +template +typename cpp_regex_traits_implementation::string_type + cpp_regex_traits_implementation::transform(const charT* p1, const charT* p2) const +{ + // + // PRECONDITIONS: + // + // A bug in gcc 3.2 (and maybe other versions as well) treats + // p1 as a null terminated string, for efficiency reasons + // we work around this elsewhere, but just assert here that + // we adhere to gcc's (buggy) preconditions... + // + BOOST_REGEX_ASSERT(*p2 == 0); + // + // swallowing all exceptions here is a bad idea + // however at least one std lib will always throw + // std::bad_alloc for certain arguments... + // + string_type result, result2; +#if defined(_CPPLIB_VER) + // + // A bug in VC11 and 12 causes the program to hang if we pass a null-string + // to std::collate::transform, but only for certain locales :-( + // Probably effects Intel and Clang or any compiler using the VC std library (Dinkumware). + // + if(*p1 == 0) + { + return result; + } +#endif +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + result = this->m_pcollate->transform(p1, p2); + // + // some implementations (Dinkumware) append unnecessary trailing \0's: + while((!result.empty()) && (charT(0) == *result.rbegin())) + result.erase(result.size() - 1); + // + // We may have NULL's used as separators between sections of the collate string, + // an example would be Boost.Locale. We have no way to detect this case via + // #defines since this can be used with any compiler/platform combination. + // Unfortunately our state machine (which was devised when all implementations + // used underlying C language API's) can't cope with that case. One workaround + // is to replace each character with 2, fortunately this code isn't used that + // much as this is now slower than before :-( + // + typedef typename std::make_unsigned::type uchar_type; + result2.reserve(result.size() * 2 + 2); + for(unsigned i = 0; i < result.size(); ++i) + { + if(static_cast(result[i]) == (std::numeric_limits::max)()) + { + result2.append(1, charT((std::numeric_limits::max)())).append(1, charT('b')); + } + else + { + result2.append(1, static_cast(1 + static_cast(result[i]))).append(1, charT('b') - 1); + } + } + BOOST_REGEX_ASSERT(std::find(result2.begin(), result2.end(), charT(0)) == result2.end()); +#ifndef BOOST_NO_EXCEPTIONS + } + catch(...) + { + } +#endif + return result2; +} + + +template +typename cpp_regex_traits_implementation::string_type + cpp_regex_traits_implementation::lookup_collatename(const charT* p1, const charT* p2) const +{ + typedef typename std::map::const_iterator iter_type; + if(!m_custom_collate_names.empty()) + { + iter_type pos = m_custom_collate_names.find(string_type(p1, p2)); + if(pos != m_custom_collate_names.end()) + return pos->second; + } + std::string name(p1, p2); + name = lookup_default_collate_name(name); + if(!name.empty()) + return string_type(name.begin(), name.end()); + if(p2 - p1 == 1) + return string_type(1, *p1); + return string_type(); +} + +template +void cpp_regex_traits_implementation::init() +{ +#ifndef __IBMCPP__ + typename std::messages::catalog cat = static_cast::catalog>(-1); +#else + typename std::messages::catalog cat = reinterpret_cast::catalog>(-1); +#endif + std::string cat_name(cpp_regex_traits::get_catalog_name()); + if((!cat_name.empty()) && (this->m_pmessages != 0)) + { + cat = this->m_pmessages->open( + cat_name, + this->m_locale); + if((int)cat < 0) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if((int)cat >= 0) + { + // + // Error messages: + // + for(boost::regex_constants::error_type i = static_cast(0); + i <= boost::regex_constants::error_unknown; + i = static_cast(i + 1)) + { + const char* p = get_default_error_string(i); + string_type default_message; + while(*p) + { + default_message.append(1, this->m_pctype->widen(*p)); + ++p; + } + string_type s = this->m_pmessages->get(cat, 0, i+200, default_message); + std::string result; + for(std::string::size_type j = 0; j < s.size(); ++j) + { + result.append(1, this->m_pctype->narrow(s[j], 0)); + } + m_error_strings[i] = result; + } + // + // Custom class names: + // + static const char_class_type masks[16] = + { + static_cast(std::ctype::alnum), + static_cast(std::ctype::alpha), + static_cast(std::ctype::cntrl), + static_cast(std::ctype::digit), + static_cast(std::ctype::graph), + cpp_regex_traits_implementation::mask_horizontal, + static_cast(std::ctype::lower), + static_cast(std::ctype::print), + static_cast(std::ctype::punct), + static_cast(std::ctype::space), + static_cast(std::ctype::upper), + cpp_regex_traits_implementation::mask_vertical, + static_cast(std::ctype::xdigit), + cpp_regex_traits_implementation::mask_blank, + cpp_regex_traits_implementation::mask_word, + cpp_regex_traits_implementation::mask_unicode, + }; + static const string_type null_string; + for(unsigned int j = 0; j <= 13; ++j) + { + string_type s(this->m_pmessages->get(cat, 0, j+300, null_string)); + if(!s.empty()) + this->m_custom_class_names[s] = masks[j]; + } + } + // + // get the collation format used by m_pcollate: + // + m_collate_type = BOOST_REGEX_DETAIL_NS::find_sort_syntax(this, &m_collate_delim); +} + +template +typename cpp_regex_traits_implementation::char_class_type + cpp_regex_traits_implementation::lookup_classname_imp(const charT* p1, const charT* p2) const +{ + static const char_class_type masks[22] = + { + 0, + static_cast(std::ctype::alnum), + static_cast(std::ctype::alpha), + cpp_regex_traits_implementation::mask_blank, + static_cast(std::ctype::cntrl), + static_cast(std::ctype::digit), + static_cast(std::ctype::digit), + static_cast(std::ctype::graph), + cpp_regex_traits_implementation::mask_horizontal, + static_cast(std::ctype::lower), + static_cast(std::ctype::lower), + static_cast(std::ctype::print), + static_cast(std::ctype::punct), + static_cast(std::ctype::space), + static_cast(std::ctype::space), + static_cast(std::ctype::upper), + cpp_regex_traits_implementation::mask_unicode, + static_cast(std::ctype::upper), + cpp_regex_traits_implementation::mask_vertical, + static_cast(std::ctype::alnum) | cpp_regex_traits_implementation::mask_word, + static_cast(std::ctype::alnum) | cpp_regex_traits_implementation::mask_word, + static_cast(std::ctype::xdigit), + }; + if(!m_custom_class_names.empty()) + { + typedef typename std::map, char_class_type>::const_iterator map_iter; + map_iter pos = m_custom_class_names.find(string_type(p1, p2)); + if(pos != m_custom_class_names.end()) + return pos->second; + } + std::size_t state_id = 1 + BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2); + BOOST_REGEX_ASSERT(state_id < sizeof(masks) / sizeof(masks[0])); + return masks[state_id]; +} + +template +inline std::shared_ptr > create_cpp_regex_traits(const std::locale& l) +{ + cpp_regex_traits_base key(l); + return ::boost::object_cache, cpp_regex_traits_implementation >::get(key, 5); +} + +} // BOOST_REGEX_DETAIL_NS + +template +class cpp_regex_traits +{ +private: + typedef std::ctype ctype_type; +public: + typedef charT char_type; + typedef std::size_t size_type; + typedef std::basic_string string_type; + typedef std::locale locale_type; + typedef std::uint_least32_t char_class_type; + + struct boost_extensions_tag{}; + + cpp_regex_traits() + : m_pimpl(BOOST_REGEX_DETAIL_NS::create_cpp_regex_traits(std::locale())) + { } + static size_type length(const char_type* p) + { + return std::char_traits::length(p); + } + regex_constants::syntax_type syntax_type(charT c)const + { + return m_pimpl->syntax_type(c); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + return m_pimpl->escape_syntax_type(c); + } + charT translate(charT c) const + { + return c; + } + charT translate_nocase(charT c) const + { + return m_pimpl->m_pctype->tolower(c); + } + charT translate(charT c, bool icase) const + { + return icase ? m_pimpl->m_pctype->tolower(c) : c; + } + charT tolower(charT c) const + { + return m_pimpl->m_pctype->tolower(c); + } + charT toupper(charT c) const + { + return m_pimpl->m_pctype->toupper(c); + } + string_type transform(const charT* p1, const charT* p2) const + { + return m_pimpl->transform(p1, p2); + } + string_type transform_primary(const charT* p1, const charT* p2) const + { + return m_pimpl->transform_primary(p1, p2); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_classname(p1, p2); + } + string_type lookup_collatename(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_collatename(p1, p2); + } + bool isctype(charT c, char_class_type f) const + { + typedef typename std::ctype::mask ctype_mask; + + static const ctype_mask mask_base = + static_cast( + std::ctype::alnum + | std::ctype::alpha + | std::ctype::cntrl + | std::ctype::digit + | std::ctype::graph + | std::ctype::lower + | std::ctype::print + | std::ctype::punct + | std::ctype::space + | std::ctype::upper + | std::ctype::xdigit); + + if((f & mask_base) + && (m_pimpl->m_pctype->is( + static_cast(f & mask_base), c))) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation::mask_unicode) && BOOST_REGEX_DETAIL_NS::is_extended(c)) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation::mask_word) && (c == '_')) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation::mask_blank) + && m_pimpl->m_pctype->is(std::ctype::space, c) + && !BOOST_REGEX_DETAIL_NS::is_separator(c)) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation::mask_vertical) + && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v'))) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation::mask_horizontal) + && this->isctype(c, std::ctype::space) && !this->isctype(c, BOOST_REGEX_DETAIL_NS::cpp_regex_traits_implementation::mask_vertical)) + return true; +#ifdef __CYGWIN__ + // + // Cygwin has a buggy ctype facet, see https://www.cygwin.com/ml/cygwin/2012-08/msg00178.html: + // + else if((f & std::ctype::xdigit) == std::ctype::xdigit) + { + if((c >= 'a') && (c <= 'f')) + return true; + if((c >= 'A') && (c <= 'F')) + return true; + } +#endif + return false; + } + std::intmax_t toi(const charT*& p1, const charT* p2, int radix)const; + int value(charT c, int radix)const + { + const charT* pc = &c; + return (int)toi(pc, pc + 1, radix); + } + locale_type imbue(locale_type l) + { + std::locale result(getloc()); + m_pimpl = BOOST_REGEX_DETAIL_NS::create_cpp_regex_traits(l); + return result; + } + locale_type getloc()const + { + return m_pimpl->m_locale; + } + std::string error_string(regex_constants::error_type n) const + { + return m_pimpl->error_string(n); + } + + // + // extension: + // set the name of the message catalog in use (defaults to "boost_regex"). + // + static std::string catalog_name(const std::string& name); + static std::string get_catalog_name(); + +private: + std::shared_ptr > m_pimpl; + // + // catalog name handler: + // + static std::string& get_catalog_name_inst(); + +#ifdef BOOST_HAS_THREADS + static std::mutex& get_mutex_inst(); +#endif +}; + + +template +std::intmax_t cpp_regex_traits::toi(const charT*& first, const charT* last, int radix)const +{ + BOOST_REGEX_DETAIL_NS::parser_buf sbuf; // buffer for parsing numbers. + std::basic_istream is(&sbuf); // stream for parsing numbers. + + // we do NOT want to parse any thousands separators inside the stream: + last = std::find(first, last, std::use_facet>(is.getloc()).thousands_sep()); + + sbuf.pubsetbuf(const_cast(static_cast(first)), static_cast(last-first)); + is.clear(); + if(std::abs(radix) == 16) is >> std::hex; + else if(std::abs(radix) == 8) is >> std::oct; + else is >> std::dec; + std::intmax_t val; + if(is >> val) + { + first = first + ((last - first) - sbuf.in_avail()); + return val; + } + else + return -1; +} + +template +std::string cpp_regex_traits::catalog_name(const std::string& name) +{ +#ifdef BOOST_HAS_THREADS + std::lock_guard lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + get_catalog_name_inst() = name; + return result; +} + +template +std::string& cpp_regex_traits::get_catalog_name_inst() +{ + static std::string s_name; + return s_name; +} + +template +std::string cpp_regex_traits::get_catalog_name() +{ +#ifdef BOOST_HAS_THREADS + std::lock_guard lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + return result; +} + +#ifdef BOOST_HAS_THREADS +template +std::mutex& cpp_regex_traits::get_mutex_inst() +{ + static std::mutex s_mutex; + return s_mutex; +} +#endif + +namespace BOOST_REGEX_DETAIL_NS { + + inline void cpp_regex_traits_char_layer::init() + { + // we need to start by initialising our syntax map so we know which + // character is used for which purpose: + std::memset(m_char_map, 0, sizeof(m_char_map)); +#ifndef __IBMCPP__ + std::messages::catalog cat = static_cast::catalog>(-1); +#else + std::messages::catalog cat = reinterpret_cast::catalog>(-1); +#endif + std::string cat_name(cpp_regex_traits::get_catalog_name()); + if ((!cat_name.empty()) && (m_pmessages != 0)) + { + cat = this->m_pmessages->open( + cat_name, + this->m_locale); + if ((int)cat < 0) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if ((int)cat >= 0) + { +#ifndef BOOST_NO_EXCEPTIONS + try { +#endif + for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + string_type mss = this->m_pmessages->get(cat, 0, i, get_default_syntax(i)); + for (string_type::size_type j = 0; j < mss.size(); ++j) + { + m_char_map[static_cast(mss[j])] = i; + } + } + this->m_pmessages->close(cat); +#ifndef BOOST_NO_EXCEPTIONS + } + catch (...) + { + this->m_pmessages->close(cat); + throw; + } +#endif + } + else + { + for (regex_constants::syntax_type j = 1; j < regex_constants::syntax_max; ++j) + { + const char* ptr = get_default_syntax(j); + while (ptr && *ptr) + { + m_char_map[static_cast(*ptr)] = j; + ++ptr; + } + } + } + // + // finish off by calculating our escape types: + // + unsigned char i = 'A'; + do + { + if (m_char_map[i] == 0) + { + if (this->m_pctype->is(std::ctype_base::lower, i)) + m_char_map[i] = regex_constants::escape_type_class; + else if (this->m_pctype->is(std::ctype_base::upper, i)) + m_char_map[i] = regex_constants::escape_type_not_class; + } + } while (0xFF != i++); + } + +} // namespace detail + + +} // boost + +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif + + +#endif diff --git a/boost/regex/v5/cregex.hpp b/boost/regex/v5/cregex.hpp new file mode 100644 index 00000000..a6571052 --- /dev/null +++ b/boost/regex/v5/cregex.hpp @@ -0,0 +1,195 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE cregex.cpp + * VERSION see + * DESCRIPTION: Declares POSIX API functions + * + boost::RegEx high level wrapper. + */ + +#ifndef BOOST_RE_CREGEX_HPP_INCLUDED +#define BOOST_RE_CREGEX_HPP_INCLUDED + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif +#include +#include + +#ifndef BOOST_REGEX_STANDALONE +#if !defined(BOOST_REGEX_NO_LIB) && !defined(BOOST_REGEX_SOURCE) && !defined(BOOST_ALL_NO_LIB) && defined(__cplusplus) +# define BOOST_LIB_NAME boost_regex +# if defined(BOOST_REGEX_DYN_LINK) || defined(BOOST_ALL_DYN_LINK) +# define BOOST_DYN_LINK +# endif +# ifdef BOOST_REGEX_DIAG +# define BOOST_LIB_DIAGNOSTIC +# endif +# include +#endif +#endif + +#ifdef __cplusplus +#include +#else +#include +#endif + +/* include these defs only for POSIX compatablity */ +#ifdef __cplusplus +namespace boost{ +extern "C" { +#endif + +#if defined(__cplusplus) +typedef std::ptrdiff_t regoff_t; +typedef std::size_t regsize_t; +#else +typedef ptrdiff_t regoff_t; +typedef size_t regsize_t; +#endif + +typedef struct +{ + unsigned int re_magic; +#ifdef __cplusplus + std::size_t re_nsub; /* number of parenthesized subexpressions */ +#else + size_t re_nsub; +#endif + const char* re_endp; /* end pointer for REG_PEND */ + void* guts; /* none of your business :-) */ + match_flag_type eflags; /* none of your business :-) */ +} regex_tA; + +#ifndef BOOST_NO_WREGEX +typedef struct +{ + unsigned int re_magic; +#ifdef __cplusplus + std::size_t re_nsub; /* number of parenthesized subexpressions */ +#else + size_t re_nsub; +#endif + const wchar_t* re_endp; /* end pointer for REG_PEND */ + void* guts; /* none of your business :-) */ + match_flag_type eflags; /* none of your business :-) */ +} regex_tW; +#endif + +typedef struct +{ + regoff_t rm_so; /* start of match */ + regoff_t rm_eo; /* end of match */ +} regmatch_t; + +/* regcomp() flags */ +typedef enum{ + REG_BASIC = 0000, + REG_EXTENDED = 0001, + REG_ICASE = 0002, + REG_NOSUB = 0004, + REG_NEWLINE = 0010, + REG_NOSPEC = 0020, + REG_PEND = 0040, + REG_DUMP = 0200, + REG_NOCOLLATE = 0400, + REG_ESCAPE_IN_LISTS = 01000, + REG_NEWLINE_ALT = 02000, + REG_PERLEX = 04000, + + REG_PERL = REG_EXTENDED | REG_NOCOLLATE | REG_ESCAPE_IN_LISTS | REG_PERLEX, + REG_AWK = REG_EXTENDED | REG_ESCAPE_IN_LISTS, + REG_GREP = REG_BASIC | REG_NEWLINE_ALT, + REG_EGREP = REG_EXTENDED | REG_NEWLINE_ALT, + + REG_ASSERT = 15, + REG_INVARG = 16, + REG_ATOI = 255, /* convert name to number (!) */ + REG_ITOA = 0400 /* convert number to name (!) */ +} reg_comp_flags; + +/* regexec() flags */ +typedef enum{ + REG_NOTBOL = 00001, + REG_NOTEOL = 00002, + REG_STARTEND = 00004 +} reg_exec_flags; + +/* + * POSIX error codes: + */ +typedef unsigned reg_error_t; +typedef reg_error_t reg_errcode_t; /* backwards compatibility */ + +static const reg_error_t REG_NOERROR = 0; /* Success. */ +static const reg_error_t REG_NOMATCH = 1; /* Didn't find a match (for regexec). */ + + /* POSIX regcomp return error codes. (In the order listed in the + standard.) */ +static const reg_error_t REG_BADPAT = 2; /* Invalid pattern. */ +static const reg_error_t REG_ECOLLATE = 3; /* Undefined collating element. */ +static const reg_error_t REG_ECTYPE = 4; /* Invalid character class name. */ +static const reg_error_t REG_EESCAPE = 5; /* Trailing backslash. */ +static const reg_error_t REG_ESUBREG = 6; /* Invalid back reference. */ +static const reg_error_t REG_EBRACK = 7; /* Unmatched left bracket. */ +static const reg_error_t REG_EPAREN = 8; /* Parenthesis imbalance. */ +static const reg_error_t REG_EBRACE = 9; /* Unmatched \{. */ +static const reg_error_t REG_BADBR = 10; /* Invalid contents of \{\}. */ +static const reg_error_t REG_ERANGE = 11; /* Invalid range end. */ +static const reg_error_t REG_ESPACE = 12; /* Ran out of memory. */ +static const reg_error_t REG_BADRPT = 13; /* No preceding re for repetition op. */ +static const reg_error_t REG_EEND = 14; /* unexpected end of expression */ +static const reg_error_t REG_ESIZE = 15; /* expression too big */ +static const reg_error_t REG_ERPAREN = 8; /* = REG_EPAREN : unmatched right parenthesis */ +static const reg_error_t REG_EMPTY = 17; /* empty expression */ +static const reg_error_t REG_E_MEMORY = 15; /* = REG_ESIZE : out of memory */ +static const reg_error_t REG_ECOMPLEXITY = 18; /* complexity too high */ +static const reg_error_t REG_ESTACK = 19; /* out of stack space */ +static const reg_error_t REG_E_PERL = 20; /* Perl (?...) error */ +static const reg_error_t REG_E_UNKNOWN = 21; /* unknown error */ +static const reg_error_t REG_ENOSYS = 21; /* = REG_E_UNKNOWN : Reserved. */ + +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompA(regex_tA*, const char*, int); +BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int, const regex_tA*, char*, regsize_t); +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecA(const regex_tA*, const char*, regsize_t, regmatch_t*, int); +BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeA(regex_tA*); + +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompW(regex_tW*, const wchar_t*, int); +BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int, const regex_tW*, wchar_t*, regsize_t); +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecW(const regex_tW*, const wchar_t*, regsize_t, regmatch_t*, int); +BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeW(regex_tW*); +#endif + +#ifdef UNICODE +#define regcomp regcompW +#define regerror regerrorW +#define regexec regexecW +#define regfree regfreeW +#define regex_t regex_tW +#else +#define regcomp regcompA +#define regerror regerrorA +#define regexec regexecA +#define regfree regfreeA +#define regex_t regex_tA +#endif + +#ifdef __cplusplus +} /* extern "C" */ +} /* namespace */ +#endif + +#endif /* include guard */ + diff --git a/boost/regex/v5/error_type.hpp b/boost/regex/v5/error_type.hpp new file mode 100644 index 00000000..afcc71e3 --- /dev/null +++ b/boost/regex/v5/error_type.hpp @@ -0,0 +1,59 @@ +/* + * + * Copyright (c) 2003-2005 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE error_type.hpp + * VERSION see + * DESCRIPTION: Declares regular expression error type enumerator. + */ + +#ifndef BOOST_REGEX_ERROR_TYPE_HPP +#define BOOST_REGEX_ERROR_TYPE_HPP + +#ifdef __cplusplus +namespace boost{ +#endif + +#ifdef __cplusplus +namespace regex_constants{ + +enum error_type{ + + error_ok = 0, /* not used */ + error_no_match = 1, /* not used */ + error_bad_pattern = 2, + error_collate = 3, + error_ctype = 4, + error_escape = 5, + error_backref = 6, + error_brack = 7, + error_paren = 8, + error_brace = 9, + error_badbrace = 10, + error_range = 11, + error_space = 12, + error_badrepeat = 13, + error_end = 14, /* not used */ + error_size = 15, + error_right_paren = 16, /* not used */ + error_empty = 17, + error_complexity = 18, + error_stack = 19, + error_perl_extension = 20, + error_unknown = 21 +}; + +} +} +#endif /* __cplusplus */ + +#endif diff --git a/boost/regex/v5/iterator_category.hpp b/boost/regex/v5/iterator_category.hpp new file mode 100644 index 00000000..9bd74578 --- /dev/null +++ b/boost/regex/v5/iterator_category.hpp @@ -0,0 +1,84 @@ +/* + * + * Copyright (c) 2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_match.hpp + * VERSION see + * DESCRIPTION: Iterator traits for selecting an iterator type as + * an integral constant expression. + */ + + +#ifndef BOOST_REGEX_ITERATOR_CATEGORY_HPP +#define BOOST_REGEX_ITERATOR_CATEGORY_HPP + +#include +#include + +namespace boost{ +namespace detail{ + +template +struct is_random_imp +{ +private: + typedef typename std::iterator_traits::iterator_category cat; +public: + static const bool value = (std::is_convertible::value); +}; + +template +struct is_random_pointer_imp +{ + static const bool value = true; +}; + +template +struct is_random_imp_selector +{ + template + struct rebind + { + typedef is_random_imp type; + }; +}; + +template <> +struct is_random_imp_selector +{ + template + struct rebind + { + typedef is_random_pointer_imp type; + }; +}; + +} + +template +struct is_random_access_iterator +{ +private: + typedef detail::is_random_imp_selector< std::is_pointer::value> selector; + typedef typename selector::template rebind bound_type; + typedef typename bound_type::type answer; +public: + static const bool value = answer::value; +}; + +template +const bool is_random_access_iterator::value; + +} + +#endif + diff --git a/boost/regex/v5/match_flags.hpp b/boost/regex/v5/match_flags.hpp new file mode 100644 index 00000000..6ff236b0 --- /dev/null +++ b/boost/regex/v5/match_flags.hpp @@ -0,0 +1,156 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE match_flags.hpp + * VERSION see + * DESCRIPTION: Declares match_flags type. + */ + +#ifndef BOOST_REGEX_V5_MATCH_FLAGS +#define BOOST_REGEX_V5_MATCH_FLAGS + +#ifdef __cplusplus +# include +#endif + +#ifdef __cplusplus +namespace boost{ + namespace regex_constants{ +#endif + +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#if BOOST_REGEX_MSVC >= 1800 +#pragma warning(disable : 26812) +#endif +#endif + +typedef enum _match_flags +{ + match_default = 0, + match_not_bol = 1, /* first is not start of line */ + match_not_eol = match_not_bol << 1, /* last is not end of line */ + match_not_bob = match_not_eol << 1, /* first is not start of buffer */ + match_not_eob = match_not_bob << 1, /* last is not end of buffer */ + match_not_bow = match_not_eob << 1, /* first is not start of word */ + match_not_eow = match_not_bow << 1, /* last is not end of word */ + match_not_dot_newline = match_not_eow << 1, /* \n is not matched by '.' */ + match_not_dot_null = match_not_dot_newline << 1, /* '\0' is not matched by '.' */ + match_prev_avail = match_not_dot_null << 1, /* *--first is a valid expression */ + match_init = match_prev_avail << 1, /* internal use */ + match_any = match_init << 1, /* don't care what we match */ + match_not_null = match_any << 1, /* string can't be null */ + match_continuous = match_not_null << 1, /* each grep match must continue from */ + /* uninterrupted from the previous one */ + match_partial = match_continuous << 1, /* find partial matches */ + + match_stop = match_partial << 1, /* stop after first match (grep) V3 only */ + match_not_initial_null = match_stop, /* don't match initial null, V4 only */ + match_all = match_stop << 1, /* must find the whole of input even if match_any is set */ + match_perl = match_all << 1, /* Use perl matching rules */ + match_posix = match_perl << 1, /* Use POSIX matching rules */ + match_nosubs = match_posix << 1, /* don't trap marked subs */ + match_extra = match_nosubs << 1, /* include full capture information for repeated captures */ + match_single_line = match_extra << 1, /* treat text as single line and ignore any \n's when matching ^ and $. */ + match_unused1 = match_single_line << 1, /* unused */ + match_unused2 = match_unused1 << 1, /* unused */ + match_unused3 = match_unused2 << 1, /* unused */ + match_max = match_unused3, + + format_perl = 0, /* perl style replacement */ + format_default = 0, /* ditto. */ + format_sed = match_max << 1, /* sed style replacement. */ + format_all = format_sed << 1, /* enable all extensions to syntax. */ + format_no_copy = format_all << 1, /* don't copy non-matching segments. */ + format_first_only = format_no_copy << 1, /* Only replace first occurrence. */ + format_is_if = format_first_only << 1, /* internal use only. */ + format_literal = format_is_if << 1, /* treat string as a literal */ + + match_not_any = match_not_bol | match_not_eol | match_not_bob + | match_not_eob | match_not_bow | match_not_eow | match_not_dot_newline + | match_not_dot_null | match_prev_avail | match_init | match_not_null + | match_continuous | match_partial | match_stop | match_not_initial_null + | match_stop | match_all | match_perl | match_posix | match_nosubs + | match_extra | match_single_line | match_unused1 | match_unused2 + | match_unused3 | match_max | format_perl | format_default | format_sed + | format_all | format_no_copy | format_first_only | format_is_if + | format_literal + + +} match_flags; + +typedef match_flags match_flag_type; + +#ifdef __cplusplus +inline match_flags operator&(match_flags m1, match_flags m2) +{ return static_cast(static_cast(m1) & static_cast(m2)); } +inline match_flags operator|(match_flags m1, match_flags m2) +{ return static_cast(static_cast(m1) | static_cast(m2)); } +inline match_flags operator^(match_flags m1, match_flags m2) +{ return static_cast(static_cast(m1) ^ static_cast(m2)); } +inline match_flags operator~(match_flags m1) +{ return static_cast(~static_cast(m1)); } +inline match_flags& operator&=(match_flags& m1, match_flags m2) +{ m1 = m1&m2; return m1; } +inline match_flags& operator|=(match_flags& m1, match_flags m2) +{ m1 = m1|m2; return m1; } +inline match_flags& operator^=(match_flags& m1, match_flags m2) +{ m1 = m1^m2; return m1; } +#endif + +#ifdef __cplusplus +} /* namespace regex_constants */ +/* + * import names into boost for backwards compatibility: + */ +using regex_constants::match_flag_type; +using regex_constants::match_default; +using regex_constants::match_not_bol; +using regex_constants::match_not_eol; +using regex_constants::match_not_bob; +using regex_constants::match_not_eob; +using regex_constants::match_not_bow; +using regex_constants::match_not_eow; +using regex_constants::match_not_dot_newline; +using regex_constants::match_not_dot_null; +using regex_constants::match_prev_avail; +/* using regex_constants::match_init; */ +using regex_constants::match_any; +using regex_constants::match_not_null; +using regex_constants::match_continuous; +using regex_constants::match_partial; +/*using regex_constants::match_stop; */ +using regex_constants::match_all; +using regex_constants::match_perl; +using regex_constants::match_posix; +using regex_constants::match_nosubs; +using regex_constants::match_extra; +using regex_constants::match_single_line; +/*using regex_constants::match_max; */ +using regex_constants::format_all; +using regex_constants::format_sed; +using regex_constants::format_perl; +using regex_constants::format_default; +using regex_constants::format_no_copy; +using regex_constants::format_first_only; +/*using regex_constants::format_is_if;*/ + +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif + + +} /* namespace boost */ +#endif /* __cplusplus */ +#endif /* include guard */ + diff --git a/boost/regex/v5/match_results.hpp b/boost/regex/v5/match_results.hpp new file mode 100644 index 00000000..3f9cd012 --- /dev/null +++ b/boost/regex/v5/match_results.hpp @@ -0,0 +1,667 @@ +/* + * + * Copyright (c) 1998-2009 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE match_results.cpp + * VERSION see + * DESCRIPTION: Declares template class match_results. + */ + +#ifndef BOOST_REGEX_V5_MATCH_RESULTS_HPP +#define BOOST_REGEX_V5_MATCH_RESULTS_HPP + +namespace boost{ +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable : 4251 4459) +#if BOOST_REGEX_MSVC < 1700 +# pragma warning(disable : 4231) +#endif +# if BOOST_REGEX_MSVC < 1600 +# pragma warning(disable : 4660) +# endif +#endif + +namespace BOOST_REGEX_DETAIL_NS{ + +class named_subexpressions; + +} + +template +class match_results +{ +private: + typedef std::vector, Allocator> vector_type; +public: + typedef sub_match value_type; + typedef typename std::allocator_traits::value_type const & const_reference; + typedef const_reference reference; + typedef typename vector_type::const_iterator const_iterator; + typedef const_iterator iterator; + typedef typename std::iterator_traits< + BidiIterator>::difference_type difference_type; + typedef typename std::allocator_traits::size_type size_type; + typedef Allocator allocator_type; + typedef typename std::iterator_traits< + BidiIterator>::value_type char_type; + typedef std::basic_string string_type; + typedef BOOST_REGEX_DETAIL_NS::named_subexpressions named_sub_type; + + // construct/copy/destroy: + explicit match_results(const Allocator& a = Allocator()) + : m_subs(a), m_base(), m_null(), m_last_closed_paren(0), m_is_singular(true) {} + // + // IMPORTANT: in the code below, the crazy looking checks around m_is_singular are + // all required because it is illegal to copy a singular iterator. + // See https://svn.boost.org/trac/boost/ticket/3632. + // + match_results(const match_results& m) + : m_subs(m.m_subs), m_base(), m_null(), m_named_subs(m.m_named_subs), m_last_closed_paren(m.m_last_closed_paren), m_is_singular(m.m_is_singular) + { + if(!m_is_singular) + { + m_base = m.m_base; + m_null = m.m_null; + } + } + match_results& operator=(const match_results& m) + { + m_subs = m.m_subs; + m_named_subs = m.m_named_subs; + m_last_closed_paren = m.m_last_closed_paren; + m_is_singular = m.m_is_singular; + if(!m_is_singular) + { + m_base = m.m_base; + m_null = m.m_null; + } + return *this; + } + ~match_results(){} + + // size: + size_type size() const + { return empty() ? 0 : m_subs.size() - 2; } + size_type max_size() const + { return m_subs.max_size(); } + bool empty() const + { return m_subs.size() < 2; } + // element access: + difference_type length(int sub = 0) const + { + if(m_is_singular) + raise_logic_error(); + sub += 2; + if((sub < (int)m_subs.size()) && (sub > 0)) + return m_subs[sub].length(); + return 0; + } + difference_type length(const char_type* sub) const + { + if(m_is_singular) + raise_logic_error(); + const char_type* sub_end = sub; + while(*sub_end) ++sub_end; + return length(named_subexpression_index(sub, sub_end)); + } + template + difference_type length(const charT* sub) const + { + if(m_is_singular) + raise_logic_error(); + const charT* sub_end = sub; + while(*sub_end) ++sub_end; + return length(named_subexpression_index(sub, sub_end)); + } + template + difference_type length(const std::basic_string& sub) const + { + return length(sub.c_str()); + } + difference_type position(size_type sub = 0) const + { + if(m_is_singular) + raise_logic_error(); + sub += 2; + if(sub < m_subs.size()) + { + const sub_match& s = m_subs[sub]; + if(s.matched || (sub == 2)) + { + return std::distance((BidiIterator)(m_base), (BidiIterator)(s.first)); + } + } + return ~static_cast(0); + } + difference_type position(const char_type* sub) const + { + const char_type* sub_end = sub; + while(*sub_end) ++sub_end; + return position(named_subexpression_index(sub, sub_end)); + } + template + difference_type position(const charT* sub) const + { + const charT* sub_end = sub; + while(*sub_end) ++sub_end; + return position(named_subexpression_index(sub, sub_end)); + } + template + difference_type position(const std::basic_string& sub) const + { + return position(sub.c_str()); + } + string_type str(int sub = 0) const + { + if(m_is_singular) + raise_logic_error(); + sub += 2; + string_type result; + if(sub < (int)m_subs.size() && (sub > 0)) + { + const sub_match& s = m_subs[sub]; + if(s.matched) + { + result = s.str(); + } + } + return result; + } + string_type str(const char_type* sub) const + { + return (*this)[sub].str(); + } + template + string_type str(const std::basic_string& sub) const + { + return (*this)[sub].str(); + } + template + string_type str(const charT* sub) const + { + return (*this)[sub].str(); + } + template + string_type str(const std::basic_string& sub) const + { + return (*this)[sub].str(); + } + const_reference operator[](int sub) const + { + if(m_is_singular && m_subs.empty()) + raise_logic_error(); + sub += 2; + if(sub < (int)m_subs.size() && (sub >= 0)) + { + return m_subs[sub]; + } + return m_null; + } + // + // Named sub-expressions: + // + const_reference named_subexpression(const char_type* i, const char_type* j) const + { + // + // Scan for the leftmost *matched* subexpression with the specified named: + // + if(m_is_singular) + raise_logic_error(); + BOOST_REGEX_DETAIL_NS::named_subexpressions::range_type r = m_named_subs->equal_range(i, j); + while((r.first != r.second) && ((*this)[r.first->index].matched == false)) + ++r.first; + return r.first != r.second ? (*this)[r.first->index] : m_null; + } + template + const_reference named_subexpression(const charT* i, const charT* j) const + { + static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic"); + if(i == j) + return m_null; + std::vector s; + while(i != j) + s.insert(s.end(), *i++); + return named_subexpression(&*s.begin(), &*s.begin() + s.size()); + } + int named_subexpression_index(const char_type* i, const char_type* j) const + { + // + // Scan for the leftmost *matched* subexpression with the specified named. + // If none found then return the leftmost expression with that name, + // otherwise an invalid index: + // + if(m_is_singular) + raise_logic_error(); + BOOST_REGEX_DETAIL_NS::named_subexpressions::range_type s, r; + s = r = m_named_subs->equal_range(i, j); + while((r.first != r.second) && ((*this)[r.first->index].matched == false)) + ++r.first; + if(r.first == r.second) + r = s; + return r.first != r.second ? r.first->index : -20; + } + template + int named_subexpression_index(const charT* i, const charT* j) const + { + static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic"); + if(i == j) + return -20; + std::vector s; + while(i != j) + s.insert(s.end(), *i++); + return named_subexpression_index(&*s.begin(), &*s.begin() + s.size()); + } + template + const_reference operator[](const std::basic_string& s) const + { + return named_subexpression(s.c_str(), s.c_str() + s.size()); + } + const_reference operator[](const char_type* p) const + { + const char_type* e = p; + while(*e) ++e; + return named_subexpression(p, e); + } + + template + const_reference operator[](const charT* p) const + { + static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic"); + if(*p == 0) + return m_null; + std::vector s; + while(*p) + s.insert(s.end(), *p++); + return named_subexpression(&*s.begin(), &*s.begin() + s.size()); + } + template + const_reference operator[](const std::basic_string& ns) const + { + static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic"); + if(ns.empty()) + return m_null; + std::vector s; + for(unsigned i = 0; i < ns.size(); ++i) + s.insert(s.end(), ns[i]); + return named_subexpression(&*s.begin(), &*s.begin() + s.size()); + } + + const_reference prefix() const + { + if(m_is_singular) + raise_logic_error(); + return (*this)[-1]; + } + + const_reference suffix() const + { + if(m_is_singular) + raise_logic_error(); + return (*this)[-2]; + } + const_iterator begin() const + { + return (m_subs.size() > 2) ? (m_subs.begin() + 2) : m_subs.end(); + } + const_iterator end() const + { + return m_subs.end(); + } + // format: + template + OutputIterator format(OutputIterator out, + Functor fmt, + match_flag_type flags = format_default) const + { + if(m_is_singular) + raise_logic_error(); + typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type, OutputIterator>::type F; + F func(fmt); + return func(*this, out, flags); + } + template + string_type format(Functor fmt, match_flag_type flags = format_default) const + { + if(m_is_singular) + raise_logic_error(); + std::basic_string result; + BOOST_REGEX_DETAIL_NS::string_out_iterator > i(result); + + typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type, BOOST_REGEX_DETAIL_NS::string_out_iterator > >::type F; + F func(fmt); + + func(*this, i, flags); + return result; + } + // format with locale: + template + OutputIterator format(OutputIterator out, + Functor fmt, + match_flag_type flags, + const RegexT& re) const + { + if(m_is_singular) + raise_logic_error(); + typedef ::boost::regex_traits_wrapper traits_type; + typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type, OutputIterator, traits_type>::type F; + F func(fmt); + return func(*this, out, flags, re.get_traits()); + } + template + string_type format(Functor fmt, + match_flag_type flags, + const RegexT& re) const + { + if(m_is_singular) + raise_logic_error(); + typedef ::boost::regex_traits_wrapper traits_type; + std::basic_string result; + BOOST_REGEX_DETAIL_NS::string_out_iterator > i(result); + + typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type, BOOST_REGEX_DETAIL_NS::string_out_iterator >, traits_type >::type F; + F func(fmt); + + func(*this, i, flags, re.get_traits()); + return result; + } + + const_reference get_last_closed_paren()const + { + if(m_is_singular) + raise_logic_error(); + return m_last_closed_paren == 0 ? m_null : (*this)[m_last_closed_paren]; + } + + allocator_type get_allocator() const + { + return m_subs.get_allocator(); + } + void swap(match_results& that) + { + std::swap(m_subs, that.m_subs); + std::swap(m_named_subs, that.m_named_subs); + std::swap(m_last_closed_paren, that.m_last_closed_paren); + if(m_is_singular) + { + if(!that.m_is_singular) + { + m_base = that.m_base; + m_null = that.m_null; + } + } + else if(that.m_is_singular) + { + that.m_base = m_base; + that.m_null = m_null; + } + else + { + std::swap(m_base, that.m_base); + std::swap(m_null, that.m_null); + } + std::swap(m_is_singular, that.m_is_singular); + } + bool operator==(const match_results& that)const + { + if(m_is_singular) + { + return that.m_is_singular; + } + else if(that.m_is_singular) + { + return false; + } + return (m_subs == that.m_subs) && (m_base == that.m_base) && (m_last_closed_paren == that.m_last_closed_paren); + } + bool operator!=(const match_results& that)const + { return !(*this == that); } + +#ifdef BOOST_REGEX_MATCH_EXTRA + typedef typename sub_match::capture_sequence_type capture_sequence_type; + + const capture_sequence_type& captures(int i)const + { + if(m_is_singular) + raise_logic_error(); + return (*this)[i].captures(); + } +#endif + + // + // private access functions: + void set_second(BidiIterator i) + { + BOOST_REGEX_ASSERT(m_subs.size() > 2); + m_subs[2].second = i; + m_subs[2].matched = true; + m_subs[0].first = i; + m_subs[0].matched = (m_subs[0].first != m_subs[0].second); + m_null.first = i; + m_null.second = i; + m_null.matched = false; + m_is_singular = false; + } + + void set_second(BidiIterator i, size_type pos, bool m = true, bool escape_k = false) + { + if(pos) + m_last_closed_paren = static_cast(pos); + pos += 2; + BOOST_REGEX_ASSERT(m_subs.size() > pos); + m_subs[pos].second = i; + m_subs[pos].matched = m; + if((pos == 2) && !escape_k) + { + m_subs[0].first = i; + m_subs[0].matched = (m_subs[0].first != m_subs[0].second); + m_null.first = i; + m_null.second = i; + m_null.matched = false; + m_is_singular = false; + } + } + void set_size(size_type n, BidiIterator i, BidiIterator j) + { + value_type v(j); + size_type len = m_subs.size(); + if(len > n + 2) + { + m_subs.erase(m_subs.begin()+n+2, m_subs.end()); + std::fill(m_subs.begin(), m_subs.end(), v); + } + else + { + std::fill(m_subs.begin(), m_subs.end(), v); + if(n+2 != len) + m_subs.insert(m_subs.end(), n+2-len, v); + } + m_subs[1].first = i; + m_last_closed_paren = 0; + } + void set_base(BidiIterator pos) + { + m_base = pos; + } + BidiIterator base()const + { + return m_base; + } + void set_first(BidiIterator i) + { + BOOST_REGEX_ASSERT(m_subs.size() > 2); + // set up prefix: + m_subs[1].second = i; + m_subs[1].matched = (m_subs[1].first != i); + // set up $0: + m_subs[2].first = i; + // zero out everything else: + for(size_type n = 3; n < m_subs.size(); ++n) + { + m_subs[n].first = m_subs[n].second = m_subs[0].second; + m_subs[n].matched = false; + } + } + void set_first(BidiIterator i, size_type pos, bool escape_k = false) + { + BOOST_REGEX_ASSERT(pos+2 < m_subs.size()); + if(pos || escape_k) + { + m_subs[pos+2].first = i; + if(escape_k) + { + m_subs[1].second = i; + m_subs[1].matched = (m_subs[1].first != m_subs[1].second); + } + } + else + set_first(i); + } + void maybe_assign(const match_results& m); + + void set_named_subs(std::shared_ptr subs) + { + m_named_subs = subs; + } + +private: + // + // Error handler called when an uninitialized match_results is accessed: + // + static void raise_logic_error() + { + std::logic_error e("Attempt to access an uninitialized boost::match_results<> class."); +#ifndef BOOST_REGEX_STANDALONE + boost::throw_exception(e); +#else + throw e; +#endif + } + + + vector_type m_subs; // subexpressions + BidiIterator m_base; // where the search started from + sub_match m_null; // a null match + std::shared_ptr m_named_subs; // Shared copy of named subs in the regex object + int m_last_closed_paren; // Last ) to be seen - used for formatting + bool m_is_singular; // True if our stored iterators are singular +}; + +template +void match_results::maybe_assign(const match_results& m) +{ + if(m_is_singular) + { + *this = m; + return; + } + const_iterator p1, p2; + p1 = begin(); + p2 = m.begin(); + // + // Distances are measured from the start of *this* match, unless this isn't + // a valid match in which case we use the start of the whole sequence. Note that + // no subsequent match-candidate can ever be to the left of the first match found. + // This ensures that when we are using bidirectional iterators, that distances + // measured are as short as possible, and therefore as efficient as possible + // to compute. Finally note that we don't use the "matched" data member to test + // whether a sub-expression is a valid match, because partial matches set this + // to false for sub-expression 0. + // + BidiIterator l_end = this->suffix().second; + BidiIterator l_base = (p1->first == l_end) ? this->prefix().first : (*this)[0].first; + difference_type len1 = 0; + difference_type len2 = 0; + difference_type base1 = 0; + difference_type base2 = 0; + std::size_t i; + for(i = 0; i < size(); ++i, ++p1, ++p2) + { + // + // Leftmost takes priority over longest; handle special cases + // where distances need not be computed first (an optimisation + // for bidirectional iterators: ensure that we don't accidently + // compute the length of the whole sequence, as this can be really + // expensive). + // + if(p1->first == l_end) + { + if(p2->first != l_end) + { + // p2 must be better than p1, and no need to calculate + // actual distances: + base1 = 1; + base2 = 0; + break; + } + else + { + // *p1 and *p2 are either unmatched or match end-of sequence, + // either way no need to calculate distances: + if((p1->matched == false) && (p2->matched == true)) + break; + if((p1->matched == true) && (p2->matched == false)) + return; + continue; + } + } + else if(p2->first == l_end) + { + // p1 better than p2, and no need to calculate distances: + return; + } + base1 = std::distance(l_base, p1->first); + base2 = std::distance(l_base, p2->first); + BOOST_REGEX_ASSERT(base1 >= 0); + BOOST_REGEX_ASSERT(base2 >= 0); + if(base1 < base2) return; + if(base2 < base1) break; + + len1 = std::distance((BidiIterator)p1->first, (BidiIterator)p1->second); + len2 = std::distance((BidiIterator)p2->first, (BidiIterator)p2->second); + BOOST_REGEX_ASSERT(len1 >= 0); + BOOST_REGEX_ASSERT(len2 >= 0); + if((len1 != len2) || ((p1->matched == false) && (p2->matched == true))) + break; + if((p1->matched == true) && (p2->matched == false)) + return; + } + if(i == size()) + return; + if(base2 < base1) + *this = m; + else if((len2 > len1) || ((p1->matched == false) && (p2->matched == true)) ) + *this = m; +} + +template +void swap(match_results& a, match_results& b) +{ + a.swap(b); +} + +template +std::basic_ostream& + operator << (std::basic_ostream& os, + const match_results& s) +{ + return (os << s.str()); +} + +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif +} // namespace boost + +#endif + + diff --git a/boost/regex/v5/mem_block_cache.hpp b/boost/regex/v5/mem_block_cache.hpp new file mode 100644 index 00000000..3e1216d0 --- /dev/null +++ b/boost/regex/v5/mem_block_cache.hpp @@ -0,0 +1,173 @@ + /* + * Copyright (c) 2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE mem_block_cache.hpp + * VERSION see + * DESCRIPTION: memory block cache used by the non-recursive matcher. + */ + +#ifndef BOOST_REGEX_V5_MEM_BLOCK_CACHE_HPP +#define BOOST_REGEX_V5_MEM_BLOCK_CACHE_HPP + +#include +#ifdef BOOST_HAS_THREADS +#include +#endif + +#ifndef BOOST_NO_CXX11_HDR_ATOMIC + #include + #if ATOMIC_POINTER_LOCK_FREE == 2 + #define BOOST_REGEX_MEM_BLOCK_CACHE_LOCK_FREE + #define BOOST_REGEX_ATOMIC_POINTER std::atomic + #endif +#endif + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +#if BOOST_REGEX_MAX_CACHE_BLOCKS != 0 +#ifdef BOOST_REGEX_MEM_BLOCK_CACHE_LOCK_FREE /* lock free implementation */ +struct mem_block_cache +{ + std::atomic cache[BOOST_REGEX_MAX_CACHE_BLOCKS]; + + ~mem_block_cache() + { + for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) { + if (cache[i].load()) ::operator delete(cache[i].load()); + } + } + void* get() + { + for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) { + void* p = cache[i].load(); + if (p != NULL) { + if (cache[i].compare_exchange_strong(p, NULL)) return p; + } + } + return ::operator new(BOOST_REGEX_BLOCKSIZE); + } + void put(void* ptr) + { + for (size_t i = 0;i < BOOST_REGEX_MAX_CACHE_BLOCKS; ++i) { + void* p = cache[i].load(); + if (p == NULL) { + if (cache[i].compare_exchange_strong(p, ptr)) return; + } + } + ::operator delete(ptr); + } + + static mem_block_cache& instance() + { + static mem_block_cache block_cache = { { {nullptr} } }; + return block_cache; + } +}; + + +#else /* lock-based implementation */ + + +struct mem_block_node +{ + mem_block_node* next; +}; + +struct mem_block_cache +{ + // this member has to be statically initialsed: + mem_block_node* next { nullptr }; + unsigned cached_blocks { 0 }; +#ifdef BOOST_HAS_THREADS + std::mutex mut; +#endif + + ~mem_block_cache() + { + while(next) + { + mem_block_node* old = next; + next = next->next; + ::operator delete(old); + } + } + void* get() + { +#ifdef BOOST_HAS_THREADS + std::lock_guard g(mut); +#endif + if(next) + { + mem_block_node* result = next; + next = next->next; + --cached_blocks; + return result; + } + return ::operator new(BOOST_REGEX_BLOCKSIZE); + } + void put(void* p) + { +#ifdef BOOST_HAS_THREADS + std::lock_guard g(mut); +#endif + if(cached_blocks >= BOOST_REGEX_MAX_CACHE_BLOCKS) + { + ::operator delete(p); + } + else + { + mem_block_node* old = static_cast(p); + old->next = next; + next = old; + ++cached_blocks; + } + } + static mem_block_cache& instance() + { + static mem_block_cache block_cache; + return block_cache; + } +}; +#endif +#endif + +#if BOOST_REGEX_MAX_CACHE_BLOCKS == 0 + +inline void* get_mem_block() +{ + return ::operator new(BOOST_REGEX_BLOCKSIZE); +} + +inline void put_mem_block(void* p) +{ + ::operator delete(p); +} + +#else + +inline void* get_mem_block() +{ + return mem_block_cache::instance().get(); +} + +inline void put_mem_block(void* p) +{ + mem_block_cache::instance().put(p); +} + +#endif +} +} // namespace boost + +#endif + diff --git a/boost/regex/v5/object_cache.hpp b/boost/regex/v5/object_cache.hpp new file mode 100644 index 00000000..6ebef9b3 --- /dev/null +++ b/boost/regex/v5/object_cache.hpp @@ -0,0 +1,160 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE object_cache.hpp + * VERSION see + * DESCRIPTION: Implements a generic object cache. + */ + +#ifndef BOOST_REGEX_OBJECT_CACHE_HPP +#define BOOST_REGEX_OBJECT_CACHE_HPP + +#include +#include +#include +#include +#include +#include +#ifdef BOOST_HAS_THREADS +#include +#endif + +namespace boost{ + +template +class object_cache +{ +public: + typedef std::pair< ::std::shared_ptr, Key const*> value_type; + typedef std::list list_type; + typedef typename list_type::iterator list_iterator; + typedef std::map map_type; + typedef typename map_type::iterator map_iterator; + typedef typename list_type::size_type size_type; + static std::shared_ptr get(const Key& k, size_type l_max_cache_size); + +private: + static std::shared_ptr do_get(const Key& k, size_type l_max_cache_size); + + struct data + { + list_type cont; + map_type index; + }; + + // Needed by compilers not implementing the resolution to DR45. For reference, + // see http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45. + friend struct data; +}; + +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable: 4702) +#endif +template +std::shared_ptr object_cache::get(const Key& k, size_type l_max_cache_size) +{ +#ifdef BOOST_HAS_THREADS + static std::mutex mut; + std::lock_guard l(mut); + return do_get(k, l_max_cache_size); +#else + return do_get(k, l_max_cache_size); +#endif +} +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif + +template +std::shared_ptr object_cache::do_get(const Key& k, size_type l_max_cache_size) +{ + typedef typename object_cache::data object_data; + typedef typename map_type::size_type map_size_type; + static object_data s_data; + + // + // see if the object is already in the cache: + // + map_iterator mpos = s_data.index.find(k); + if(mpos != s_data.index.end()) + { + // + // Eureka! + // We have a cached item, bump it up the list and return it: + // + if(--(s_data.cont.end()) != mpos->second) + { + // splice out the item we want to move: + list_type temp; + temp.splice(temp.end(), s_data.cont, mpos->second); + // and now place it at the end of the list: + s_data.cont.splice(s_data.cont.end(), temp, temp.begin()); + BOOST_REGEX_ASSERT(*(s_data.cont.back().second) == k); + // update index with new position: + mpos->second = --(s_data.cont.end()); + BOOST_REGEX_ASSERT(&(mpos->first) == mpos->second->second); + BOOST_REGEX_ASSERT(&(mpos->first) == s_data.cont.back().second); + } + return s_data.cont.back().first; + } + // + // if we get here then the item is not in the cache, + // so create it: + // + std::shared_ptr result(new Object(k)); + // + // Add it to the list, and index it: + // + s_data.cont.push_back(value_type(result, static_cast(0))); + s_data.index.insert(std::make_pair(k, --(s_data.cont.end()))); + s_data.cont.back().second = &(s_data.index.find(k)->first); + map_size_type s = s_data.index.size(); + BOOST_REGEX_ASSERT(s_data.index[k]->first.get() == result.get()); + BOOST_REGEX_ASSERT(&(s_data.index.find(k)->first) == s_data.cont.back().second); + BOOST_REGEX_ASSERT(s_data.index.find(k)->first == k); + if(s > l_max_cache_size) + { + // + // We have too many items in the list, so we need to start + // popping them off the back of the list, but only if they're + // being held uniquely by us: + // + list_iterator pos = s_data.cont.begin(); + list_iterator last = s_data.cont.end(); + while((pos != last) && (s > l_max_cache_size)) + { + if(pos->first.use_count() == 1) + { + list_iterator condemmed(pos); + ++pos; + // now remove the items from our containers, + // then order has to be as follows: + BOOST_REGEX_ASSERT(s_data.index.find(*(condemmed->second)) != s_data.index.end()); + s_data.index.erase(*(condemmed->second)); + s_data.cont.erase(condemmed); + --s; + } + else + ++pos; + } + BOOST_REGEX_ASSERT(s_data.index[k]->first.get() == result.get()); + BOOST_REGEX_ASSERT(&(s_data.index.find(k)->first) == s_data.cont.back().second); + BOOST_REGEX_ASSERT(s_data.index.find(k)->first == k); + } + return result; +} + +} + +#endif diff --git a/boost/regex/v5/pattern_except.hpp b/boost/regex/v5/pattern_except.hpp new file mode 100644 index 00000000..3fbdca0a --- /dev/null +++ b/boost/regex/v5/pattern_except.hpp @@ -0,0 +1,106 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE pattern_except.hpp + * VERSION see + * DESCRIPTION: Declares pattern-matching exception classes. + */ + +#ifndef BOOST_RE_V5_PAT_EXCEPT_HPP +#define BOOST_RE_V5_PAT_EXCEPT_HPP + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif + +#include +#include +#include +#include + +namespace boost{ + +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable : 4275) +#if BOOST_REGEX_MSVC >= 1800 +#pragma warning(disable : 26812 4459) +#endif +#endif +class regex_error : public std::runtime_error +{ +public: + explicit regex_error(const std::string& s, regex_constants::error_type err = regex_constants::error_unknown, std::ptrdiff_t pos = 0) + : std::runtime_error(s) + , m_error_code(err) + , m_position(pos) + { + } + explicit regex_error(regex_constants::error_type err) + : std::runtime_error(::boost::BOOST_REGEX_DETAIL_NS::get_default_error_string(err)) + , m_error_code(err) + , m_position(0) + { + } + ~regex_error() noexcept override {} + regex_constants::error_type code()const + { return m_error_code; } + std::ptrdiff_t position()const + { return m_position; } + void raise()const + { +#ifndef BOOST_NO_EXCEPTIONS +#ifndef BOOST_REGEX_STANDALONE + ::boost::throw_exception(*this); +#else + throw* this; +#endif +#endif + } +private: + regex_constants::error_type m_error_code; + std::ptrdiff_t m_position; +}; + +typedef regex_error bad_pattern; +typedef regex_error bad_expression; + +namespace BOOST_REGEX_DETAIL_NS{ + +template +inline void raise_runtime_error(const E& ex) +{ +#ifndef BOOST_REGEX_STANDALONE + ::boost::throw_exception(ex); +#else + throw ex; +#endif +} + +template +void raise_error(const traits& t, regex_constants::error_type code) +{ + (void)t; // warning suppression + regex_error e(t.error_string(code), code, 0); + ::boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(e); +} + +} + +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif + +} // namespace boost + +#endif diff --git a/boost/regex/v5/perl_matcher.hpp b/boost/regex/v5/perl_matcher.hpp new file mode 100644 index 00000000..deeffa58 --- /dev/null +++ b/boost/regex/v5/perl_matcher.hpp @@ -0,0 +1,576 @@ +/* + * + * Copyright (c) 2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + +#ifndef BOOST_REGEX_MATCHER_HPP +#define BOOST_REGEX_MATCHER_HPP + +#include + +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +#pragma warning(disable : 4251 4459) +#if BOOST_REGEX_MSVC < 1700 +# pragma warning(disable : 4231) +#endif +# if BOOST_REGEX_MSVC < 1600 +# pragma warning(disable : 4660) +# endif +#if BOOST_REGEX_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +// +// error checking API: +// +inline void verify_options(boost::regex_constants::syntax_option_type, match_flag_type mf) +{ + // + // can't mix match_extra with POSIX matching rules: + // + if ((mf & match_extra) && (mf & match_posix)) + { + std::logic_error msg("Usage Error: Can't mix regular expression captures with POSIX matching rules"); +#ifndef BOOST_REGEX_STANDALONE + throw_exception(msg); +#else + throw msg; +#endif + } +} +// +// function can_start: +// +template +inline bool can_start(charT c, const unsigned char* map, unsigned char mask) +{ + return ((c < static_cast(0)) ? true : ((c >= static_cast(1 << CHAR_BIT)) ? true : map[c] & mask)); +} +inline bool can_start(char c, const unsigned char* map, unsigned char mask) +{ + return map[(unsigned char)c] & mask; +} +inline bool can_start(signed char c, const unsigned char* map, unsigned char mask) +{ + return map[(unsigned char)c] & mask; +} +inline bool can_start(unsigned char c, const unsigned char* map, unsigned char mask) +{ + return map[c] & mask; +} +inline bool can_start(unsigned short c, const unsigned char* map, unsigned char mask) +{ + return ((c >= (1 << CHAR_BIT)) ? true : map[c] & mask); +} +#if defined(WCHAR_MIN) && (WCHAR_MIN == 0) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) +inline bool can_start(wchar_t c, const unsigned char* map, unsigned char mask) +{ + return ((c >= static_cast(1u << CHAR_BIT)) ? true : map[c] & mask); +} +#endif +#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) +inline bool can_start(unsigned int c, const unsigned char* map, unsigned char mask) +{ + return (((c >= static_cast(1u << CHAR_BIT)) ? true : map[c] & mask)); +} +#endif + +template +inline int string_compare(const std::basic_string& s, const C* p) +{ + if(0 == *p) + { + if(s.empty() || ((s.size() == 1) && (s[0] == 0))) + return 0; + } + return s.compare(p); +} +template +inline int string_compare(const Seq& s, const C* p) +{ + std::size_t i = 0; + while((i < s.size()) && (p[i] == s[i])) + { + ++i; + } + return (i == s.size()) ? -(int)p[i] : (int)s[i] - (int)p[i]; +} +# define STR_COMP(s,p) string_compare(s,p) + +template +inline const charT* re_skip_past_null(const charT* p) +{ + while (*p != static_cast(0)) ++p; + return ++p; +} + +template +iterator re_is_set_member(iterator next, + iterator last, + const re_set_long* set_, + const regex_data& e, bool icase) +{ + const charT* p = reinterpret_cast(set_+1); + iterator ptr; + unsigned int i; + //bool icase = e.m_flags & regex_constants::icase; + + if(next == last) return next; + + typedef typename traits_type::string_type traits_string_type; + const ::boost::regex_traits_wrapper& traits_inst = *(e.m_ptraits); + + // dwa 9/13/00 suppress incorrect MSVC warning - it claims this is never + // referenced + (void)traits_inst; + + // try and match a single character, could be a multi-character + // collating element... + for(i = 0; i < set_->csingles; ++i) + { + ptr = next; + if(*p == static_cast(0)) + { + // treat null string as special case: + if(traits_inst.translate(*ptr, icase)) + { + ++p; + continue; + } + return set_->isnot ? next : (ptr == next) ? ++next : ptr; + } + else + { + while(*p && (ptr != last)) + { + if(traits_inst.translate(*ptr, icase) != *p) + break; + ++p; + ++ptr; + } + + if(*p == static_cast(0)) // if null we've matched + return set_->isnot ? next : (ptr == next) ? ++next : ptr; + + p = re_skip_past_null(p); // skip null + } + } + + charT col = traits_inst.translate(*next, icase); + + + if(set_->cranges || set_->cequivalents) + { + traits_string_type s1; + // + // try and match a range, NB only a single character can match + if(set_->cranges) + { + if((e.m_flags & regex_constants::collate) == 0) + s1.assign(1, col); + else + { + charT a[2] = { col, charT(0), }; + s1 = traits_inst.transform(a, a + 1); + } + for(i = 0; i < set_->cranges; ++i) + { + if(STR_COMP(s1, p) >= 0) + { + do{ ++p; }while(*p); + ++p; + if(STR_COMP(s1, p) <= 0) + return set_->isnot ? next : ++next; + } + else + { + // skip first string + do{ ++p; }while(*p); + ++p; + } + // skip second string + do{ ++p; }while(*p); + ++p; + } + } + // + // try and match an equivalence class, NB only a single character can match + if(set_->cequivalents) + { + charT a[2] = { col, charT(0), }; + s1 = traits_inst.transform_primary(a, a +1); + for(i = 0; i < set_->cequivalents; ++i) + { + if(STR_COMP(s1, p) == 0) + return set_->isnot ? next : ++next; + // skip string + do{ ++p; }while(*p); + ++p; + } + } + } + if(traits_inst.isctype(col, set_->cclasses) == true) + return set_->isnot ? next : ++next; + if((set_->cnclasses != 0) && (traits_inst.isctype(col, set_->cnclasses) == false)) + return set_->isnot ? next : ++next; + return set_->isnot ? ++next : next; +} + +template +class repeater_count +{ + repeater_count** stack; + repeater_count* next; + int state_id; + std::size_t count; // the number of iterations so far + BidiIterator start_pos; // where the last repeat started + + repeater_count* unwind_until(int n, repeater_count* p, int current_recursion_id) + { + while(p && (p->state_id != n)) + { + if(-2 - current_recursion_id == p->state_id) + return 0; + p = p->next; + if(p && (p->state_id < 0)) + { + p = unwind_until(p->state_id, p, current_recursion_id); + if(!p) + return p; + p = p->next; + } + } + return p; + } +public: + repeater_count(repeater_count** s) : stack(s), next(0), state_id(-1), count(0), start_pos() {} + + repeater_count(int i, repeater_count** s, BidiIterator start, int current_recursion_id) + : start_pos(start) + { + state_id = i; + stack = s; + next = *stack; + *stack = this; + if((state_id > next->state_id) && (next->state_id >= 0)) + count = 0; + else + { + repeater_count* p = next; + p = unwind_until(state_id, p, current_recursion_id); + if(p) + { + count = p->count; + start_pos = p->start_pos; + } + else + count = 0; + } + } + ~repeater_count() + { + if(next) + *stack = next; + } + std::size_t get_count() { return count; } + int get_id() { return state_id; } + std::size_t operator++() { return ++count; } + bool check_null_repeat(const BidiIterator& pos, std::size_t max) + { + // this is called when we are about to start a new repeat, + // if the last one was NULL move our count to max, + // otherwise save the current position. + bool result = (count == 0) ? false : (pos == start_pos); + if(result) + count = max; + else + start_pos = pos; + return result; + } +}; + +struct saved_state; + +enum saved_state_type +{ + saved_type_end = 0, + saved_type_paren = 1, + saved_type_recurse = 2, + saved_type_assertion = 3, + saved_state_alt = 4, + saved_state_repeater_count = 5, + saved_state_extra_block = 6, + saved_state_greedy_single_repeat = 7, + saved_state_rep_slow_dot = 8, + saved_state_rep_fast_dot = 9, + saved_state_rep_char = 10, + saved_state_rep_short_set = 11, + saved_state_rep_long_set = 12, + saved_state_non_greedy_long_repeat = 13, + saved_state_count = 14 +}; + +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +#if BOOST_REGEX_MSVC >= 1800 +#pragma warning(disable:26495) +#endif +#endif +template +struct recursion_info +{ + typedef typename Results::value_type value_type; + typedef typename value_type::iterator iterator; + int idx; + const re_syntax_base* preturn_address; + Results results; + repeater_count* repeater_stack; + iterator location_of_start; +}; +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif + +template +class perl_matcher +{ +public: + typedef typename traits::char_type char_type; + typedef perl_matcher self_type; + typedef bool (self_type::*matcher_proc_type)(); + typedef std::size_t traits_size_type; + typedef typename is_byte::width_type width_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef match_results results_type; + + perl_matcher(BidiIterator first, BidiIterator end, + match_results& what, + const basic_regex& e, + match_flag_type f, + BidiIterator l_base) + : m_result(what), base(first), last(end), + position(first), backstop(l_base), re(e), traits_inst(e.get_traits()), + m_independent(false), next_count(&rep_obj), rep_obj(&next_count) + , m_recursions(0) + { + construct_init(e, f); + } + + bool match(); + bool find(); + + void setf(match_flag_type f) + { m_match_flags |= f; } + void unsetf(match_flag_type f) + { m_match_flags &= ~f; } + +private: + void construct_init(const basic_regex& e, match_flag_type f); + + bool find_imp(); + bool match_imp(); + void estimate_max_state_count(std::random_access_iterator_tag*); + void estimate_max_state_count(void*); + bool match_prefix(); + bool match_all_states(); + + // match procs, stored in s_match_vtable: + bool match_startmark(); + bool match_endmark(); + bool match_literal(); + bool match_start_line(); + bool match_end_line(); + bool match_wild(); + bool match_match(); + bool match_word_boundary(); + bool match_within_word(); + bool match_word_start(); + bool match_word_end(); + bool match_buffer_start(); + bool match_buffer_end(); + bool match_backref(); + bool match_long_set(); + bool match_set(); + bool match_jump(); + bool match_alt(); + bool match_rep(); + bool match_combining(); + bool match_soft_buffer_end(); + bool match_restart_continue(); + bool match_long_set_repeat(); + bool match_set_repeat(); + bool match_char_repeat(); + bool match_dot_repeat_fast(); + bool match_dot_repeat_slow(); + bool match_dot_repeat_dispatch() + { + return ::boost::is_random_access_iterator::value ? match_dot_repeat_fast() : match_dot_repeat_slow(); + } + bool match_backstep(); + bool match_assert_backref(); + bool match_toggle_case(); + bool match_recursion(); + bool match_fail(); + bool match_accept(); + bool match_commit(); + bool match_then(); + bool skip_until_paren(int index, bool match = true); + + // find procs stored in s_find_vtable: + bool find_restart_any(); + bool find_restart_word(); + bool find_restart_line(); + bool find_restart_buf(); + bool find_restart_lit(); + +private: + // final result structure to be filled in: + match_results& m_result; + // temporary result for POSIX matches: + std::unique_ptr > m_temp_match; + // pointer to actual result structure to fill in: + match_results* m_presult; + // start of sequence being searched: + BidiIterator base; + // end of sequence being searched: + BidiIterator last; + // current character being examined: + BidiIterator position; + // where to restart next search after failed match attempt: + BidiIterator restart; + // where the current search started from, acts as base for $` during grep: + BidiIterator search_base; + // how far we can go back when matching lookbehind: + BidiIterator backstop; + // the expression being examined: + const basic_regex& re; + // the expression's traits class: + const ::boost::regex_traits_wrapper& traits_inst; + // the next state in the machine being matched: + const re_syntax_base* pstate; + // matching flags in use: + match_flag_type m_match_flags; + // how many states we have examined so far: + std::ptrdiff_t state_count; + // max number of states to examine before giving up: + std::ptrdiff_t max_state_count; + // whether we should ignore case or not: + bool icase; + // set to true when (position == last), indicates that we may have a partial match: + bool m_has_partial_match; + // set to true whenever we get a match: + bool m_has_found_match; + // set to true whenever we're inside an independent sub-expression: + bool m_independent; + // the current repeat being examined: + repeater_count* next_count; + // the first repeat being examined (top of linked list): + repeater_count rep_obj; + // the mask to pass when matching word boundaries: + typename traits::char_class_type m_word_mask; + // the bitmask to use when determining whether a match_any matches a newline or not: + unsigned char match_any_mask; + // recursion information: + std::vector > recursion_stack; + // + // additional members for non-recursive version: + // + typedef bool (self_type::*unwind_proc_type)(bool); + + void extend_stack(); + bool unwind(bool); + bool unwind_end(bool); + bool unwind_paren(bool); + bool unwind_recursion_stopper(bool); + bool unwind_assertion(bool); + bool unwind_alt(bool); + bool unwind_repeater_counter(bool); + bool unwind_extra_block(bool); + bool unwind_greedy_single_repeat(bool); + bool unwind_slow_dot_repeat(bool); + bool unwind_fast_dot_repeat(bool); + bool unwind_char_repeat(bool); + bool unwind_short_set_repeat(bool); + bool unwind_long_set_repeat(bool); + bool unwind_non_greedy_repeat(bool); + bool unwind_recursion(bool); + bool unwind_recursion_pop(bool); + bool unwind_commit(bool); + bool unwind_then(bool); + bool unwind_case(bool); + void destroy_single_repeat(); + void push_matched_paren(int index, const sub_match& sub); + void push_recursion_stopper(); + void push_assertion(const re_syntax_base* ps, bool positive); + void push_alt(const re_syntax_base* ps); + void push_repeater_count(int i, repeater_count** s); + void push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id); + void push_non_greedy_repeat(const re_syntax_base* ps); + void push_recursion(int idx, const re_syntax_base* p, results_type* presults, results_type* presults2); + void push_recursion_pop(); + void push_case_change(bool); + + // pointer to base of stack: + saved_state* m_stack_base; + // pointer to current stack position: + saved_state* m_backup_state; + // how many memory blocks have we used up?: + unsigned used_block_count; + // determines what value to return when unwinding from recursion, + // allows for mixed recursive/non-recursive algorithm: + bool m_recursive_result; + // We have unwound to a lookahead/lookbehind, used by COMMIT/PRUNE/SKIP: + bool m_unwound_lookahead; + // We have unwound to an alternative, used by THEN: + bool m_unwound_alt; + // We are unwinding a commit - used by independent subs to determine whether to stop there or carry on unwinding: + //bool m_unwind_commit; + // Recursion limit: + unsigned m_recursions; + +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +#if BOOST_REGEX_MSVC >= 1800 +#pragma warning(disable:26495) +#endif +#endif + // these operations aren't allowed, so are declared private, + // bodies are provided to keep explicit-instantiation requests happy: + perl_matcher& operator=(const perl_matcher&) + { + return *this; + } + perl_matcher(const perl_matcher& that) + : m_result(that.m_result), re(that.re), traits_inst(that.traits_inst), rep_obj(0) {} +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif +}; + +} // namespace BOOST_REGEX_DETAIL_NS + +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif + +} // namespace boost + +// +// include the implementation of perl_matcher: +// +#include +// this one has to be last: +#include + +#endif diff --git a/boost/regex/v5/perl_matcher_common.hpp b/boost/regex/v5/perl_matcher_common.hpp new file mode 100644 index 00000000..dcce9e6a --- /dev/null +++ b/boost/regex/v5/perl_matcher_common.hpp @@ -0,0 +1,921 @@ +/* + * + * Copyright (c) 2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE perl_matcher_common.cpp + * VERSION see + * DESCRIPTION: Definitions of perl_matcher member functions that are + * common to both the recursive and non-recursive versions. + */ + +#ifndef BOOST_REGEX_V5_PERL_MATCHER_COMMON_HPP +#define BOOST_REGEX_V5_PERL_MATCHER_COMMON_HPP + +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +#pragma warning(disable:4459) +#if BOOST_REGEX_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +#pragma warning(disable:26812) +#endif + template +void perl_matcher::construct_init(const basic_regex& e, match_flag_type f) +{ + typedef typename std::iterator_traits::iterator_category category; + typedef typename basic_regex::flag_type expression_flag_type; + + if(e.empty()) + { + // precondition failure: e is not a valid regex. + std::invalid_argument ex("Invalid regular expression object"); +#ifndef BOOST_REGEX_STANDALONE + boost::throw_exception(ex); +#else + throw e; +#endif + } + pstate = 0; + m_match_flags = f; + estimate_max_state_count(static_cast(0)); + expression_flag_type re_f = re.flags(); + icase = re_f & regex_constants::icase; + if(!(m_match_flags & (match_perl|match_posix))) + { + if((re_f & (regbase::main_option_type|regbase::no_perl_ex)) == 0) + m_match_flags |= match_perl; + else if((re_f & (regbase::main_option_type|regbase::emacs_ex)) == (regbase::basic_syntax_group|regbase::emacs_ex)) + m_match_flags |= match_perl; + else if((re_f & (regbase::main_option_type|regbase::literal)) == (regbase::literal)) + m_match_flags |= match_perl; + else + m_match_flags |= match_posix; + } + if(m_match_flags & match_posix) + { + m_temp_match.reset(new match_results()); + m_presult = m_temp_match.get(); + } + else + m_presult = &m_result; + m_stack_base = 0; + m_backup_state = 0; + // find the value to use for matching word boundaries: + m_word_mask = re.get_data().m_word_mask; + // find bitmask to use for matching '.': + match_any_mask = static_cast((f & match_not_dot_newline) ? BOOST_REGEX_DETAIL_NS::test_not_newline : BOOST_REGEX_DETAIL_NS::test_newline); + // Disable match_any if requested in the state machine: + if(e.get_data().m_disable_match_any) + m_match_flags &= regex_constants::match_not_any; +} +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif + +template +void perl_matcher::estimate_max_state_count(std::random_access_iterator_tag*) +{ + // + // How many states should we allow our machine to visit before giving up? + // This is a heuristic: it takes the greater of O(N^2) and O(NS^2) + // where N is the length of the string, and S is the number of states + // in the machine. It's tempting to up this to O(N^2S) or even O(N^2S^2) + // but these take unreasonably amounts of time to bale out in pathological + // cases. + // + // Calculate NS^2 first: + // + static const std::ptrdiff_t k = 100000; + std::ptrdiff_t dist = std::distance(base, last); + if(dist == 0) + dist = 1; + std::ptrdiff_t states = re.size(); + if(states == 0) + states = 1; + if ((std::numeric_limits::max)() / states < states) + { + max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits::max)() - 2); + return; + } + states *= states; + if((std::numeric_limits::max)() / dist < states) + { + max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits::max)() - 2); + return; + } + states *= dist; + if((std::numeric_limits::max)() - k < states) + { + max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits::max)() - 2); + return; + } + states += k; + + max_state_count = states; + + // + // Now calculate N^2: + // + states = dist; + if((std::numeric_limits::max)() / dist < states) + { + max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits::max)() - 2); + return; + } + states *= dist; + if((std::numeric_limits::max)() - k < states) + { + max_state_count = (std::min)((std::ptrdiff_t)BOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits::max)() - 2); + return; + } + states += k; + // + // N^2 can be a very large number indeed, to prevent things getting out + // of control, cap the max states: + // + if(states > BOOST_REGEX_MAX_STATE_COUNT) + states = BOOST_REGEX_MAX_STATE_COUNT; + // + // If (the possibly capped) N^2 is larger than our first estimate, + // use this instead: + // + if(states > max_state_count) + max_state_count = states; +} + +template +inline void perl_matcher::estimate_max_state_count(void*) +{ + // we don't know how long the sequence is: + max_state_count = BOOST_REGEX_MAX_STATE_COUNT; +} + +template +inline bool perl_matcher::match() +{ + return match_imp(); +} + +template +bool perl_matcher::match_imp() +{ + // initialise our stack if we are non-recursive: + save_state_init init(&m_stack_base, &m_backup_state); + used_block_count = BOOST_REGEX_MAX_BLOCKS; +#if !defined(BOOST_NO_EXCEPTIONS) + try{ +#endif + + // reset our state machine: + position = base; + search_base = base; + state_count = 0; + m_match_flags |= regex_constants::match_all; + m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast(1u + re.mark_count()), search_base, last); + m_presult->set_base(base); + m_presult->set_named_subs(this->re.get_named_subs()); + if(m_match_flags & match_posix) + m_result = *m_presult; + verify_options(re.flags(), m_match_flags); + if(0 == match_prefix()) + return false; + return (m_result[0].second == last) && (m_result[0].first == base); + +#if !defined(BOOST_NO_EXCEPTIONS) + } + catch(...) + { + // unwind all pushed states, apart from anything else this + // ensures that all the states are correctly destructed + // not just the memory freed. + while(unwind(true)){} + throw; + } +#endif +} + +template +inline bool perl_matcher::find() +{ + return find_imp(); +} + +template +bool perl_matcher::find_imp() +{ + static matcher_proc_type const s_find_vtable[7] = + { + &perl_matcher::find_restart_any, + &perl_matcher::find_restart_word, + &perl_matcher::find_restart_line, + &perl_matcher::find_restart_buf, + &perl_matcher::match_prefix, + &perl_matcher::find_restart_lit, + &perl_matcher::find_restart_lit, + }; + + // initialise our stack if we are non-recursive: + save_state_init init(&m_stack_base, &m_backup_state); + used_block_count = BOOST_REGEX_MAX_BLOCKS; +#if !defined(BOOST_NO_EXCEPTIONS) + try{ +#endif + + state_count = 0; + if((m_match_flags & regex_constants::match_init) == 0) + { + // reset our state machine: + search_base = position = base; + pstate = re.get_first_state(); + m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast(1u + re.mark_count()), base, last); + m_presult->set_base(base); + m_presult->set_named_subs(this->re.get_named_subs()); + m_match_flags |= regex_constants::match_init; + } + else + { + // start again: + search_base = position = m_result[0].second; + // If last match was null and match_not_null was not set then increment + // our start position, otherwise we go into an infinite loop: + if(((m_match_flags & match_not_null) == 0) && (m_result.length() == 0)) + { + if(position == last) + return false; + else + ++position; + } + // reset $` start: + m_presult->set_size((m_match_flags & match_nosubs) ? 1u : static_cast(1u + re.mark_count()), search_base, last); + //if((base != search_base) && (base == backstop)) + // m_match_flags |= match_prev_avail; + } + if(m_match_flags & match_posix) + { + m_result.set_size(static_cast(1u + re.mark_count()), base, last); + m_result.set_base(base); + } + + verify_options(re.flags(), m_match_flags); + // find out what kind of expression we have: + unsigned type = (m_match_flags & match_continuous) ? + static_cast(regbase::restart_continue) + : static_cast(re.get_restart_type()); + + // call the appropriate search routine: + matcher_proc_type proc = s_find_vtable[type]; + return (this->*proc)(); + +#if !defined(BOOST_NO_EXCEPTIONS) + } + catch(...) + { + // unwind all pushed states, apart from anything else this + // ensures that all the states are correctly destructed + // not just the memory freed. + while(unwind(true)){} + throw; + } +#endif +} + +template +bool perl_matcher::match_prefix() +{ + m_has_partial_match = false; + m_has_found_match = false; + pstate = re.get_first_state(); + m_presult->set_first(position); + restart = position; + match_all_states(); + if(!m_has_found_match && m_has_partial_match && (m_match_flags & match_partial)) + { + m_has_found_match = true; + m_presult->set_second(last, 0, false); + position = last; + if((m_match_flags & match_posix) == match_posix) + { + m_result.maybe_assign(*m_presult); + } + } +#ifdef BOOST_REGEX_MATCH_EXTRA + if(m_has_found_match && (match_extra & m_match_flags)) + { + // + // we have a match, reverse the capture information: + // + for(unsigned i = 0; i < m_presult->size(); ++i) + { + typename sub_match::capture_sequence_type & seq = ((*m_presult)[i]).get_captures(); + std::reverse(seq.begin(), seq.end()); + } + } +#endif + if(!m_has_found_match) + position = restart; // reset search postion + return m_has_found_match; +} + +template +bool perl_matcher::match_literal() +{ + unsigned int len = static_cast(pstate)->length; + const char_type* what = reinterpret_cast(static_cast(pstate) + 1); + // + // compare string with what we stored in + // our records: + for(unsigned int i = 0; i < len; ++i, ++position) + { + if((position == last) || (traits_inst.translate(*position, icase) != what[i])) + return false; + } + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_start_line() +{ + if(position == backstop) + { + if((m_match_flags & match_prev_avail) == 0) + { + if((m_match_flags & match_not_bol) == 0) + { + pstate = pstate->next.p; + return true; + } + return false; + } + } + else if(m_match_flags & match_single_line) + return false; + + // check the previous value character: + BidiIterator t(position); + --t; + if(position != last) + { + if(is_separator(*t) && !((*t == static_cast('\r')) && (*position == static_cast('\n'))) ) + { + pstate = pstate->next.p; + return true; + } + } + else if(is_separator(*t)) + { + pstate = pstate->next.p; + return true; + } + return false; +} + +template +bool perl_matcher::match_end_line() +{ + if(position != last) + { + if(m_match_flags & match_single_line) + return false; + // we're not yet at the end so *first is always valid: + if(is_separator(*position)) + { + if((position != backstop) || (m_match_flags & match_prev_avail)) + { + // check that we're not in the middle of \r\n sequence + BidiIterator t(position); + --t; + if((*t == static_cast('\r')) && (*position == static_cast('\n'))) + { + return false; + } + } + pstate = pstate->next.p; + return true; + } + } + else if((m_match_flags & match_not_eol) == 0) + { + pstate = pstate->next.p; + return true; + } + return false; +} + +template +bool perl_matcher::match_wild() +{ + if(position == last) + return false; + if(is_separator(*position) && ((match_any_mask & static_cast(pstate)->mask) == 0)) + return false; + if((*position == char_type(0)) && (m_match_flags & match_not_dot_null)) + return false; + pstate = pstate->next.p; + ++position; + return true; +} + +template +bool perl_matcher::match_word_boundary() +{ + bool b; // indcates whether next character is a word character + if(position != last) + { + // prev and this character must be opposites: + b = traits_inst.isctype(*position, m_word_mask); + } + else + { + if (m_match_flags & match_not_eow) + return false; + b = false; + } + if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) + { + if(m_match_flags & match_not_bow) + return false; + else + b ^= false; + } + else + { + --position; + b ^= traits_inst.isctype(*position, m_word_mask); + ++position; + } + if(b) + { + pstate = pstate->next.p; + return true; + } + return false; // no match if we get to here... +} + +template +bool perl_matcher::match_within_word() +{ + bool b = !match_word_boundary(); + if(b) + pstate = pstate->next.p; + return b; + /* + if(position == last) + return false; + // both prev and this character must be m_word_mask: + bool prev = traits_inst.isctype(*position, m_word_mask); + { + bool b; + if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) + return false; + else + { + --position; + b = traits_inst.isctype(*position, m_word_mask); + ++position; + } + if(b == prev) + { + pstate = pstate->next.p; + return true; + } + } + return false; + */ +} + +template +bool perl_matcher::match_word_start() +{ + if(position == last) + return false; // can't be starting a word if we're already at the end of input + if(!traits_inst.isctype(*position, m_word_mask)) + return false; // next character isn't a word character + if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) + { + if(m_match_flags & match_not_bow) + return false; // no previous input + } + else + { + // otherwise inside buffer: + BidiIterator t(position); + --t; + if(traits_inst.isctype(*t, m_word_mask)) + return false; // previous character not non-word + } + // OK we have a match: + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_word_end() +{ + if((position == backstop) && ((m_match_flags & match_prev_avail) == 0)) + return false; // start of buffer can't be end of word + BidiIterator t(position); + --t; + if(traits_inst.isctype(*t, m_word_mask) == false) + return false; // previous character wasn't a word character + + if(position == last) + { + if(m_match_flags & match_not_eow) + return false; // end of buffer but not end of word + } + else + { + // otherwise inside buffer: + if(traits_inst.isctype(*position, m_word_mask)) + return false; // next character is a word character + } + pstate = pstate->next.p; + return true; // if we fall through to here then we've succeeded +} + +template +bool perl_matcher::match_buffer_start() +{ + if((position != backstop) || (m_match_flags & match_not_bob)) + return false; + // OK match: + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_buffer_end() +{ + if((position != last) || (m_match_flags & match_not_eob)) + return false; + // OK match: + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_backref() +{ + // + // Compare with what we previously matched. + // Note that this succeeds if the backref did not partisipate + // in the match, this is in line with ECMAScript, but not Perl + // or PCRE. + // + int index = static_cast(pstate)->index; + if(index >= hash_value_mask) + { + named_subexpressions::range_type r = re.get_data().equal_range(index); + BOOST_REGEX_ASSERT(r.first != r.second); + do + { + index = r.first->index; + ++r.first; + }while((r.first != r.second) && ((*m_presult)[index].matched != true)); + } + + if((m_match_flags & match_perl) && !(*m_presult)[index].matched) + return false; + + BidiIterator i = (*m_presult)[index].first; + BidiIterator j = (*m_presult)[index].second; + while(i != j) + { + if((position == last) || (traits_inst.translate(*position, icase) != traits_inst.translate(*i, icase))) + return false; + ++i; + ++position; + } + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_long_set() +{ + typedef typename traits::char_class_type char_class_type; + // let the traits class do the work: + if(position == last) + return false; + BidiIterator t = re_is_set_member(position, last, static_cast*>(pstate), re.get_data(), icase); + if(t != position) + { + pstate = pstate->next.p; + position = t; + return true; + } + return false; +} + +template +bool perl_matcher::match_set() +{ + if(position == last) + return false; + if(static_cast(pstate)->_map[static_cast(traits_inst.translate(*position, icase))]) + { + pstate = pstate->next.p; + ++position; + return true; + } + return false; +} + +template +bool perl_matcher::match_jump() +{ + pstate = static_cast(pstate)->alt.p; + return true; +} + +template +bool perl_matcher::match_combining() +{ + if(position == last) + return false; + if(is_combining(traits_inst.translate(*position, icase))) + return false; + ++position; + while((position != last) && is_combining(traits_inst.translate(*position, icase))) + ++position; + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_soft_buffer_end() +{ + if(m_match_flags & match_not_eob) + return false; + BidiIterator p(position); + while((p != last) && is_separator(traits_inst.translate(*p, icase)))++p; + if(p != last) + return false; + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_restart_continue() +{ + if(position == search_base) + { + pstate = pstate->next.p; + return true; + } + return false; +} + +template +bool perl_matcher::match_backstep() +{ +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + if( ::boost::is_random_access_iterator::value) + { + std::ptrdiff_t maxlen = std::distance(backstop, position); + if(maxlen < static_cast(pstate)->index) + return false; + std::advance(position, -static_cast(pstate)->index); + } + else + { + int c = static_cast(pstate)->index; + while(c--) + { + if(position == backstop) + return false; + --position; + } + } + pstate = pstate->next.p; + return true; +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif +} + +template +inline bool perl_matcher::match_assert_backref() +{ + // return true if marked sub-expression N has been matched: + int index = static_cast(pstate)->index; + bool result = false; + if(index == 9999) + { + // Magic value for a (DEFINE) block: + return false; + } + else if(index > 0) + { + // Have we matched subexpression "index"? + // Check if index is a hash value: + if(index >= hash_value_mask) + { + named_subexpressions::range_type r = re.get_data().equal_range(index); + while(r.first != r.second) + { + if((*m_presult)[r.first->index].matched) + { + result = true; + break; + } + ++r.first; + } + } + else + { + result = (*m_presult)[index].matched; + } + pstate = pstate->next.p; + } + else + { + // Have we recursed into subexpression "index"? + // If index == 0 then check for any recursion at all, otherwise for recursion to -index-1. + int idx = -(index+1); + if(idx >= hash_value_mask) + { + named_subexpressions::range_type r = re.get_data().equal_range(idx); + int stack_index = recursion_stack.empty() ? -1 : recursion_stack.back().idx; + while(r.first != r.second) + { + result |= (stack_index == r.first->index); + if(result)break; + ++r.first; + } + } + else + { + result = !recursion_stack.empty() && ((recursion_stack.back().idx == idx) || (index == 0)); + } + pstate = pstate->next.p; + } + return result; +} + +template +bool perl_matcher::match_fail() +{ + // Just force a backtrack: + return false; +} + +template +bool perl_matcher::match_accept() +{ + if(!recursion_stack.empty()) + { + return skip_until_paren(recursion_stack.back().idx); + } + else + { + return skip_until_paren(INT_MAX); + } +} + +template +bool perl_matcher::find_restart_any() +{ +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + const unsigned char* _map = re.get_map(); + while(true) + { + // skip everything we can't match: + while((position != last) && !can_start(*position, _map, (unsigned char)mask_any) ) + ++position; + if(position == last) + { + // run out of characters, try a null match if possible: + if(re.can_be_null()) + return match_prefix(); + break; + } + // now try and obtain a match: + if(match_prefix()) + return true; + if(position == last) + return false; + ++position; + } + return false; +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::find_restart_word() +{ +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif + // do search optimised for word starts: + const unsigned char* _map = re.get_map(); + if((m_match_flags & match_prev_avail) || (position != base)) + --position; + else if(match_prefix()) + return true; + do + { + while((position != last) && traits_inst.isctype(*position, m_word_mask)) + ++position; + while((position != last) && !traits_inst.isctype(*position, m_word_mask)) + ++position; + if(position == last) + break; + + if(can_start(*position, _map, (unsigned char)mask_any) ) + { + if(match_prefix()) + return true; + } + if(position == last) + break; + } while(true); + return false; +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::find_restart_line() +{ + // do search optimised for line starts: + const unsigned char* _map = re.get_map(); + if(match_prefix()) + return true; + while(position != last) + { + while((position != last) && !is_separator(*position)) + ++position; + if(position == last) + return false; + ++position; + if(position == last) + { + if(re.can_be_null() && match_prefix()) + return true; + return false; + } + + if( can_start(*position, _map, (unsigned char)mask_any) ) + { + if(match_prefix()) + return true; + } + if(position == last) + return false; + //++position; + } + return false; +} + +template +bool perl_matcher::find_restart_buf() +{ + if((position == base) && ((m_match_flags & match_not_bob) == 0)) + return match_prefix(); + return false; +} + +template +bool perl_matcher::find_restart_lit() +{ + return false; +} + +} // namespace BOOST_REGEX_DETAIL_NS + +} // namespace boost + +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif + +#endif + diff --git a/boost/regex/v5/perl_matcher_non_recursive.hpp b/boost/regex/v5/perl_matcher_non_recursive.hpp new file mode 100644 index 00000000..28d6c462 --- /dev/null +++ b/boost/regex/v5/perl_matcher_non_recursive.hpp @@ -0,0 +1,1874 @@ +/* + * + * Copyright (c) 2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE perl_matcher_common.cpp + * VERSION see + * DESCRIPTION: Definitions of perl_matcher member functions that are + * specific to the non-recursive implementation. + */ + +#ifndef BOOST_REGEX_V5_PERL_MATCHER_NON_RECURSIVE_HPP +#define BOOST_REGEX_V5_PERL_MATCHER_NON_RECURSIVE_HPP + +#include + +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +# pragma warning(disable: 4706 4459) +#if BOOST_REGEX_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +template +inline void inplace_destroy(T* p) +{ + (void)p; // warning suppression + p->~T(); +} + +struct saved_state +{ + union{ + unsigned int state_id; + // this padding ensures correct alignment on 64-bit platforms: + std::size_t padding1; + std::ptrdiff_t padding2; + void* padding3; + }; + saved_state(unsigned i) : state_id(i) {} +}; + +template +struct saved_matched_paren : public saved_state +{ + int index; + sub_match sub; + saved_matched_paren(int i, const sub_match& s) : saved_state(1), index(i), sub(s){} +}; + +template +struct saved_position : public saved_state +{ + const re_syntax_base* pstate; + BidiIterator position; + saved_position(const re_syntax_base* ps, BidiIterator pos, int i) : saved_state(i), pstate(ps), position(pos){} +}; + +template +struct saved_assertion : public saved_position +{ + bool positive; + saved_assertion(bool p, const re_syntax_base* ps, BidiIterator pos) + : saved_position(ps, pos, saved_type_assertion), positive(p){} +}; + +template +struct saved_repeater : public saved_state +{ + repeater_count count; + saved_repeater(int i, repeater_count** s, BidiIterator start, int current_recursion_id) + : saved_state(saved_state_repeater_count), count(i, s, start, current_recursion_id){} +}; + +struct saved_extra_block : public saved_state +{ + saved_state *base, *end; + saved_extra_block(saved_state* b, saved_state* e) + : saved_state(saved_state_extra_block), base(b), end(e) {} +}; + +struct save_state_init +{ + saved_state** stack; + save_state_init(saved_state** base, saved_state** end) + : stack(base) + { + *base = static_cast(get_mem_block()); + *end = reinterpret_cast(reinterpret_cast(*base)+BOOST_REGEX_BLOCKSIZE); + --(*end); + (void) new (*end)saved_state(0); + BOOST_REGEX_ASSERT(*end > *base); + } + ~save_state_init() + { + put_mem_block(*stack); + *stack = 0; + } +}; + +template +struct saved_single_repeat : public saved_state +{ + std::size_t count; + const re_repeat* rep; + BidiIterator last_position; + saved_single_repeat(std::size_t c, const re_repeat* r, BidiIterator lp, int arg_id) + : saved_state(arg_id), count(c), rep(r), last_position(lp){} +}; + +template +struct saved_recursion : public saved_state +{ + saved_recursion(int idx, const re_syntax_base* p, Results* pr, Results* pr2) + : saved_state(14), recursion_id(idx), preturn_address(p), internal_results(*pr), prior_results(*pr2) {} + int recursion_id; + const re_syntax_base* preturn_address; + Results internal_results, prior_results; +}; + +struct saved_change_case : public saved_state +{ + bool icase; + saved_change_case(bool c) : saved_state(18), icase(c) {} +}; + +struct incrementer +{ + incrementer(unsigned* pu) : m_pu(pu) { ++*m_pu; } + ~incrementer() { --*m_pu; } + bool operator > (unsigned i) { return *m_pu > i; } +private: + unsigned* m_pu; +}; + +template +bool perl_matcher::match_all_states() +{ + static matcher_proc_type const s_match_vtable[34] = + { + (&perl_matcher::match_startmark), + &perl_matcher::match_endmark, + &perl_matcher::match_literal, + &perl_matcher::match_start_line, + &perl_matcher::match_end_line, + &perl_matcher::match_wild, + &perl_matcher::match_match, + &perl_matcher::match_word_boundary, + &perl_matcher::match_within_word, + &perl_matcher::match_word_start, + &perl_matcher::match_word_end, + &perl_matcher::match_buffer_start, + &perl_matcher::match_buffer_end, + &perl_matcher::match_backref, + &perl_matcher::match_long_set, + &perl_matcher::match_set, + &perl_matcher::match_jump, + &perl_matcher::match_alt, + &perl_matcher::match_rep, + &perl_matcher::match_combining, + &perl_matcher::match_soft_buffer_end, + &perl_matcher::match_restart_continue, + // Although this next line *should* be evaluated at compile time, in practice + // some compilers (VC++) emit run-time initialisation which breaks thread + // safety, so use a dispatch function instead: + //(::boost::is_random_access_iterator::value ? &perl_matcher::match_dot_repeat_fast : &perl_matcher::match_dot_repeat_slow), + &perl_matcher::match_dot_repeat_dispatch, + &perl_matcher::match_char_repeat, + &perl_matcher::match_set_repeat, + &perl_matcher::match_long_set_repeat, + &perl_matcher::match_backstep, + &perl_matcher::match_assert_backref, + &perl_matcher::match_toggle_case, + &perl_matcher::match_recursion, + &perl_matcher::match_fail, + &perl_matcher::match_accept, + &perl_matcher::match_commit, + &perl_matcher::match_then, + }; + incrementer inc(&m_recursions); + if(inc > 80) + raise_error(traits_inst, regex_constants::error_complexity); + push_recursion_stopper(); + do{ + while(pstate) + { + matcher_proc_type proc = s_match_vtable[pstate->type]; + ++state_count; + if(!(this->*proc)()) + { + if(state_count > max_state_count) + raise_error(traits_inst, regex_constants::error_complexity); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + bool successful_unwind = unwind(false); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(!successful_unwind) + return m_recursive_result; + } + } + }while(unwind(true)); + return m_recursive_result; +} + +template +void perl_matcher::extend_stack() +{ + if(used_block_count) + { + --used_block_count; + saved_state* stack_base; + saved_state* backup_state; + stack_base = static_cast(get_mem_block()); + backup_state = reinterpret_cast(reinterpret_cast(stack_base)+BOOST_REGEX_BLOCKSIZE); + saved_extra_block* block = static_cast(backup_state); + --block; + (void) new (block) saved_extra_block(m_stack_base, m_backup_state); + m_stack_base = stack_base; + m_backup_state = block; + } + else + raise_error(traits_inst, regex_constants::error_stack); +} + +template +inline void perl_matcher::push_matched_paren(int index, const sub_match& sub) +{ + //BOOST_REGEX_ASSERT(index); + saved_matched_paren* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_matched_paren(index, sub); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_case_change(bool c) +{ + //BOOST_REGEX_ASSERT(index); + saved_change_case* pmp = static_cast(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast(m_backup_state); + --pmp; + } + (void) new (pmp)saved_change_case(c); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_recursion_stopper() +{ + saved_state* pmp = m_backup_state; + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = m_backup_state; + --pmp; + } + (void) new (pmp)saved_state(saved_type_recurse); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_assertion(const re_syntax_base* ps, bool positive) +{ + saved_assertion* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_assertion(positive, ps, position); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_alt(const re_syntax_base* ps) +{ + saved_position* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_position(ps, position, saved_state_alt); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_non_greedy_repeat(const re_syntax_base* ps) +{ + saved_position* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_position(ps, position, saved_state_non_greedy_long_repeat); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_repeater_count(int i, repeater_count** s) +{ + saved_repeater* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_repeater(i, s, position, this->recursion_stack.empty() ? (INT_MIN + 3) : this->recursion_stack.back().idx); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id) +{ + saved_single_repeat* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_single_repeat(c, r, last_position, state_id); + m_backup_state = pmp; +} + +template +inline void perl_matcher::push_recursion(int idx, const re_syntax_base* p, results_type* presults, results_type* presults2) +{ + saved_recursion* pmp = static_cast*>(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast*>(m_backup_state); + --pmp; + } + (void) new (pmp)saved_recursion(idx, p, presults, presults2); + m_backup_state = pmp; +} + +template +bool perl_matcher::match_toggle_case() +{ + // change our case sensitivity: + push_case_change(this->icase); + this->icase = static_cast(pstate)->icase; + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_startmark() +{ + int index = static_cast(pstate)->index; + icase = static_cast(pstate)->icase; + switch(index) + { + case 0: + pstate = pstate->next.p; + break; + case -1: + case -2: + { + // forward lookahead assert: + const re_syntax_base* next_pstate = static_cast(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; + push_assertion(next_pstate, index == -1); + break; + } + case -3: + { + // independent sub-expression, currently this is always recursive: + bool old_independent = m_independent; + m_independent = true; + const re_syntax_base* next_pstate = static_cast(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; + bool r = false; +#if !defined(BOOST_NO_EXCEPTIONS) + try{ +#endif + r = match_all_states(); + if(!r && !m_independent) + { + // Must be unwinding from a COMMIT/SKIP/PRUNE and the independent + // sub failed, need to unwind everything else: + while (m_backup_state->state_id) + unwind(false); + return false; + } +#if !defined(BOOST_NO_EXCEPTIONS) + } + catch(...) + { + pstate = next_pstate; + // unwind all pushed states, apart from anything else this + // ensures that all the states are correctly destructed + // not just the memory freed. + while(unwind(true)) {} + throw; + } +#endif + pstate = next_pstate; + m_independent = old_independent; +#ifdef BOOST_REGEX_MATCH_EXTRA + if(r && (m_match_flags & match_extra)) + { + // + // our captures have been stored in *m_presult + // we need to unpack them, and insert them + // back in the right order when we unwind the stack: + // + match_results temp_match(*m_presult); + unsigned i; + for(i = 0; i < temp_match.size(); ++i) + (*m_presult)[i].get_captures().clear(); + // match everything else: +#if !defined(BOOST_NO_EXCEPTIONS) + try{ +#endif + r = match_all_states(); +#if !defined(BOOST_NO_EXCEPTIONS) + } + catch(...) + { + pstate = next_pstate; + // unwind all pushed states, apart from anything else this + // ensures that all the states are correctly destructed + // not just the memory freed. + while(unwind(true)) {} + throw; + } +#endif + // now place the stored captures back: + for(i = 0; i < temp_match.size(); ++i) + { + typedef typename sub_match::capture_sequence_type seq; + seq& s1 = (*m_presult)[i].get_captures(); + const seq& s2 = temp_match[i].captures(); + s1.insert( + s1.end(), + s2.begin(), + s2.end()); + } + } +#endif + return r; + } + case -4: + { + // conditional expression: + const re_alt* alt = static_cast(pstate->next.p); + BOOST_REGEX_ASSERT(alt->type == syntax_element_alt); + pstate = alt->next.p; + if(pstate->type == syntax_element_assert_backref) + { + if(!match_assert_backref()) + pstate = alt->alt.p; + break; + } + else + { + // zero width assertion, have to match this recursively: + BOOST_REGEX_ASSERT(pstate->type == syntax_element_startmark); + bool negated = static_cast(pstate)->index == -2; + BidiIterator saved_position = position; + const re_syntax_base* next_pstate = static_cast(pstate->next.p)->alt.p->next.p; + pstate = pstate->next.p->next.p; +#if !defined(BOOST_NO_EXCEPTIONS) + try{ +#endif + bool r = match_all_states(); + position = saved_position; + if(negated) + r = !r; + if(r) + pstate = next_pstate; + else + pstate = alt->alt.p; +#if !defined(BOOST_NO_EXCEPTIONS) + } + catch(...) + { + pstate = next_pstate; + // unwind all pushed states, apart from anything else this + // ensures that all the states are correctly destructed + // not just the memory freed. + while(unwind(true)){} + throw; + } +#endif + break; + } + } + case -5: + { + push_matched_paren(0, (*m_presult)[0]); + m_presult->set_first(position, 0, true); + pstate = pstate->next.p; + break; + } + default: + { + BOOST_REGEX_ASSERT(index > 0); + if((m_match_flags & match_nosubs) == 0) + { + push_matched_paren(index, (*m_presult)[index]); + m_presult->set_first(position, index); + } + pstate = pstate->next.p; + break; + } + } + return true; +} + +template +bool perl_matcher::match_alt() +{ + bool take_first, take_second; + const re_alt* jmp = static_cast(pstate); + + // find out which of these two alternatives we need to take: + if(position == last) + { + take_first = jmp->can_be_null & mask_take; + take_second = jmp->can_be_null & mask_skip; + } + else + { + take_first = can_start(*position, jmp->_map, (unsigned char)mask_take); + take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip); + } + + if(take_first) + { + // we can take the first alternative, + // see if we need to push next alternative: + if(take_second) + { + push_alt(jmp->alt.p); + } + pstate = pstate->next.p; + return true; + } + if(take_second) + { + pstate = jmp->alt.p; + return true; + } + return false; // neither option is possible +} + +template +bool perl_matcher::match_rep() +{ +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4127 4244) +#endif +#ifdef BOOST_BORLANDC +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + const re_repeat* rep = static_cast(pstate); + + // find out which of these two alternatives we need to take: + bool take_first, take_second; + if(position == last) + { + take_first = rep->can_be_null & mask_take; + take_second = rep->can_be_null & mask_skip; + } + else + { + take_first = can_start(*position, rep->_map, (unsigned char)mask_take); + take_second = can_start(*position, rep->_map, (unsigned char)mask_skip); + } + + if((m_backup_state->state_id != saved_state_repeater_count) + || (static_cast*>(m_backup_state)->count.get_id() != rep->state_id) + || (next_count->get_id() != rep->state_id)) + { + // we're moving to a different repeat from the last + // one, so set up a counter object: + push_repeater_count(rep->state_id, &next_count); + } + // + // If we've had at least one repeat already, and the last one + // matched the NULL string then set the repeat count to + // maximum: + // + next_count->check_null_repeat(position, rep->max); + + if(next_count->get_count() < rep->min) + { + // we must take the repeat: + if(take_first) + { + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + return true; + } + return false; + } + + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + if(greedy) + { + // try and take the repeat if we can: + if((next_count->get_count() < rep->max) && take_first) + { + if(take_second) + { + // store position in case we fail: + push_alt(rep->alt.p); + } + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + return true; + } + else if(take_second) + { + pstate = rep->alt.p; + return true; + } + return false; // can't take anything, fail... + } + else // non-greedy + { + // try and skip the repeat if we can: + if(take_second) + { + if((next_count->get_count() < rep->max) && take_first) + { + // store position in case we fail: + push_non_greedy_repeat(rep->next.p); + } + pstate = rep->alt.p; + return true; + } + if((next_count->get_count() < rep->max) && take_first) + { + // increase the counter: + ++(*next_count); + pstate = rep->next.p; + return true; + } + } + return false; +#ifdef BOOST_BORLANDC +#pragma option pop +#endif +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_dot_repeat_slow() +{ + std::size_t count = 0; + const re_repeat* rep = static_cast(pstate); + re_syntax_base* psingle = rep->next.p; + // match compulsory repeats first: + while(count < rep->min) + { + pstate = psingle; + if(!match_wild()) + return false; + ++count; + } + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + if(greedy) + { + // repeat for as long as we can: + while(count < rep->max) + { + pstate = psingle; + if(!match_wild()) + break; + ++count; + } + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_slow_dot); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +} + +template +bool perl_matcher::match_dot_repeat_fast() +{ + if(m_match_flags & match_not_dot_null) + return match_dot_repeat_slow(); + if((static_cast(pstate->next.p)->mask & match_any_mask) == 0) + return match_dot_repeat_slow(); + + const re_repeat* rep = static_cast(pstate); + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t count = static_cast((std::min)(static_cast(std::distance(position, last)), greedy ? rep->max : rep->min)); + if(rep->min > count) + { + position = last; + return false; // not enough text left to match + } + std::advance(position, count); + + if(greedy) + { + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_fast_dot); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +} + +template +bool perl_matcher::match_char_repeat() +{ +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif +#ifdef BOOST_BORLANDC +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + const re_repeat* rep = static_cast(pstate); + BOOST_REGEX_ASSERT(1 == static_cast(rep->next.p)->length); + const char_type what = *reinterpret_cast(static_cast(rep->next.p) + 1); + std::size_t count = 0; + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t desired = greedy ? rep->max : rep->min; + if(::boost::is_random_access_iterator::value) + { + BidiIterator end = position; + // Move end forward by "desired", preferably without using distance or advance if we can + // as these can be slow for some iterator types. + std::size_t len = (desired == (std::numeric_limits::max)()) ? 0u : std::distance(position, last); + if(desired >= len) + end = last; + else + std::advance(end, desired); + BidiIterator origin(position); + while((position != end) && (traits_inst.translate(*position, icase) == what)) + { + ++position; + } + count = (unsigned)std::distance(origin, position); + } + else + { + while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what)) + { + ++position; + ++count; + } + } + + if(count < rep->min) + return false; + + if(greedy) + { + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_char); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +#ifdef BOOST_BORLANDC +#pragma option pop +#endif +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_set_repeat() +{ +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif +#ifdef BOOST_BORLANDC +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + const re_repeat* rep = static_cast(pstate); + const unsigned char* map = static_cast(rep->next.p)->_map; + std::size_t count = 0; + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t desired = greedy ? rep->max : rep->min; + if(::boost::is_random_access_iterator::value) + { + BidiIterator end = position; + // Move end forward by "desired", preferably without using distance or advance if we can + // as these can be slow for some iterator types. + std::size_t len = (desired == (std::numeric_limits::max)()) ? 0u : std::distance(position, last); + if(desired >= len) + end = last; + else + std::advance(end, desired); + BidiIterator origin(position); + while((position != end) && map[static_cast(traits_inst.translate(*position, icase))]) + { + ++position; + } + count = (unsigned)std::distance(origin, position); + } + else + { + while((count < desired) && (position != last) && map[static_cast(traits_inst.translate(*position, icase))]) + { + ++position; + ++count; + } + } + + if(count < rep->min) + return false; + + if(greedy) + { + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_short_set); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +#ifdef BOOST_BORLANDC +#pragma option pop +#endif +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_long_set_repeat() +{ +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4127) +#endif +#ifdef BOOST_BORLANDC +#pragma option push -w-8008 -w-8066 -w-8004 +#endif + typedef typename traits::char_class_type m_type; + const re_repeat* rep = static_cast(pstate); + const re_set_long* set = static_cast*>(pstate->next.p); + std::size_t count = 0; + // + // start by working out how much we can skip: + // + bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent); + std::size_t desired = greedy ? rep->max : rep->min; + if(::boost::is_random_access_iterator::value) + { + BidiIterator end = position; + // Move end forward by "desired", preferably without using distance or advance if we can + // as these can be slow for some iterator types. + std::size_t len = (desired == (std::numeric_limits::max)()) ? 0u : std::distance(position, last); + if(desired >= len) + end = last; + else + std::advance(end, desired); + BidiIterator origin(position); + while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase))) + { + ++position; + } + count = (unsigned)std::distance(origin, position); + } + else + { + while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase))) + { + ++position; + ++count; + } + } + + if(count < rep->min) + return false; + + if(greedy) + { + if((rep->leading) && (count < rep->max)) + restart = position; + // push backtrack info if available: + if(count - rep->min) + push_single_repeat(count, rep, position, saved_state_greedy_single_repeat); + // jump to next state: + pstate = rep->alt.p; + return true; + } + else + { + // non-greedy, push state and return true if we can skip: + if(count < rep->max) + push_single_repeat(count, rep, position, saved_state_rep_long_set); + pstate = rep->alt.p; + return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip); + } +#ifdef BOOST_BORLANDC +#pragma option pop +#endif +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif +} + +template +bool perl_matcher::match_recursion() +{ + BOOST_REGEX_ASSERT(pstate->type == syntax_element_recurse); + // + // See if we've seen this recursion before at this location, if we have then + // we need to prevent infinite recursion: + // + for(typename std::vector >::reverse_iterator i = recursion_stack.rbegin(); i != recursion_stack.rend(); ++i) + { + if(i->idx == static_cast(static_cast(pstate)->alt.p)->index) + { + if(i->location_of_start == position) + return false; + break; + } + } + // + // Backup call stack: + // + push_recursion_pop(); + // + // Set new call stack: + // + if(recursion_stack.capacity() == 0) + { + recursion_stack.reserve(50); + } + recursion_stack.push_back(recursion_info()); + recursion_stack.back().preturn_address = pstate->next.p; + recursion_stack.back().results = *m_presult; + pstate = static_cast(pstate)->alt.p; + recursion_stack.back().idx = static_cast(pstate)->index; + recursion_stack.back().location_of_start = position; + //if(static_cast(pstate)->state_id > 0) + { + push_repeater_count(-(2 + static_cast(pstate)->index), &next_count); + } + + return true; +} + +template +bool perl_matcher::match_endmark() +{ + int index = static_cast(pstate)->index; + icase = static_cast(pstate)->icase; + if(index > 0) + { + if((m_match_flags & match_nosubs) == 0) + { + m_presult->set_second(position, index); + } + if(!recursion_stack.empty()) + { + if(index == recursion_stack.back().idx) + { + pstate = recursion_stack.back().preturn_address; + *m_presult = recursion_stack.back().results; + push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, m_presult, &recursion_stack.back().results); + recursion_stack.pop_back(); + push_repeater_count(-(2 + index), &next_count); + } + } + } + else if((index < 0) && (index != -4)) + { + // matched forward lookahead: + pstate = 0; + return true; + } + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_match() +{ + if(!recursion_stack.empty()) + { + BOOST_REGEX_ASSERT(0 == recursion_stack.back().idx); + pstate = recursion_stack.back().preturn_address; + push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, m_presult, &recursion_stack.back().results); + *m_presult = recursion_stack.back().results; + recursion_stack.pop_back(); + return true; + } + if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first)) + return false; + if((m_match_flags & match_all) && (position != last)) + return false; + if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base)) + return false; + m_presult->set_second(position); + pstate = 0; + m_has_found_match = true; + if((m_match_flags & match_posix) == match_posix) + { + m_result.maybe_assign(*m_presult); + if((m_match_flags & match_any) == 0) + return false; + } +#ifdef BOOST_REGEX_MATCH_EXTRA + if(match_extra & m_match_flags) + { + for(unsigned i = 0; i < m_presult->size(); ++i) + if((*m_presult)[i].matched) + ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]); + } +#endif + return true; +} + +template +bool perl_matcher::match_commit() +{ + // Ideally we would just junk all the states that are on the stack, + // however we might not unwind correctly in that case, so for now, + // just mark that we don't backtrack into whatever is left (or rather + // we'll unwind it unconditionally without pausing to try other matches). + + switch(static_cast(pstate)->action) + { + case commit_commit: + restart = last; + break; + case commit_skip: + if(base != position) + { + restart = position; + // Have to decrement restart since it will get incremented again later: + --restart; + } + break; + case commit_prune: + break; + } + + saved_state* pmp = m_backup_state; + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = m_backup_state; + --pmp; + } + (void) new (pmp)saved_state(16); + m_backup_state = pmp; + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::match_then() +{ + // Just leave a mark that we need to skip to next alternative: + saved_state* pmp = m_backup_state; + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = m_backup_state; + --pmp; + } + (void) new (pmp)saved_state(17); + m_backup_state = pmp; + pstate = pstate->next.p; + return true; +} + +template +bool perl_matcher::skip_until_paren(int index, bool have_match) +{ + while(pstate) + { + if(pstate->type == syntax_element_endmark) + { + if(static_cast(pstate)->index == index) + { + if(have_match) + return this->match_endmark(); + pstate = pstate->next.p; + return true; + } + else + { + // Unenclosed closing ), occurs when (*ACCEPT) is inside some other + // parenthesis which may or may not have other side effects associated with it. + const re_syntax_base* sp = pstate; + match_endmark(); + if(!pstate) + { + unwind(true); + // unwind may leave pstate NULL if we've unwound a forward lookahead, in which + // case just move to the next state and keep looking... + if (!pstate) + pstate = sp->next.p; + } + } + continue; + } + else if(pstate->type == syntax_element_match) + return true; + else if(pstate->type == syntax_element_startmark) + { + int idx = static_cast(pstate)->index; + pstate = pstate->next.p; + skip_until_paren(idx, false); + continue; + } + pstate = pstate->next.p; + } + return true; +} + +/**************************************************************************** + +Unwind and associated procedures follow, these perform what normal stack +unwinding does in the recursive implementation. + +****************************************************************************/ + +template +bool perl_matcher::unwind(bool have_match) +{ + static unwind_proc_type const s_unwind_table[19] = + { + &perl_matcher::unwind_end, + &perl_matcher::unwind_paren, + &perl_matcher::unwind_recursion_stopper, + &perl_matcher::unwind_assertion, + &perl_matcher::unwind_alt, + &perl_matcher::unwind_repeater_counter, + &perl_matcher::unwind_extra_block, + &perl_matcher::unwind_greedy_single_repeat, + &perl_matcher::unwind_slow_dot_repeat, + &perl_matcher::unwind_fast_dot_repeat, + &perl_matcher::unwind_char_repeat, + &perl_matcher::unwind_short_set_repeat, + &perl_matcher::unwind_long_set_repeat, + &perl_matcher::unwind_non_greedy_repeat, + &perl_matcher::unwind_recursion, + &perl_matcher::unwind_recursion_pop, + &perl_matcher::unwind_commit, + &perl_matcher::unwind_then, + &perl_matcher::unwind_case, + }; + + m_recursive_result = have_match; + m_unwound_lookahead = false; + m_unwound_alt = false; + unwind_proc_type unwinder; + bool cont; + // + // keep unwinding our stack until we have something to do: + // + do + { + unwinder = s_unwind_table[m_backup_state->state_id]; + cont = (this->*unwinder)(m_recursive_result); + }while(cont); + // + // return true if we have more states to try: + // + return pstate ? true : false; +} + +template +bool perl_matcher::unwind_end(bool) +{ + pstate = 0; // nothing left to search + return false; // end of stack nothing more to search +} + +template +bool perl_matcher::unwind_case(bool) +{ + saved_change_case* pmp = static_cast(m_backup_state); + icase = pmp->icase; + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; +} + +template +bool perl_matcher::unwind_paren(bool have_match) +{ + saved_matched_paren* pmp = static_cast*>(m_backup_state); + // restore previous values if no match was found: + if(!have_match) + { + m_presult->set_first(pmp->sub.first, pmp->index, pmp->index == 0); + m_presult->set_second(pmp->sub.second, pmp->index, pmp->sub.matched, pmp->index == 0); + } +#ifdef BOOST_REGEX_MATCH_EXTRA + // + // we have a match, push the capture information onto the stack: + // + else if(pmp->sub.matched && (match_extra & m_match_flags)) + ((*m_presult)[pmp->index]).get_captures().push_back(pmp->sub); +#endif + // unwind stack: + m_backup_state = pmp+1; + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp); + return true; // keep looking +} + +template +bool perl_matcher::unwind_recursion_stopper(bool) +{ + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++); + pstate = 0; // nothing left to search + return false; // end of stack nothing more to search +} + +template +bool perl_matcher::unwind_assertion(bool r) +{ + saved_assertion* pmp = static_cast*>(m_backup_state); + pstate = pmp->pstate; + position = pmp->position; + bool result = (r == pmp->positive); + m_recursive_result = pmp->positive ? r : !r; + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + m_unwound_lookahead = true; + return !result; // return false if the assertion was matched to stop search. +} + +template +bool perl_matcher::unwind_alt(bool r) +{ + saved_position* pmp = static_cast*>(m_backup_state); + if(!r) + { + pstate = pmp->pstate; + position = pmp->position; + } + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + m_unwound_alt = !r; + return r; +} + +template +bool perl_matcher::unwind_repeater_counter(bool) +{ + saved_repeater* pmp = static_cast*>(m_backup_state); + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; // keep looking +} + +template +bool perl_matcher::unwind_extra_block(bool) +{ + ++used_block_count; + saved_extra_block* pmp = static_cast(m_backup_state); + void* condemmed = m_stack_base; + m_stack_base = pmp->base; + m_backup_state = pmp->end; + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp); + put_mem_block(condemmed); + return true; // keep looking +} + +template +inline void perl_matcher::destroy_single_repeat() +{ + saved_single_repeat* p = static_cast*>(m_backup_state); + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(p++); + m_backup_state = p; +} + +template +bool perl_matcher::unwind_greedy_single_repeat(bool r) +{ + saved_single_repeat* pmp = static_cast*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + BOOST_REGEX_ASSERT(rep->next.p != 0); + BOOST_REGEX_ASSERT(rep->alt.p != 0); + + count -= rep->min; + + if((m_match_flags & match_partial) && (position == last)) + m_has_partial_match = true; + + BOOST_REGEX_ASSERT(count); + position = pmp->last_position; + + // backtrack till we can skip out: + do + { + --position; + --count; + ++state_count; + }while(count && !can_start(*position, rep->_map, mask_skip)); + + // if we've hit base, destroy this state: + if(count == 0) + { + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count + rep->min; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template +bool perl_matcher::unwind_slow_dot_repeat(bool r) +{ + saved_single_repeat* pmp = static_cast*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + BOOST_REGEX_ASSERT(rep->type == syntax_element_dot_rep); + BOOST_REGEX_ASSERT(rep->next.p != 0); + BOOST_REGEX_ASSERT(rep->alt.p != 0); + BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_wild); + + BOOST_REGEX_ASSERT(count < rep->max); + pstate = rep->next.p; + position = pmp->last_position; + + if(position != last) + { + // wind forward until we can skip out of the repeat: + do + { + if(!match_wild()) + { + // failed repeat match, discard this state and look for another: + destroy_single_repeat(); + return true; + } + ++count; + ++state_count; + pstate = rep->next.p; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template +bool perl_matcher::unwind_fast_dot_repeat(bool r) +{ + saved_single_repeat* pmp = static_cast*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + + BOOST_REGEX_ASSERT(count < rep->max); + position = pmp->last_position; + if(position != last) + { + + // wind forward until we can skip out of the repeat: + do + { + ++position; + ++count; + ++state_count; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template +bool perl_matcher::unwind_char_repeat(bool r) +{ + saved_single_repeat* pmp = static_cast*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + pstate = rep->next.p; + const char_type what = *reinterpret_cast(static_cast(pstate) + 1); + position = pmp->last_position; + + BOOST_REGEX_ASSERT(rep->type == syntax_element_char_rep); + BOOST_REGEX_ASSERT(rep->next.p != 0); + BOOST_REGEX_ASSERT(rep->alt.p != 0); + BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_literal); + BOOST_REGEX_ASSERT(count < rep->max); + + if(position != last) + { + // wind forward until we can skip out of the repeat: + do + { + if(traits_inst.translate(*position, icase) != what) + { + // failed repeat match, discard this state and look for another: + destroy_single_repeat(); + return true; + } + ++count; + ++ position; + ++state_count; + pstate = rep->next.p; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template +bool perl_matcher::unwind_short_set_repeat(bool r) +{ + saved_single_repeat* pmp = static_cast*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + pstate = rep->next.p; + const unsigned char* map = static_cast(rep->next.p)->_map; + position = pmp->last_position; + + BOOST_REGEX_ASSERT(rep->type == syntax_element_short_set_rep); + BOOST_REGEX_ASSERT(rep->next.p != 0); + BOOST_REGEX_ASSERT(rep->alt.p != 0); + BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_set); + BOOST_REGEX_ASSERT(count < rep->max); + + if(position != last) + { + // wind forward until we can skip out of the repeat: + do + { + if(!map[static_cast(traits_inst.translate(*position, icase))]) + { + // failed repeat match, discard this state and look for another: + destroy_single_repeat(); + return true; + } + ++count; + ++ position; + ++state_count; + pstate = rep->next.p; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template +bool perl_matcher::unwind_long_set_repeat(bool r) +{ + typedef typename traits::char_class_type m_type; + saved_single_repeat* pmp = static_cast*>(m_backup_state); + + // if we have a match, just discard this state: + if(r) + { + destroy_single_repeat(); + return true; + } + + const re_repeat* rep = pmp->rep; + std::size_t count = pmp->count; + pstate = rep->next.p; + const re_set_long* set = static_cast*>(pstate); + position = pmp->last_position; + + BOOST_REGEX_ASSERT(rep->type == syntax_element_long_set_rep); + BOOST_REGEX_ASSERT(rep->next.p != 0); + BOOST_REGEX_ASSERT(rep->alt.p != 0); + BOOST_REGEX_ASSERT(rep->next.p->type == syntax_element_long_set); + BOOST_REGEX_ASSERT(count < rep->max); + + if(position != last) + { + // wind forward until we can skip out of the repeat: + do + { + if(position == re_is_set_member(position, last, set, re.get_data(), icase)) + { + // failed repeat match, discard this state and look for another: + destroy_single_repeat(); + return true; + } + ++position; + ++count; + ++state_count; + pstate = rep->next.p; + }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip)); + } + // remember where we got to if this is a leading repeat: + if((rep->leading) && (count < rep->max)) + restart = position; + if(position == last) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if((m_match_flags & match_partial) && (position == last) && (position != search_base)) + m_has_partial_match = true; + if(0 == (rep->can_be_null & mask_skip)) + return true; + } + else if(count == rep->max) + { + // can't repeat any more, remove the pushed state: + destroy_single_repeat(); + if(!can_start(*position, rep->_map, mask_skip)) + return true; + } + else + { + pmp->count = count; + pmp->last_position = position; + } + pstate = rep->alt.p; + return false; +} + +template +bool perl_matcher::unwind_non_greedy_repeat(bool r) +{ + saved_position* pmp = static_cast*>(m_backup_state); + if(!r) + { + position = pmp->position; + pstate = pmp->pstate; + ++(*next_count); + } + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + return r; +} + +template +bool perl_matcher::unwind_recursion(bool r) +{ + // We are backtracking back inside a recursion, need to push the info + // back onto the recursion stack, and do so unconditionally, otherwise + // we can get mismatched pushes and pops... + saved_recursion* pmp = static_cast*>(m_backup_state); + if (!r) + { + recursion_stack.push_back(recursion_info()); + recursion_stack.back().idx = pmp->recursion_id; + recursion_stack.back().preturn_address = pmp->preturn_address; + recursion_stack.back().results = pmp->prior_results; + recursion_stack.back().location_of_start = position; + *m_presult = pmp->internal_results; + } + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; +} + +template +bool perl_matcher::unwind_recursion_pop(bool r) +{ + // Backtracking out of a recursion, we must pop state off the recursion + // stack unconditionally to ensure matched pushes and pops: + saved_state* pmp = static_cast(m_backup_state); + if (!r && !recursion_stack.empty()) + { + *m_presult = recursion_stack.back().results; + position = recursion_stack.back().location_of_start; + recursion_stack.pop_back(); + } + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++); + m_backup_state = pmp; + return true; +} + +template +void perl_matcher::push_recursion_pop() +{ + saved_state* pmp = static_cast(m_backup_state); + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = static_cast(m_backup_state); + --pmp; + } + (void) new (pmp)saved_state(15); + m_backup_state = pmp; +} + +template +bool perl_matcher::unwind_commit(bool b) +{ + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++); + while(unwind(b) && !m_unwound_lookahead){} + if(m_unwound_lookahead && pstate) + { + // + // If we stop because we just unwound an assertion, put the + // commit state back on the stack again: + // + m_unwound_lookahead = false; + saved_state* pmp = m_backup_state; + --pmp; + if(pmp < m_stack_base) + { + extend_stack(); + pmp = m_backup_state; + --pmp; + } + (void) new (pmp)saved_state(16); + m_backup_state = pmp; + } + // This prevents us from stopping when we exit from an independent sub-expression: + m_independent = false; + return false; +} + +template +bool perl_matcher::unwind_then(bool b) +{ + // Unwind everything till we hit an alternative: + boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++); + bool result = false; + result = unwind(b); + while(result && !m_unwound_alt) + { + result = unwind(b); + } + // We're now pointing at the next alternative, need one more backtrack + // since *all* the other alternatives must fail once we've reached a THEN clause: + if(result && m_unwound_alt) + unwind(b); + return false; +} + +} // namespace BOOST_REGEX_DETAIL_NS +} // namespace boost + +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif + +#endif diff --git a/boost/regex/v5/primary_transform.hpp b/boost/regex/v5/primary_transform.hpp new file mode 100644 index 00000000..ed46f392 --- /dev/null +++ b/boost/regex/v5/primary_transform.hpp @@ -0,0 +1,120 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE: primary_transform.hpp + * VERSION: see + * DESCRIPTION: Heuristically determines the sort string format in use + * by the current locale. + */ + +#ifndef BOOST_REGEX_PRIMARY_TRANSFORM +#define BOOST_REGEX_PRIMARY_TRANSFORM + +namespace boost{ + namespace BOOST_REGEX_DETAIL_NS{ + + +enum{ + sort_C, + sort_fixed, + sort_delim, + sort_unknown +}; + +template +unsigned count_chars(const S& s, charT c) +{ + // + // Count how many occurrences of character c occur + // in string s: if c is a delimeter between collation + // fields, then this should be the same value for all + // sort keys: + // + unsigned int count = 0; + for(unsigned pos = 0; pos < s.size(); ++pos) + { + if(s[pos] == c) ++count; + } + return count; +} + + +template +unsigned find_sort_syntax(const traits* pt, charT* delim) +{ + // + // compare 'a' with 'A' to see how similar they are, + // should really use a-accute but we can't portably do that, + // + typedef typename traits::string_type string_type; + typedef typename traits::char_type char_type; + + // Suppress incorrect warning for MSVC + (void)pt; + + char_type a[2] = {'a', '\0', }; + string_type sa(pt->transform(a, a+1)); + if(sa == a) + { + *delim = 0; + return sort_C; + } + char_type A[2] = { 'A', '\0', }; + string_type sA(pt->transform(A, A+1)); + char_type c[2] = { ';', '\0', }; + string_type sc(pt->transform(c, c+1)); + + int pos = 0; + while((pos <= static_cast(sa.size())) && (pos <= static_cast(sA.size())) && (sa[pos] == sA[pos])) ++pos; + --pos; + if(pos < 0) + { + *delim = 0; + return sort_unknown; + } + // + // at this point sa[pos] is either the end of a fixed width field + // or the character that acts as a delimiter: + // + charT maybe_delim = sa[pos]; + if((pos != 0) && (count_chars(sa, maybe_delim) == count_chars(sA, maybe_delim)) && (count_chars(sa, maybe_delim) == count_chars(sc, maybe_delim))) + { + *delim = maybe_delim; + return sort_delim; + } + // + // OK doen't look like a delimiter, try for fixed width field: + // + if((sa.size() == sA.size()) && (sa.size() == sc.size())) + { + // note assumes that the fixed width field is less than + // (numeric_limits::max)(), should be true for all types + // I can't imagine 127 character fields... + *delim = static_cast(++pos); + return sort_fixed; + } + // + // don't know what it is: + // + *delim = 0; + return sort_unknown; +} + + + } // namespace BOOST_REGEX_DETAIL_NS +} // namespace boost + +#endif + + + diff --git a/boost/regex/v5/regbase.hpp b/boost/regex/v5/regbase.hpp new file mode 100644 index 00000000..5cefb36b --- /dev/null +++ b/boost/regex/v5/regbase.hpp @@ -0,0 +1,158 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regbase.cpp + * VERSION see + * DESCRIPTION: Declares class regbase. + */ + +#ifndef BOOST_REGEX_V5_REGBASE_HPP +#define BOOST_REGEX_V5_REGBASE_HPP + +namespace boost{ +// +// class regbase +// handles error codes and flags +// +class regbase +{ +public: + enum flag_type_ + { + // + // Divide the flags up into logical groups: + // bits 0-7 indicate main synatx type. + // bits 8-15 indicate syntax subtype. + // bits 16-31 indicate options that are common to all + // regex syntaxes. + // In all cases the default is 0. + // + // Main synatx group: + // + perl_syntax_group = 0, // default + basic_syntax_group = 1, // POSIX basic + literal = 2, // all characters are literals + main_option_type = literal | basic_syntax_group | perl_syntax_group, // everything! + // + // options specific to perl group: + // + no_bk_refs = 1 << 8, // \d not allowed + no_perl_ex = 1 << 9, // disable perl extensions + no_mod_m = 1 << 10, // disable Perl m modifier + mod_x = 1 << 11, // Perl x modifier + mod_s = 1 << 12, // force s modifier on (overrides match_not_dot_newline) + no_mod_s = 1 << 13, // force s modifier off (overrides match_not_dot_newline) + + // + // options specific to basic group: + // + no_char_classes = 1 << 8, // [[:CLASS:]] not allowed + no_intervals = 1 << 9, // {x,y} not allowed + bk_plus_qm = 1 << 10, // uses \+ and \? + bk_vbar = 1 << 11, // use \| for alternatives + emacs_ex = 1 << 12, // enables emacs extensions + + // + // options common to all groups: + // + no_escape_in_lists = 1 << 16, // '\' not special inside [...] + newline_alt = 1 << 17, // \n is the same as | + no_except = 1 << 18, // no exception on error + failbit = 1 << 19, // error flag + icase = 1 << 20, // characters are matched regardless of case + nocollate = 0, // don't use locale specific collation (deprecated) + collate = 1 << 21, // use locale specific collation + nosubs = 1 << 22, // don't mark sub-expressions + save_subexpression_location = 1 << 23, // save subexpression locations + no_empty_expressions = 1 << 24, // no empty expressions allowed + optimize = 0, // not really supported + + + + basic = basic_syntax_group | collate | no_escape_in_lists, + extended = no_bk_refs | collate | no_perl_ex | no_escape_in_lists, + normal = 0, + emacs = basic_syntax_group | collate | emacs_ex | bk_vbar, + awk = no_bk_refs | collate | no_perl_ex, + grep = basic | newline_alt, + egrep = extended | newline_alt, + sed = basic, + perl = normal, + ECMAScript = normal, + JavaScript = normal, + JScript = normal + }; + typedef unsigned int flag_type; + + enum restart_info + { + restart_any = 0, + restart_word = 1, + restart_line = 2, + restart_buf = 3, + restart_continue = 4, + restart_lit = 5, + restart_fixed_lit = 6, + restart_count = 7 + }; +}; + +// +// provide std lib proposal compatible constants: +// +namespace regex_constants{ + + enum flag_type_ + { + + no_except = ::boost::regbase::no_except, + failbit = ::boost::regbase::failbit, + literal = ::boost::regbase::literal, + icase = ::boost::regbase::icase, + nocollate = ::boost::regbase::nocollate, + collate = ::boost::regbase::collate, + nosubs = ::boost::regbase::nosubs, + optimize = ::boost::regbase::optimize, + bk_plus_qm = ::boost::regbase::bk_plus_qm, + bk_vbar = ::boost::regbase::bk_vbar, + no_intervals = ::boost::regbase::no_intervals, + no_char_classes = ::boost::regbase::no_char_classes, + no_escape_in_lists = ::boost::regbase::no_escape_in_lists, + no_mod_m = ::boost::regbase::no_mod_m, + mod_x = ::boost::regbase::mod_x, + mod_s = ::boost::regbase::mod_s, + no_mod_s = ::boost::regbase::no_mod_s, + save_subexpression_location = ::boost::regbase::save_subexpression_location, + no_empty_expressions = ::boost::regbase::no_empty_expressions, + + basic = ::boost::regbase::basic, + extended = ::boost::regbase::extended, + normal = ::boost::regbase::normal, + emacs = ::boost::regbase::emacs, + awk = ::boost::regbase::awk, + grep = ::boost::regbase::grep, + egrep = ::boost::regbase::egrep, + sed = basic, + perl = normal, + ECMAScript = normal, + JavaScript = normal, + JScript = normal + }; + typedef ::boost::regbase::flag_type syntax_option_type; + +} // namespace regex_constants + +} // namespace boost + +#endif + diff --git a/boost/regex/v5/regex.hpp b/boost/regex/v5/regex.hpp new file mode 100644 index 00000000..eb6dc728 --- /dev/null +++ b/boost/regex/v5/regex.hpp @@ -0,0 +1,106 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex.cpp + * VERSION see + * DESCRIPTION: Declares boost::basic_regex<> and associated + * functions and classes. This header is the main + * entry point for the template regex code. + */ + +#ifndef BOOST_RE_REGEX_HPP_INCLUDED +#define BOOST_RE_REGEX_HPP_INCLUDED + +#ifdef __cplusplus + +// what follows is all C++ don't include in C builds!! + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ +#ifdef BOOST_REGEX_NO_FWD +typedef basic_regex > regex; +#ifndef BOOST_NO_WREGEX +typedef basic_regex > wregex; +#endif +#endif + +typedef match_results cmatch; +typedef match_results smatch; +#ifndef BOOST_NO_WREGEX +typedef match_results wcmatch; +typedef match_results wsmatch; +#endif + +} // namespace boost + +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // __cplusplus + +#endif // include + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/boost/regex/v5/regex_format.hpp b/boost/regex/v5/regex_format.hpp new file mode 100644 index 00000000..4c82d185 --- /dev/null +++ b/boost/regex/v5/regex_format.hpp @@ -0,0 +1,1124 @@ +/* + * + * Copyright (c) 1998-2009 John Maddock + * Copyright 2008 Eric Niebler. + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_format.hpp + * VERSION see + * DESCRIPTION: Provides formatting output routines for search and replace + * operations. Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_FORMAT_HPP +#define BOOST_REGEX_FORMAT_HPP + +#include +#include + +namespace boost{ + +// +// Forward declaration: +// + template >::allocator_type > +class match_results; + +namespace BOOST_REGEX_DETAIL_NS{ + +// +// struct trivial_format_traits: +// defines minimum localisation support for formatting +// in the case that the actual regex traits is unavailable. +// +template +struct trivial_format_traits +{ + typedef charT char_type; + + static std::ptrdiff_t length(const charT* p) + { + return global_length(p); + } + static charT tolower(charT c) + { + return ::boost::BOOST_REGEX_DETAIL_NS::global_lower(c); + } + static charT toupper(charT c) + { + return ::boost::BOOST_REGEX_DETAIL_NS::global_upper(c); + } + static int value(const charT c, int radix) + { + int result = global_value(c); + return result >= radix ? -1 : result; + } + int toi(const charT*& p1, const charT* p2, int radix)const + { + return (int)global_toi(p1, p2, radix, *this); + } +}; + +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +#pragma warning(disable:26812) +#endif +template +class basic_regex_formatter +{ +public: + typedef typename traits::char_type char_type; + basic_regex_formatter(OutputIterator o, const Results& r, const traits& t) + : m_traits(t), m_results(r), m_out(o), m_position(), m_end(), m_flags(), m_state(output_copy), m_restore_state(output_copy), m_have_conditional(false) {} + OutputIterator format(ForwardIter p1, ForwardIter p2, match_flag_type f); + OutputIterator format(ForwardIter p1, match_flag_type f) + { + return format(p1, p1 + m_traits.length(p1), f); + } +private: + typedef typename Results::value_type sub_match_type; + enum output_state + { + output_copy, + output_next_lower, + output_next_upper, + output_lower, + output_upper, + output_none + }; + + void put(char_type c); + void put(const sub_match_type& sub); + void format_all(); + void format_perl(); + void format_escape(); + void format_conditional(); + void format_until_scope_end(); + bool handle_perl_verb(bool have_brace); + + inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const std::integral_constant&) + { + std::vector v(i, j); + return (i != j) ? this->m_results.named_subexpression(&v[0], &v[0] + v.size()) + : this->m_results.named_subexpression(static_cast(0), static_cast(0)); + } + inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const std::integral_constant&) + { + return this->m_results.named_subexpression(i, j); + } + inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j) + { + typedef typename std::is_convertible::type tag_type; + return get_named_sub(i, j, tag_type()); + } + inline int get_named_sub_index(ForwardIter i, ForwardIter j, const std::integral_constant&) + { + std::vector v(i, j); + return (i != j) ? this->m_results.named_subexpression_index(&v[0], &v[0] + v.size()) + : this->m_results.named_subexpression_index(static_cast(0), static_cast(0)); + } + inline int get_named_sub_index(ForwardIter i, ForwardIter j, const std::integral_constant&) + { + return this->m_results.named_subexpression_index(i, j); + } + inline int get_named_sub_index(ForwardIter i, ForwardIter j) + { + typedef typename std::is_convertible::type tag_type; + return get_named_sub_index(i, j, tag_type()); + } +#ifdef BOOST_REGEX_MSVC + // msvc-8.0 issues a spurious warning on the call to std::advance here: +#pragma warning(push) +#pragma warning(disable:4244) +#endif + inline int toi(ForwardIter& i, ForwardIter j, int base, const std::integral_constant&) + { + if(i != j) + { + std::vector v(i, j); + const char_type* start = &v[0]; + const char_type* pos = start; + int r = (int)m_traits.toi(pos, &v[0] + v.size(), base); + std::advance(i, pos - start); + return r; + } + return -1; + } +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif + inline int toi(ForwardIter& i, ForwardIter j, int base, const std::integral_constant&) + { + return m_traits.toi(i, j, base); + } + inline int toi(ForwardIter& i, ForwardIter j, int base) + { +#if defined(_MSC_VER) && defined(__INTEL_COMPILER) && ((__INTEL_COMPILER == 9999) || (__INTEL_COMPILER == 1210)) + // Workaround for Intel support issue #656654. + // See also https://svn.boost.org/trac/boost/ticket/6359 + return toi(i, j, base, std::integral_constant()); +#else + typedef typename std::is_convertible::type tag_type; + return toi(i, j, base, tag_type()); +#endif + } + + const traits& m_traits; // the traits class for localised formatting operations + const Results& m_results; // the match_results being used. + OutputIterator m_out; // where to send output. + ForwardIter m_position; // format string, current position + ForwardIter m_end; // format string end + match_flag_type m_flags; // format flags to use + output_state m_state; // what to do with the next character + output_state m_restore_state; // what state to restore to. + bool m_have_conditional; // we are parsing a conditional +private: + basic_regex_formatter(const basic_regex_formatter&); + basic_regex_formatter& operator=(const basic_regex_formatter&); +}; +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif + +template +OutputIterator basic_regex_formatter::format(ForwardIter p1, ForwardIter p2, match_flag_type f) +{ + m_position = p1; + m_end = p2; + m_flags = f; + format_all(); + return m_out; +} + +template +void basic_regex_formatter::format_all() +{ + // over and over: + while(m_position != m_end) + { + switch(*m_position) + { + case '&': + if(m_flags & ::boost::regex_constants::format_sed) + { + ++m_position; + put(m_results[0]); + break; + } + put(*m_position++); + break; + case '\\': + format_escape(); + break; + case '(': + if(m_flags & boost::regex_constants::format_all) + { + ++m_position; + bool have_conditional = m_have_conditional; + m_have_conditional = false; + format_until_scope_end(); + m_have_conditional = have_conditional; + if(m_position == m_end) + return; + BOOST_REGEX_ASSERT(*m_position == static_cast(')')); + ++m_position; // skip the closing ')' + break; + } + put(*m_position); + ++m_position; + break; + case ')': + if(m_flags & boost::regex_constants::format_all) + { + return; + } + put(*m_position); + ++m_position; + break; + case ':': + if((m_flags & boost::regex_constants::format_all) && m_have_conditional) + { + return; + } + put(*m_position); + ++m_position; + break; + case '?': + if(m_flags & boost::regex_constants::format_all) + { + ++m_position; + format_conditional(); + break; + } + put(*m_position); + ++m_position; + break; + case '$': + if((m_flags & format_sed) == 0) + { + format_perl(); + break; + } + // not a special character: + BOOST_REGEX_FALLTHROUGH; + default: + put(*m_position); + ++m_position; + break; + } + } +} + +template +void basic_regex_formatter::format_perl() +{ + // + // On entry *m_position points to a '$' character + // output the information that goes with it: + // + BOOST_REGEX_ASSERT(*m_position == '$'); + // + // see if this is a trailing '$': + // + if(++m_position == m_end) + { + --m_position; + put(*m_position); + ++m_position; + return; + } + // + // OK find out what kind it is: + // + bool have_brace = false; + ForwardIter save_position = m_position; + switch(*m_position) + { + case '&': + ++m_position; + put(this->m_results[0]); + break; + case '`': + ++m_position; + put(this->m_results.prefix()); + break; + case '\'': + ++m_position; + put(this->m_results.suffix()); + break; + case '$': + put(*m_position++); + break; + case '+': + if((++m_position != m_end) && (*m_position == '{')) + { + ForwardIter base = ++m_position; + while((m_position != m_end) && (*m_position != '}')) ++m_position; + if(m_position != m_end) + { + // Named sub-expression: + put(get_named_sub(base, m_position)); + ++m_position; + break; + } + else + { + m_position = --base; + } + } + put((this->m_results)[this->m_results.size() > 1 ? static_cast(this->m_results.size() - 1) : 1]); + break; + case '{': + have_brace = true; + ++m_position; + BOOST_REGEX_FALLTHROUGH; + default: + // see if we have a number: + { + std::ptrdiff_t len = std::distance(m_position, m_end); + //len = (std::min)(static_cast(2), len); + int v = this->toi(m_position, m_position + len, 10); + if((v < 0) || (have_brace && ((m_position == m_end) || (*m_position != '}')))) + { + // Look for a Perl-5.10 verb: + if(!handle_perl_verb(have_brace)) + { + // leave the $ as is, and carry on: + m_position = --save_position; + put(*m_position); + ++m_position; + } + break; + } + // otherwise output sub v: + put(this->m_results[v]); + if(have_brace) + ++m_position; + } + } +} + +template +bool basic_regex_formatter::handle_perl_verb(bool have_brace) +{ + // + // We may have a capitalised string containing a Perl action: + // + static const char_type MATCH[] = { 'M', 'A', 'T', 'C', 'H' }; + static const char_type PREMATCH[] = { 'P', 'R', 'E', 'M', 'A', 'T', 'C', 'H' }; + static const char_type POSTMATCH[] = { 'P', 'O', 'S', 'T', 'M', 'A', 'T', 'C', 'H' }; + static const char_type LAST_PAREN_MATCH[] = { 'L', 'A', 'S', 'T', '_', 'P', 'A', 'R', 'E', 'N', '_', 'M', 'A', 'T', 'C', 'H' }; + static const char_type LAST_SUBMATCH_RESULT[] = { 'L', 'A', 'S', 'T', '_', 'S', 'U', 'B', 'M', 'A', 'T', 'C', 'H', '_', 'R', 'E', 'S', 'U', 'L', 'T' }; + static const char_type LAST_SUBMATCH_RESULT_ALT[] = { '^', 'N' }; + + if(m_position == m_end) + return false; + if(have_brace && (*m_position == '^')) + ++m_position; + + std::ptrdiff_t max_len = m_end - m_position; + + if((max_len >= 5) && std::equal(m_position, m_position + 5, MATCH)) + { + m_position += 5; + if(have_brace) + { + if((m_position != m_end) && (*m_position == '}')) + ++m_position; + else + { + m_position -= 5; + return false; + } + } + put(this->m_results[0]); + return true; + } + if((max_len >= 8) && std::equal(m_position, m_position + 8, PREMATCH)) + { + m_position += 8; + if(have_brace) + { + if((m_position != m_end) && (*m_position == '}')) + ++m_position; + else + { + m_position -= 8; + return false; + } + } + put(this->m_results.prefix()); + return true; + } + if((max_len >= 9) && std::equal(m_position, m_position + 9, POSTMATCH)) + { + m_position += 9; + if(have_brace) + { + if((m_position != m_end) && (*m_position == '}')) + ++m_position; + else + { + m_position -= 9; + return false; + } + } + put(this->m_results.suffix()); + return true; + } + if((max_len >= 16) && std::equal(m_position, m_position + 16, LAST_PAREN_MATCH)) + { + m_position += 16; + if(have_brace) + { + if((m_position != m_end) && (*m_position == '}')) + ++m_position; + else + { + m_position -= 16; + return false; + } + } + put((this->m_results)[this->m_results.size() > 1 ? static_cast(this->m_results.size() - 1) : 1]); + return true; + } + if((max_len >= 20) && std::equal(m_position, m_position + 20, LAST_SUBMATCH_RESULT)) + { + m_position += 20; + if(have_brace) + { + if((m_position != m_end) && (*m_position == '}')) + ++m_position; + else + { + m_position -= 20; + return false; + } + } + put(this->m_results.get_last_closed_paren()); + return true; + } + if((max_len >= 2) && std::equal(m_position, m_position + 2, LAST_SUBMATCH_RESULT_ALT)) + { + m_position += 2; + if(have_brace) + { + if((m_position != m_end) && (*m_position == '}')) + ++m_position; + else + { + m_position -= 2; + return false; + } + } + put(this->m_results.get_last_closed_paren()); + return true; + } + return false; +} + +template +void basic_regex_formatter::format_escape() +{ + // skip the escape and check for trailing escape: + if(++m_position == m_end) + { + put(static_cast('\\')); + return; + } + // now switch on the escape type: + switch(*m_position) + { + case 'a': + put(static_cast('\a')); + ++m_position; + break; + case 'f': + put(static_cast('\f')); + ++m_position; + break; + case 'n': + put(static_cast('\n')); + ++m_position; + break; + case 'r': + put(static_cast('\r')); + ++m_position; + break; + case 't': + put(static_cast('\t')); + ++m_position; + break; + case 'v': + put(static_cast('\v')); + ++m_position; + break; + case 'x': + if(++m_position == m_end) + { + put(static_cast('x')); + return; + } + // maybe have \x{ddd} + if(*m_position == static_cast('{')) + { + ++m_position; + int val = this->toi(m_position, m_end, 16); + if(val < 0) + { + // invalid value treat everything as literals: + put(static_cast('x')); + put(static_cast('{')); + return; + } + if((m_position == m_end) || (*m_position != static_cast('}'))) + { + --m_position; + while(*m_position != static_cast('\\')) + --m_position; + ++m_position; + put(*m_position++); + return; + } + ++m_position; + put(static_cast(val)); + return; + } + else + { + std::ptrdiff_t len = std::distance(m_position, m_end); + len = (std::min)(static_cast(2), len); + int val = this->toi(m_position, m_position + len, 16); + if(val < 0) + { + --m_position; + put(*m_position++); + return; + } + put(static_cast(val)); + } + break; + case 'c': + if(++m_position == m_end) + { + --m_position; + put(*m_position++); + return; + } + put(static_cast(*m_position++ % 32)); + break; + case 'e': + put(static_cast(27)); + ++m_position; + break; + default: + // see if we have a perl specific escape: + if((m_flags & boost::regex_constants::format_sed) == 0) + { + bool breakout = false; + switch(*m_position) + { + case 'l': + ++m_position; + m_restore_state = m_state; + m_state = output_next_lower; + breakout = true; + break; + case 'L': + ++m_position; + m_state = output_lower; + breakout = true; + break; + case 'u': + ++m_position; + m_restore_state = m_state; + m_state = output_next_upper; + breakout = true; + break; + case 'U': + ++m_position; + m_state = output_upper; + breakout = true; + break; + case 'E': + ++m_position; + m_state = output_copy; + breakout = true; + break; + } + if(breakout) + break; + } + // see if we have a \n sed style backreference: + std::ptrdiff_t len = std::distance(m_position, m_end); + len = (std::min)(static_cast(1), len); + int v = this->toi(m_position, m_position+len, 10); + if((v > 0) || ((v == 0) && (m_flags & ::boost::regex_constants::format_sed))) + { + put(m_results[v]); + break; + } + else if(v == 0) + { + // octal ecape sequence: + --m_position; + len = std::distance(m_position, m_end); + len = (std::min)(static_cast(4), len); + v = this->toi(m_position, m_position + len, 8); + BOOST_REGEX_ASSERT(v >= 0); + put(static_cast(v)); + break; + } + // Otherwise output the character "as is": + put(*m_position++); + break; + } +} + +template +void basic_regex_formatter::format_conditional() +{ + if(m_position == m_end) + { + // oops trailing '?': + put(static_cast('?')); + return; + } + int v; + if(*m_position == '{') + { + ForwardIter base = m_position; + ++m_position; + v = this->toi(m_position, m_end, 10); + if(v < 0) + { + // Try a named subexpression: + while((m_position != m_end) && (*m_position != '}')) + ++m_position; + v = this->get_named_sub_index(base + 1, m_position); + } + if((v < 0) || (*m_position != '}')) + { + m_position = base; + // oops trailing '?': + put(static_cast('?')); + return; + } + // Skip trailing '}': + ++m_position; + } + else + { + std::ptrdiff_t len = std::distance(m_position, m_end); + len = (std::min)(static_cast(2), len); + v = this->toi(m_position, m_position + len, 10); + } + if(v < 0) + { + // oops not a number: + put(static_cast('?')); + return; + } + + // output varies depending upon whether sub-expression v matched or not: + if(m_results[v].matched) + { + m_have_conditional = true; + format_all(); + m_have_conditional = false; + if((m_position != m_end) && (*m_position == static_cast(':'))) + { + // skip the ':': + ++m_position; + // save output state, then turn it off: + output_state saved_state = m_state; + m_state = output_none; + // format the rest of this scope: + format_until_scope_end(); + // restore output state: + m_state = saved_state; + } + } + else + { + // save output state, then turn it off: + output_state saved_state = m_state; + m_state = output_none; + // format until ':' or ')': + m_have_conditional = true; + format_all(); + m_have_conditional = false; + // restore state: + m_state = saved_state; + if((m_position != m_end) && (*m_position == static_cast(':'))) + { + // skip the ':': + ++m_position; + // format the rest of this scope: + format_until_scope_end(); + } + } +} + +template +void basic_regex_formatter::format_until_scope_end() +{ + do + { + format_all(); + if((m_position == m_end) || (*m_position == static_cast(')'))) + return; + put(*m_position++); + }while(m_position != m_end); +} + +template +void basic_regex_formatter::put(char_type c) +{ + // write a single character to output + // according to which case translation mode we are in: + switch(this->m_state) + { + case output_none: + return; + case output_next_lower: + c = m_traits.tolower(c); + this->m_state = m_restore_state; + break; + case output_next_upper: + c = m_traits.toupper(c); + this->m_state = m_restore_state; + break; + case output_lower: + c = m_traits.tolower(c); + break; + case output_upper: + c = m_traits.toupper(c); + break; + default: + break; + } + *m_out = c; + ++m_out; +} + +template +void basic_regex_formatter::put(const sub_match_type& sub) +{ + typedef typename sub_match_type::iterator iterator_type; + iterator_type i = sub.first; + while(i != sub.second) + { + put(*i); + ++i; + } +} + +template +class string_out_iterator +{ + S* out; +public: + string_out_iterator(S& s) : out(&s) {} + string_out_iterator& operator++() { return *this; } + string_out_iterator& operator++(int) { return *this; } + string_out_iterator& operator*() { return *this; } + string_out_iterator& operator=(typename S::value_type v) + { + out->append(1, v); + return *this; + } + + typedef std::ptrdiff_t difference_type; + typedef typename S::value_type value_type; + typedef value_type* pointer; + typedef value_type& reference; + typedef std::output_iterator_tag iterator_category; +}; + +template +OutputIterator regex_format_imp(OutputIterator out, + const match_results& m, + ForwardIter p1, ForwardIter p2, + match_flag_type flags, + const traits& t + ) +{ + if(flags & regex_constants::format_literal) + { + return BOOST_REGEX_DETAIL_NS::copy(p1, p2, out); + } + + BOOST_REGEX_DETAIL_NS::basic_regex_formatter< + OutputIterator, + match_results, + traits, ForwardIter> f(out, m, t); + return f.format(p1, p2, flags); +} + +template +struct has_const_iterator +{ + template + static typename U::const_iterator tester(U*); + static char tester(...); + + static T* get(); + + static const bool value = sizeof(tester(get())) != sizeof(char); +}; + +struct any_type +{ + template + any_type(const T&); + template + any_type(const T&, const U&); + template + any_type(const T&, const U&, const V&); +}; +typedef char no_type; +typedef char (&unary_type)[2]; +typedef char (&binary_type)[3]; +typedef char (&ternary_type)[4]; + +no_type check_is_formatter(unary_type, binary_type, ternary_type); +template +unary_type check_is_formatter(T const &, binary_type, ternary_type); +template +binary_type check_is_formatter(unary_type, T const &, ternary_type); +template +binary_type check_is_formatter(T const &, U const &, ternary_type); +template +ternary_type check_is_formatter(unary_type, binary_type, T const &); +template +ternary_type check_is_formatter(T const &, binary_type, U const &); +template +ternary_type check_is_formatter(unary_type, T const &, U const &); +template +ternary_type check_is_formatter(T const &, U const &, V const &); + +struct unary_binary_ternary +{ + typedef unary_type (*unary_fun)(any_type); + typedef binary_type (*binary_fun)(any_type, any_type); + typedef ternary_type (*ternary_fun)(any_type, any_type, any_type); + operator unary_fun(); + operator binary_fun(); + operator ternary_fun(); +}; + +template::value> +struct formatter_wrapper + : Formatter + , unary_binary_ternary +{ + formatter_wrapper(){} +}; + +template +struct formatter_wrapper + : unary_binary_ternary +{ + operator Formatter *(); +}; + +template +struct formatter_wrapper + : unary_binary_ternary +{ + operator Formatter *(); +}; + +template +struct do_unwrap_reference +{ + typedef T type; +}; +template +struct do_unwrap_reference > +{ + typedef T type; +}; + +template +T& do_unwrap_ref(T& r) { return r; } +template +T& do_unwrap_ref(std::reference_wrapper const& r) { return r.get(); } + +template +struct format_traits_imp +{ +private: + // + // F must be a pointer, a function, or a class with a function call operator: + // + static_assert((::std::is_pointer::value || ::std::is_function::value || ::std::is_class::value), "The functor must be a pointer or a class with a function call operator"); + static formatter_wrapper::type> f; + static M m; + static O out; + static boost::regex_constants::match_flag_type flags; +public: + static const int value = sizeof(check_is_formatter(f(m), f(m, out), f(m, out, flags))); +}; + +template +struct format_traits +{ +public: + // + // Type is std::integral_constant where N is one of: + // + // 0 : F is a pointer to a presumably null-terminated string. + // 1 : F is a character-container such as a std::string. + // 2 : F is a Unary Functor. + // 3 : F is a Binary Functor. + // 4 : F is a Ternary Functor. + // + typedef typename std::conditional< + std::is_pointer::value && !std::is_function::type>::value, + std::integral_constant, + typename std::conditional< + has_const_iterator::value, + std::integral_constant, + std::integral_constant::value> + >::type + >::type type; + // + // This static assertion will fail if the functor passed does not accept + // the same type of arguments passed. + // + static_assert( std::is_class::value && !has_const_iterator::value ? (type::value > 1) : true, "Argument mismatch in Functor type"); +}; + +template +struct format_functor3 +{ + format_functor3(Base b) : func(b) {} + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f) + { + return do_unwrap_ref(func)(m, i, f); + } + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&) + { + return (*this)(m, i, f); + } +private: + Base func; + format_functor3(const format_functor3&); + format_functor3& operator=(const format_functor3&); +}; + +template +struct format_functor2 +{ + format_functor2(Base b) : func(b) {} + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type /*f*/) + { + return do_unwrap_ref(func)(m, i); + } + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&) + { + return (*this)(m, i, f); + } +private: + Base func; + format_functor2(const format_functor2&); + format_functor2& operator=(const format_functor2&); +}; + +template +struct format_functor1 +{ + format_functor1(Base b) : func(b) {} + + template + OutputIter do_format_string(const S& s, OutputIter i) + { + return std::copy(s.begin(), s.end(), i); + } + template + inline OutputIter do_format_string(const S* s, OutputIter i) + { + while(s && *s) + { + *i = *s; + ++i; + ++s; + } + return i; + } + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type /*f*/) + { + return do_format_string(do_unwrap_ref(func)(m), i); + } + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&) + { + return (*this)(m, i, f); + } +private: + Base func; + format_functor1(const format_functor1&); + format_functor1& operator=(const format_functor1&); +}; + +template +struct format_functor_c_string +{ + format_functor_c_string(const charT* ps) : func(ps) {} + + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits& t = Traits()) + { + //typedef typename Match::char_type char_type; + const charT* end = func; + while(*end) ++end; + return regex_format_imp(i, m, func, end, f, t); + } +private: + const charT* func; + format_functor_c_string(const format_functor_c_string&); + format_functor_c_string& operator=(const format_functor_c_string&); +}; + +template +struct format_functor_container +{ + format_functor_container(const Container& c) : func(c) {} + + template + OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits& t = Traits()) + { + //typedef typename Match::char_type char_type; + return BOOST_REGEX_DETAIL_NS::regex_format_imp(i, m, func.begin(), func.end(), f, t); + } +private: + const Container& func; + format_functor_container(const format_functor_container&); + format_functor_container& operator=(const format_functor_container&); +}; + +template > +struct compute_functor_type +{ + typedef typename format_traits::type tag; + typedef typename std::remove_cv< typename std::remove_pointer::type>::type maybe_char_type; + + typedef typename std::conditional< + tag::value == 0, format_functor_c_string, + typename std::conditional< + tag::value == 1, format_functor_container, + typename std::conditional< + tag::value == 2, format_functor1, + typename std::conditional< + tag::value == 3, format_functor2, + format_functor3 + >::type + >::type + >::type + >::type type; +}; + +} // namespace BOOST_REGEX_DETAIL_NS + +template +inline OutputIterator regex_format(OutputIterator out, + const match_results& m, + Functor fmt, + match_flag_type flags = format_all + ) +{ + return m.format(out, fmt, flags); +} + +template +inline std::basic_string::char_type> regex_format(const match_results& m, + Functor fmt, + match_flag_type flags = format_all) +{ + return m.format(fmt, flags); +} + +} // namespace boost + +#endif // BOOST_REGEX_FORMAT_HPP + + + + + + diff --git a/boost/regex/v5/regex_fwd.hpp b/boost/regex/v5/regex_fwd.hpp new file mode 100644 index 00000000..3076b069 --- /dev/null +++ b/boost/regex/v5/regex_fwd.hpp @@ -0,0 +1,73 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_fwd.cpp + * VERSION see + * DESCRIPTION: Forward declares boost::basic_regex<> and + * associated typedefs. + */ + +#ifndef BOOST_REGEX_FWD_HPP_INCLUDED +#define BOOST_REGEX_FWD_HPP_INCLUDED + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif + +// +// define BOOST_REGEX_NO_FWD if this +// header doesn't work! +// +#ifdef BOOST_REGEX_NO_FWD +# ifndef BOOST_RE_REGEX_HPP +# include +# endif +#else + +namespace boost{ + +template +class cpp_regex_traits; +template +struct c_regex_traits; +template +class w32_regex_traits; + +#ifdef BOOST_REGEX_USE_WIN32_LOCALE +template > +struct regex_traits; +#elif defined(BOOST_REGEX_USE_CPP_LOCALE) +template > +struct regex_traits; +#else +template > +struct regex_traits; +#endif + +template > +class basic_regex; + +typedef basic_regex > regex; +#ifndef BOOST_NO_WREGEX +typedef basic_regex > wregex; +#endif + +} // namespace boost + +#endif // BOOST_REGEX_NO_FWD + +#endif + + + + diff --git a/boost/regex/v5/regex_grep.hpp b/boost/regex/v5/regex_grep.hpp new file mode 100644 index 00000000..6cd625d6 --- /dev/null +++ b/boost/regex/v5/regex_grep.hpp @@ -0,0 +1,98 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_grep.hpp + * VERSION see + * DESCRIPTION: Provides regex_grep implementation. + */ + +#ifndef BOOST_REGEX_V5_REGEX_GREP_HPP +#define BOOST_REGEX_V5_REGEX_GREP_HPP + + +namespace boost{ + +// +// regex_grep: +// find all non-overlapping matches within the sequence first last: +// +template +inline unsigned int regex_grep(Predicate foo, + BidiIterator first, + BidiIterator last, + const basic_regex& e, + match_flag_type flags = match_default) +{ + if(e.flags() & regex_constants::failbit) + return false; + + typedef typename match_results::allocator_type match_allocator_type; + + match_results m; + BOOST_REGEX_DETAIL_NS::perl_matcher matcher(first, last, m, e, flags, first); + unsigned int count = 0; + while(matcher.find()) + { + ++count; + if(0 == foo(m)) + return count; // caller doesn't want to go on + if(m[0].second == last) + return count; // we've reached the end, don't try and find an extra null match. + if(m.length() == 0) + { + if(m[0].second == last) + return count; + // we found a NULL-match, now try to find + // a non-NULL one at the same position: + match_results m2(m); + matcher.setf(match_not_null | match_continuous); + if(matcher.find()) + { + ++count; + if(0 == foo(m)) + return count; + } + else + { + // reset match back to where it was: + m = m2; + } + matcher.unsetf((match_not_null | match_continuous) & ~flags); + } + } + return count; +} + +// +// regex_grep convenience interfaces: +// +template +inline unsigned int regex_grep(Predicate foo, const charT* str, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, str, str + traits::length(str), e, flags); +} + +template +inline unsigned int regex_grep(Predicate foo, const std::basic_string& s, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_grep(foo, s.begin(), s.end(), e, flags); +} + +} // namespace boost + +#endif // BOOST_REGEX_V5_REGEX_GREP_HPP + diff --git a/boost/regex/v5/regex_iterator.hpp b/boost/regex/v5/regex_iterator.hpp new file mode 100644 index 00000000..b2e9d2ce --- /dev/null +++ b/boost/regex/v5/regex_iterator.hpp @@ -0,0 +1,173 @@ +/* + * + * Copyright (c) 2003 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_iterator.hpp + * VERSION see + * DESCRIPTION: Provides regex_iterator implementation. + */ + +#ifndef BOOST_REGEX_V5_REGEX_ITERATOR_HPP +#define BOOST_REGEX_V5_REGEX_ITERATOR_HPP + +#include + +namespace boost{ + +template +class regex_iterator_implementation +{ + typedef basic_regex regex_type; + + match_results what; // current match + BidirectionalIterator base; // start of sequence + BidirectionalIterator end; // end of sequence + const regex_type re; // the expression + match_flag_type flags; // flags for matching + +public: + regex_iterator_implementation(const regex_type* p, BidirectionalIterator last, match_flag_type f) + : base(), end(last), re(*p), flags(f){} + regex_iterator_implementation(const regex_iterator_implementation& other) + :what(other.what), base(other.base), end(other.end), re(other.re), flags(other.flags){} + bool init(BidirectionalIterator first) + { + base = first; + return regex_search(first, end, what, re, flags); + } + bool compare(const regex_iterator_implementation& that) + { + if(this == &that) return true; + return (&re.get_data() == &that.re.get_data()) && (end == that.end) && (flags == that.flags) && (what[0].first == that.what[0].first) && (what[0].second == that.what[0].second); + } + const match_results& get() + { return what; } + bool next() + { + //if(what.prefix().first != what[0].second) + // flags |= match_prev_avail; + BidirectionalIterator next_start = what[0].second; + match_flag_type f(flags); + if(!what.length() || (f & regex_constants::match_posix)) + f |= regex_constants::match_not_initial_null; + //if(base != next_start) + // f |= regex_constants::match_not_bob; + bool result = regex_search(next_start, end, what, re, f, base); + if(result) + what.set_base(base); + return result; + } +private: + regex_iterator_implementation& operator=(const regex_iterator_implementation&); +}; + +template ::value_type, + class traits = regex_traits > +class regex_iterator +{ +private: + typedef regex_iterator_implementation impl; + typedef std::shared_ptr pimpl; +public: + typedef basic_regex regex_type; + typedef match_results value_type; + typedef typename std::iterator_traits::difference_type + difference_type; + typedef const value_type* pointer; + typedef const value_type& reference; + typedef std::forward_iterator_tag iterator_category; + + regex_iterator(){} + regex_iterator(BidirectionalIterator a, BidirectionalIterator b, + const regex_type& re, + match_flag_type m = match_default) + : pdata(new impl(&re, b, m)) + { + if(!pdata->init(a)) + { + pdata.reset(); + } + } + regex_iterator(const regex_iterator& that) + : pdata(that.pdata) {} + regex_iterator& operator=(const regex_iterator& that) + { + pdata = that.pdata; + return *this; + } + bool operator==(const regex_iterator& that)const + { + if((pdata.get() == 0) || (that.pdata.get() == 0)) + return pdata.get() == that.pdata.get(); + return pdata->compare(*(that.pdata.get())); + } + bool operator!=(const regex_iterator& that)const + { return !(*this == that); } + const value_type& operator*()const + { return pdata->get(); } + const value_type* operator->()const + { return &(pdata->get()); } + regex_iterator& operator++() + { + cow(); + if(0 == pdata->next()) + { + pdata.reset(); + } + return *this; + } + regex_iterator operator++(int) + { + regex_iterator result(*this); + ++(*this); + return result; + } +private: + + pimpl pdata; + + void cow() + { + // copy-on-write + if(pdata.get() && (pdata.use_count() > 1)) + { + pdata.reset(new impl(*(pdata.get()))); + } + } +}; + +typedef regex_iterator cregex_iterator; +typedef regex_iterator sregex_iterator; +#ifndef BOOST_NO_WREGEX +typedef regex_iterator wcregex_iterator; +typedef regex_iterator wsregex_iterator; +#endif + +// make_regex_iterator: +template +inline regex_iterator make_regex_iterator(const charT* p, const basic_regex& e, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_iterator(p, p+traits::length(p), e, m); +} +template +inline regex_iterator::const_iterator, charT, traits> make_regex_iterator(const std::basic_string& p, const basic_regex& e, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_iterator::const_iterator, charT, traits>(p.begin(), p.end(), e, m); +} + +} // namespace boost + +#endif // BOOST_REGEX_V5_REGEX_ITERATOR_HPP + diff --git a/boost/regex/v5/regex_match.hpp b/boost/regex/v5/regex_match.hpp new file mode 100644 index 00000000..21753576 --- /dev/null +++ b/boost/regex/v5/regex_match.hpp @@ -0,0 +1,92 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_match.hpp + * VERSION see + * DESCRIPTION: Regular expression matching algorithms. + * Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + + +#ifndef BOOST_REGEX_MATCH_HPP +#define BOOST_REGEX_MATCH_HPP + +namespace boost{ + +// +// proc regex_match +// returns true if the specified regular expression matches +// the whole of the input. Fills in what matched in m. +// +template +bool regex_match(BidiIterator first, BidiIterator last, + match_results& m, + const basic_regex& e, + match_flag_type flags = match_default) +{ + BOOST_REGEX_DETAIL_NS::perl_matcher matcher(first, last, m, e, flags, first); + return matcher.match(); +} +template +bool regex_match(iterator first, iterator last, + const basic_regex& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(first, last, m, e, flags | regex_constants::match_any); +} +// +// query_match convenience interfaces: +// +template +inline bool regex_match(const charT* str, + match_results& m, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + traits::length(str), m, e, flags); +} + +template +inline bool regex_match(const std::basic_string& s, + match_results::const_iterator, Allocator>& m, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +template +inline bool regex_match(const charT* str, + const basic_regex& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(str, str + traits::length(str), m, e, flags | regex_constants::match_any); +} + +template +inline bool regex_match(const std::basic_string& s, + const basic_regex& e, + match_flag_type flags = match_default) +{ + typedef typename std::basic_string::const_iterator iterator; + match_results m; + return regex_match(s.begin(), s.end(), m, e, flags | regex_constants::match_any); +} + + +} // namespace boost + +#endif // BOOST_REGEX_MATCH_HPP + diff --git a/boost/regex/v5/regex_merge.hpp b/boost/regex/v5/regex_merge.hpp new file mode 100644 index 00000000..a5103c53 --- /dev/null +++ b/boost/regex/v5/regex_merge.hpp @@ -0,0 +1,71 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_format.hpp + * VERSION see + * DESCRIPTION: Provides formatting output routines for search and replace + * operations. Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_V5_REGEX_MERGE_HPP +#define BOOST_REGEX_V5_REGEX_MERGE_HPP + + +namespace boost{ + +template +inline OutputIterator regex_merge(OutputIterator out, + Iterator first, + Iterator last, + const basic_regex& e, + const charT* fmt, + match_flag_type flags = match_default) +{ + return regex_replace(out, first, last, e, fmt, flags); +} + +template +inline OutputIterator regex_merge(OutputIterator out, + Iterator first, + Iterator last, + const basic_regex& e, + const std::basic_string& fmt, + match_flag_type flags = match_default) +{ + return regex_merge(out, first, last, e, fmt.c_str(), flags); +} + +template +inline std::basic_string regex_merge(const std::basic_string& s, + const basic_regex& e, + const charT* fmt, + match_flag_type flags = match_default) +{ + return regex_replace(s, e, fmt, flags); +} + +template +inline std::basic_string regex_merge(const std::basic_string& s, + const basic_regex& e, + const std::basic_string& fmt, + match_flag_type flags = match_default) +{ + return regex_replace(s, e, fmt, flags); +} + +} // namespace boost + +#endif // BOOST_REGEX_V5_REGEX_MERGE_HPP + + diff --git a/boost/regex/v5/regex_raw_buffer.hpp b/boost/regex/v5/regex_raw_buffer.hpp new file mode 100644 index 00000000..443c57a2 --- /dev/null +++ b/boost/regex/v5/regex_raw_buffer.hpp @@ -0,0 +1,213 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_raw_buffer.hpp + * VERSION see + * DESCRIPTION: Raw character buffer for regex code. + * Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_RAW_BUFFER_HPP +#define BOOST_REGEX_RAW_BUFFER_HPP + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif + +#include +#include + +namespace boost{ + namespace BOOST_REGEX_DETAIL_NS{ + +struct empty_padding{}; + +union padding +{ + void* p; + unsigned int i; +}; + +template +struct padding3 +{ + enum{ + padding_size = 8, + padding_mask = 7 + }; +}; + +template<> +struct padding3<2> +{ + enum{ + padding_size = 2, + padding_mask = 1 + }; +}; + +template<> +struct padding3<4> +{ + enum{ + padding_size = 4, + padding_mask = 3 + }; +}; + +template<> +struct padding3<8> +{ + enum{ + padding_size = 8, + padding_mask = 7 + }; +}; + +template<> +struct padding3<16> +{ + enum{ + padding_size = 16, + padding_mask = 15 + }; +}; + +enum{ + padding_size = padding3::padding_size, + padding_mask = padding3::padding_mask +}; + +// +// class raw_storage +// basically this is a simplified vector +// this is used by basic_regex for expression storage +// + +class raw_storage +{ +public: + typedef std::size_t size_type; + typedef unsigned char* pointer; +private: + pointer last, start, end; +public: + + raw_storage(); + raw_storage(size_type n); + + ~raw_storage() + { + ::operator delete(start); + } + + void resize(size_type n) + { + size_type newsize = start ? last - start : 1024; + while (newsize < n) + newsize *= 2; + size_type datasize = end - start; + // extend newsize to WORD/DWORD boundary: + newsize = (newsize + padding_mask) & ~(padding_mask); + + // allocate and copy data: + pointer ptr = static_cast(::operator new(newsize)); + BOOST_REGEX_NOEH_ASSERT(ptr) + if (start) + std::memcpy(ptr, start, datasize); + + // get rid of old buffer: + ::operator delete(start); + + // and set up pointers: + start = ptr; + end = ptr + datasize; + last = ptr + newsize; + } + + void* extend(size_type n) + { + if(size_type(last - end) < n) + resize(n + (end - start)); + pointer result = end; + end += n; + return result; + } + + void* insert(size_type pos, size_type n) + { + BOOST_REGEX_ASSERT(pos <= size_type(end - start)); + if (size_type(last - end) < n) + resize(n + (end - start)); + void* result = start + pos; + std::memmove(start + pos + n, start + pos, (end - start) - pos); + end += n; + return result; + } + + size_type size() + { + return size_type(end - start); + } + + size_type capacity() + { + return size_type(last - start); + } + + void* data()const + { + return start; + } + + size_type index(void* ptr) + { + return size_type(static_cast(ptr) - static_cast(data())); + } + + void clear() + { + end = start; + } + + void align() + { + // move end up to a boundary: + end = start + (((end - start) + padding_mask) & ~padding_mask); + } + void swap(raw_storage& that) + { + std::swap(start, that.start); + std::swap(end, that.end); + std::swap(last, that.last); + } +}; + +inline raw_storage::raw_storage() +{ + last = start = end = 0; +} + +inline raw_storage::raw_storage(size_type n) +{ + start = end = static_cast(::operator new(n)); + BOOST_REGEX_NOEH_ASSERT(start) + last = start + n; +} + +} // namespace BOOST_REGEX_DETAIL_NS +} // namespace boost + +#endif + diff --git a/boost/regex/v5/regex_replace.hpp b/boost/regex/v5/regex_replace.hpp new file mode 100644 index 00000000..75f8894f --- /dev/null +++ b/boost/regex/v5/regex_replace.hpp @@ -0,0 +1,77 @@ +/* + * + * Copyright (c) 1998-2009 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_format.hpp + * VERSION see + * DESCRIPTION: Provides formatting output routines for search and replace + * operations. Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_V5_REGEX_REPLACE_HPP +#define BOOST_REGEX_V5_REGEX_REPLACE_HPP + + +namespace boost{ + +template +OutputIterator regex_replace(OutputIterator out, + BidirectionalIterator first, + BidirectionalIterator last, + const basic_regex& e, + Formatter fmt, + match_flag_type flags = match_default) +{ + regex_iterator i(first, last, e, flags); + regex_iterator j; + if(i == j) + { + if(!(flags & regex_constants::format_no_copy)) + out = BOOST_REGEX_DETAIL_NS::copy(first, last, out); + } + else + { + BidirectionalIterator last_m(first); + while(i != j) + { + if(!(flags & regex_constants::format_no_copy)) + out = BOOST_REGEX_DETAIL_NS::copy(i->prefix().first, i->prefix().second, out); + out = i->format(out, fmt, flags, e); + last_m = (*i)[0].second; + if(flags & regex_constants::format_first_only) + break; + ++i; + } + if(!(flags & regex_constants::format_no_copy)) + out = BOOST_REGEX_DETAIL_NS::copy(last_m, last, out); + } + return out; +} + +template +std::basic_string regex_replace(const std::basic_string& s, + const basic_regex& e, + Formatter fmt, + match_flag_type flags = match_default) +{ + std::basic_string result; + BOOST_REGEX_DETAIL_NS::string_out_iterator > i(result); + regex_replace(i, s.begin(), s.end(), e, fmt, flags); + return result; +} + +} // namespace boost + +#endif // BOOST_REGEX_V5_REGEX_REPLACE_HPP + + diff --git a/boost/regex/v5/regex_search.hpp b/boost/regex/v5/regex_search.hpp new file mode 100644 index 00000000..d0addb19 --- /dev/null +++ b/boost/regex/v5/regex_search.hpp @@ -0,0 +1,103 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_search.hpp + * VERSION see + * DESCRIPTION: Provides regex_search implementation. + */ + +#ifndef BOOST_REGEX_V5_REGEX_SEARCH_HPP +#define BOOST_REGEX_V5_REGEX_SEARCH_HPP + + +namespace boost{ + +template +bool regex_search(BidiIterator first, BidiIterator last, + match_results& m, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_search(first, last, m, e, flags, first); +} + +template +bool regex_search(BidiIterator first, BidiIterator last, + match_results& m, + const basic_regex& e, + match_flag_type flags, + BidiIterator base) +{ + if(e.flags() & regex_constants::failbit) + return false; + + BOOST_REGEX_DETAIL_NS::perl_matcher matcher(first, last, m, e, flags, base); + return matcher.find(); +} + +// +// regex_search convenience interfaces: +// +template +inline bool regex_search(const charT* str, + match_results& m, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_search(str, str + traits::length(str), m, e, flags); +} + +template +inline bool regex_search(const std::basic_string& s, + match_results::const_iterator, Allocator>& m, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_search(s.begin(), s.end(), m, e, flags); +} + +template +bool regex_search(BidiIterator first, BidiIterator last, + const basic_regex& e, + match_flag_type flags = match_default) +{ + if(e.flags() & regex_constants::failbit) + return false; + + match_results m; + typedef typename match_results::allocator_type match_alloc_type; + BOOST_REGEX_DETAIL_NS::perl_matcher matcher(first, last, m, e, flags | regex_constants::match_any, first); + return matcher.find(); +} + +template +inline bool regex_search(const charT* str, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_search(str, str + traits::length(str), e, flags); +} + +template +inline bool regex_search(const std::basic_string& s, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_search(s.begin(), s.end(), e, flags); +} + +} // namespace boost + +#endif // BOOST_REGEX_V5_REGEX_SEARCH_HPP + + diff --git a/boost/regex/v5/regex_split.hpp b/boost/regex/v5/regex_split.hpp new file mode 100644 index 00000000..8d932896 --- /dev/null +++ b/boost/regex/v5/regex_split.hpp @@ -0,0 +1,152 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_split.hpp + * VERSION see + * DESCRIPTION: Implements regex_split and associated functions. + * Note this is an internal header file included + * by regex.hpp, do not include on its own. + */ + +#ifndef BOOST_REGEX_SPLIT_HPP +#define BOOST_REGEX_SPLIT_HPP + +namespace boost{ + +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +#if BOOST_REGEX_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +namespace BOOST_REGEX_DETAIL_NS{ + +template +const basic_regex& get_default_expression(charT) +{ + static const charT expression_text[4] = { '\\', 's', '+', '\00', }; + static const basic_regex e(expression_text); + return e; +} + +template +class split_pred +{ + typedef std::basic_string string_type; + typedef typename string_type::const_iterator iterator_type; + iterator_type* p_last; + OutputIterator* p_out; + std::size_t* p_max; + std::size_t initial_max; +public: + split_pred(iterator_type* a, OutputIterator* b, std::size_t* c) + : p_last(a), p_out(b), p_max(c), initial_max(*c) {} + + bool operator()(const match_results& what); +}; + +template +bool split_pred::operator() + (const match_results& what) +{ + *p_last = what[0].second; + if(what.size() > 1) + { + // output sub-expressions only: + for(unsigned i = 1; i < what.size(); ++i) + { + *(*p_out) = what.str(i); + ++(*p_out); + if(0 == --*p_max) return false; + } + return *p_max != 0; + } + else + { + // output $` only if it's not-null or not at the start of the input: + const sub_match& sub = what[-1]; + if((sub.first != sub.second) || (*p_max != initial_max)) + { + *(*p_out) = sub.str(); + ++(*p_out); + return --*p_max; + } + } + // + // initial null, do nothing: + return true; +} + +} // namespace BOOST_REGEX_DETAIL_NS + +template +std::size_t regex_split(OutputIterator out, + std::basic_string& s, + const basic_regex& e, + match_flag_type flags, + std::size_t max_split) +{ + typedef typename std::basic_string::const_iterator ci_t; + //typedef typename match_results::allocator_type match_allocator; + ci_t last = s.begin(); + std::size_t init_size = max_split; + BOOST_REGEX_DETAIL_NS::split_pred pred(&last, &out, &max_split); + ci_t i, j; + i = s.begin(); + j = s.end(); + regex_grep(pred, i, j, e, flags); + // + // if there is still input left, do a final push as long as max_split + // is not exhausted, and we're not splitting sub-expressions rather + // than whitespace: + if(max_split && (last != s.end()) && (e.mark_count() == 0)) + { + *out = std::basic_string((ci_t)last, (ci_t)s.end()); + ++out; + last = s.end(); + --max_split; + } + // + // delete from the string everything that has been processed so far: + s.erase(0, last - s.begin()); + // + // return the number of new records pushed: + return init_size - max_split; +} + +template +inline std::size_t regex_split(OutputIterator out, + std::basic_string& s, + const basic_regex& e, + match_flag_type flags = match_default) +{ + return regex_split(out, s, e, flags, UINT_MAX); +} + +template +inline std::size_t regex_split(OutputIterator out, + std::basic_string& s) +{ + return regex_split(out, s, BOOST_REGEX_DETAIL_NS::get_default_expression(charT(0)), match_default, UINT_MAX); +} + +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif + +} // namespace boost + +#endif + + diff --git a/boost/regex/v5/regex_token_iterator.hpp b/boost/regex/v5/regex_token_iterator.hpp new file mode 100644 index 00000000..16832746 --- /dev/null +++ b/boost/regex/v5/regex_token_iterator.hpp @@ -0,0 +1,255 @@ +/* + * + * Copyright (c) 2003 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_token_iterator.hpp + * VERSION see + * DESCRIPTION: Provides regex_token_iterator implementation. + */ + +#ifndef BOOST_REGEX_V5_REGEX_TOKEN_ITERATOR_HPP +#define BOOST_REGEX_V5_REGEX_TOKEN_ITERATOR_HPP + +#include + +namespace boost{ + +template +class regex_token_iterator_implementation +{ + typedef basic_regex regex_type; + typedef sub_match value_type; + + match_results what; // current match + BidirectionalIterator base; // start of search area + BidirectionalIterator end; // end of search area + const regex_type re; // the expression + match_flag_type flags; // match flags + value_type result; // the current string result + int N; // the current sub-expression being enumerated + std::vector subs; // the sub-expressions to enumerate + +public: + regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, int sub, match_flag_type f) + : end(last), re(*p), flags(f), N(0){ subs.push_back(sub); } + regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const std::vector& v, match_flag_type f) + : end(last), re(*p), flags(f), N(0), subs(v){} + template + regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const int (&submatches)[CN], match_flag_type f) + : end(last), re(*p), flags(f), N(0) + { + for(std::size_t i = 0; i < CN; ++i) + { + subs.push_back(submatches[i]); + } + } + regex_token_iterator_implementation(const regex_token_iterator_implementation& other) = default; + bool init(BidirectionalIterator first) + { + N = 0; + base = first; + if(regex_search(first, end, what, re, flags, base) == true) + { + N = 0; + result = ((subs[N] == -1) ? what.prefix() : what[(int)subs[N]]); + return true; + } + else if((subs[N] == -1) && (first != end)) + { + result.first = first; + result.second = end; + result.matched = (first != end); + N = -1; + return true; + } + return false; + } + bool compare(const regex_token_iterator_implementation& that) + { + if(this == &that) return true; + return (&re.get_data() == &that.re.get_data()) + && (end == that.end) + && (flags == that.flags) + && (N == that.N) + && (what[0].first == that.what[0].first) + && (what[0].second == that.what[0].second); + } + const value_type& get() + { return result; } + bool next() + { + if(N == -1) + return false; + if(N+1 < (int)subs.size()) + { + ++N; + result =((subs[N] == -1) ? what.prefix() : what[subs[N]]); + return true; + } + //if(what.prefix().first != what[0].second) + // flags |= /*match_prev_avail |*/ regex_constants::match_not_bob; + BidirectionalIterator last_end(what[0].second); + if(regex_search(last_end, end, what, re, ((what[0].first == what[0].second) ? flags | regex_constants::match_not_initial_null : flags), base)) + { + N =0; + result =((subs[N] == -1) ? what.prefix() : what[subs[N]]); + return true; + } + else if((last_end != end) && (subs[0] == -1)) + { + N =-1; + result.first = last_end; + result.second = end; + result.matched = (last_end != end); + return true; + } + return false; + } +private: + regex_token_iterator_implementation& operator=(const regex_token_iterator_implementation&); +}; + +template ::value_type, + class traits = regex_traits > +class regex_token_iterator +{ +private: + typedef regex_token_iterator_implementation impl; + typedef std::shared_ptr pimpl; +public: + typedef basic_regex regex_type; + typedef sub_match value_type; + typedef typename std::iterator_traits::difference_type + difference_type; + typedef const value_type* pointer; + typedef const value_type& reference; + typedef std::forward_iterator_tag iterator_category; + + regex_token_iterator(){} + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + int submatch = 0, match_flag_type m = match_default) + : pdata(new impl(&re, b, submatch, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + const std::vector& submatches, match_flag_type m = match_default) + : pdata(new impl(&re, b, submatches, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } + template + regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, const regex_type& re, + const int (&submatches)[N], match_flag_type m = match_default) + : pdata(new impl(&re, b, submatches, m)) + { + if(!pdata->init(a)) + pdata.reset(); + } + regex_token_iterator(const regex_token_iterator& that) + : pdata(that.pdata) {} + regex_token_iterator& operator=(const regex_token_iterator& that) + { + pdata = that.pdata; + return *this; + } + bool operator==(const regex_token_iterator& that)const + { + if((pdata.get() == 0) || (that.pdata.get() == 0)) + return pdata.get() == that.pdata.get(); + return pdata->compare(*(that.pdata.get())); + } + bool operator!=(const regex_token_iterator& that)const + { return !(*this == that); } + const value_type& operator*()const + { return pdata->get(); } + const value_type* operator->()const + { return &(pdata->get()); } + regex_token_iterator& operator++() + { + cow(); + if(0 == pdata->next()) + { + pdata.reset(); + } + return *this; + } + regex_token_iterator operator++(int) + { + regex_token_iterator result(*this); + ++(*this); + return result; + } +private: + + pimpl pdata; + + void cow() + { + // copy-on-write + if(pdata.get() && (pdata.use_count() > 1)) + { + pdata.reset(new impl(*(pdata.get()))); + } + } +}; + +typedef regex_token_iterator cregex_token_iterator; +typedef regex_token_iterator sregex_token_iterator; +#ifndef BOOST_NO_WREGEX +typedef regex_token_iterator wcregex_token_iterator; +typedef regex_token_iterator wsregex_token_iterator; +#endif + +template +inline regex_token_iterator make_regex_token_iterator(const charT* p, const basic_regex& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator(p, p+traits::length(p), e, submatch, m); +} +template +inline regex_token_iterator::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string& p, const basic_regex& e, int submatch = 0, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m); +} +template +inline regex_token_iterator make_regex_token_iterator(const charT* p, const basic_regex& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator(p, p+traits::length(p), e, submatch, m); +} +template +inline regex_token_iterator::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string& p, const basic_regex& e, const int (&submatch)[N], regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m); +} +template +inline regex_token_iterator make_regex_token_iterator(const charT* p, const basic_regex& e, const std::vector& submatch, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator(p, p+traits::length(p), e, submatch, m); +} +template +inline regex_token_iterator::const_iterator, charT, traits> make_regex_token_iterator(const std::basic_string& p, const basic_regex& e, const std::vector& submatch, regex_constants::match_flag_type m = regex_constants::match_default) +{ + return regex_token_iterator::const_iterator, charT, traits>(p.begin(), p.end(), e, submatch, m); +} + +} // namespace boost + +#endif // BOOST_REGEX_V5_REGEX_TOKEN_ITERATOR_HPP + + + + diff --git a/boost/regex/v5/regex_traits.hpp b/boost/regex/v5/regex_traits.hpp new file mode 100644 index 00000000..6c64695b --- /dev/null +++ b/boost/regex/v5/regex_traits.hpp @@ -0,0 +1,130 @@ +/* + * + * Copyright (c) 2003 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_traits.hpp + * VERSION see + * DESCRIPTION: Declares regular expression traits classes. + */ + +#ifndef BOOST_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_REGEX_TRAITS_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +# include +#endif +#include + +namespace boost{ + +template +struct regex_traits : public implementationT +{ + regex_traits() : implementationT() {} +}; + +// +// class regex_traits_wrapper. +// this is what our implementation will actually store; +// it provides default implementations of the "optional" +// interfaces that we support, in addition to the +// required "standard" ones: +// +namespace BOOST_REGEX_DETAIL_NS{ + + template + struct has_boost_extensions_tag + { + template + static double checker(U*, typename U::boost_extensions_tag* = nullptr); + static char checker(...); + static T* get(); + + static const bool value = sizeof(checker(get())) > 1; + }; + + +template +struct default_wrapper : public BaseT +{ + typedef typename BaseT::char_type char_type; + std::string error_string(::boost::regex_constants::error_type e)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::get_default_error_string(e); + } + ::boost::regex_constants::syntax_type syntax_type(char_type c)const + { + return (char_type(c & 0x7f) == c) ? get_default_syntax_type(static_cast(c)) : ::boost::regex_constants::syntax_char; + } + ::boost::regex_constants::escape_syntax_type escape_syntax_type(char_type c)const + { + return (char_type(c & 0x7f) == c) ? get_default_escape_syntax_type(static_cast(c)) : ::boost::regex_constants::escape_type_identity; + } + std::intmax_t toi(const char_type*& p1, const char_type* p2, int radix)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::global_toi(p1, p2, radix, *this); + } + char_type translate(char_type c, bool icase)const + { + return (icase ? this->translate_nocase(c) : this->translate(c)); + } + char_type translate(char_type c)const + { + return BaseT::translate(c); + } + char_type tolower(char_type c)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::global_lower(c); + } + char_type toupper(char_type c)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::global_upper(c); + } +}; + +template +struct compute_wrapper_base +{ + typedef BaseT type; +}; +template +struct compute_wrapper_base +{ + typedef default_wrapper type; +}; + +} // namespace BOOST_REGEX_DETAIL_NS + +template +struct regex_traits_wrapper + : public ::boost::BOOST_REGEX_DETAIL_NS::compute_wrapper_base< + BaseT, + ::boost::BOOST_REGEX_DETAIL_NS::has_boost_extensions_tag::value + >::type +{ + regex_traits_wrapper(){} +private: + regex_traits_wrapper(const regex_traits_wrapper&); + regex_traits_wrapper& operator=(const regex_traits_wrapper&); +}; + +} // namespace boost + +#endif // include + diff --git a/boost/regex/v5/regex_traits_defaults.hpp b/boost/regex/v5/regex_traits_defaults.hpp new file mode 100644 index 00000000..4b81441f --- /dev/null +++ b/boost/regex/v5/regex_traits_defaults.hpp @@ -0,0 +1,996 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_traits_defaults.hpp + * VERSION see + * DESCRIPTION: Declares API's for access to regex_traits default properties. + */ + +#ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED +#define BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ namespace BOOST_REGEX_DETAIL_NS{ + + +// +// helpers to suppress warnings: +// +template +inline bool is_extended(charT c) +{ + typedef typename std::make_unsigned::type unsigned_type; + return (sizeof(charT) > 1) && (static_cast(c) >= 256u); +} +inline bool is_extended(char) +{ return false; } + +inline const char* get_default_syntax(regex_constants::syntax_type n) +{ + // if the user hasn't supplied a message catalog, then this supplies + // default "messages" for us to load in the range 1-100. + const char* messages[] = { + "", + "(", + ")", + "$", + "^", + ".", + "*", + "+", + "?", + "[", + "]", + "|", + "\\", + "#", + "-", + "{", + "}", + "0123456789", + "b", + "B", + "<", + ">", + "", + "", + "A`", + "z'", + "\n", + ",", + "a", + "f", + "n", + "r", + "t", + "v", + "x", + "c", + ":", + "=", + "e", + "", + "", + "", + "", + "", + "", + "", + "", + "E", + "Q", + "X", + "C", + "Z", + "G", + "!", + "p", + "P", + "N", + "gk", + "K", + "R", + }; + + return ((n >= (sizeof(messages) / sizeof(messages[1]))) ? "" : messages[n]); +} + +inline const char* get_default_error_string(regex_constants::error_type n) +{ + static const char* const s_default_error_messages[] = { + "Success", /* REG_NOERROR 0 error_ok */ + "No match", /* REG_NOMATCH 1 error_no_match */ + "Invalid regular expression.", /* REG_BADPAT 2 error_bad_pattern */ + "Invalid collation character.", /* REG_ECOLLATE 3 error_collate */ + "Invalid character class name, collating name, or character range.", /* REG_ECTYPE 4 error_ctype */ + "Invalid or unterminated escape sequence.", /* REG_EESCAPE 5 error_escape */ + "Invalid back reference: specified capturing group does not exist.", /* REG_ESUBREG 6 error_backref */ + "Unmatched [ or [^ in character class declaration.", /* REG_EBRACK 7 error_brack */ + "Unmatched marking parenthesis ( or \\(.", /* REG_EPAREN 8 error_paren */ + "Unmatched quantified repeat operator { or \\{.", /* REG_EBRACE 9 error_brace */ + "Invalid content of repeat range.", /* REG_BADBR 10 error_badbrace */ + "Invalid range end in character class", /* REG_ERANGE 11 error_range */ + "Out of memory.", /* REG_ESPACE 12 error_space NOT USED */ + "Invalid preceding regular expression prior to repetition operator.", /* REG_BADRPT 13 error_badrepeat */ + "Premature end of regular expression", /* REG_EEND 14 error_end NOT USED */ + "Regular expression is too large.", /* REG_ESIZE 15 error_size NOT USED */ + "Unmatched ) or \\)", /* REG_ERPAREN 16 error_right_paren NOT USED */ + "Empty regular expression.", /* REG_EMPTY 17 error_empty */ + "The complexity of matching the regular expression exceeded predefined bounds. " + "Try refactoring the regular expression to make each choice made by the state machine unambiguous. " + "This exception is thrown to prevent \"eternal\" matches that take an " + "indefinite period time to locate.", /* REG_ECOMPLEXITY 18 error_complexity */ + "Ran out of stack space trying to match the regular expression.", /* REG_ESTACK 19 error_stack */ + "Invalid or unterminated Perl (?...) sequence.", /* REG_E_PERL 20 error_perl */ + "Unknown error.", /* REG_E_UNKNOWN 21 error_unknown */ + }; + + return (n > ::boost::regex_constants::error_unknown) ? s_default_error_messages[::boost::regex_constants::error_unknown] : s_default_error_messages[n]; +} + +inline regex_constants::syntax_type get_default_syntax_type(char c) +{ + // + // char_syntax determines how the compiler treats a given character + // in a regular expression. + // + static regex_constants::syntax_type char_syntax[] = { + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_newline, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /* */ // 32 + regex_constants::syntax_not, /*!*/ + regex_constants::syntax_char, /*"*/ + regex_constants::syntax_hash, /*#*/ + regex_constants::syntax_dollar, /*$*/ + regex_constants::syntax_char, /*%*/ + regex_constants::syntax_char, /*&*/ + regex_constants::escape_type_end_buffer, /*'*/ + regex_constants::syntax_open_mark, /*(*/ + regex_constants::syntax_close_mark, /*)*/ + regex_constants::syntax_star, /***/ + regex_constants::syntax_plus, /*+*/ + regex_constants::syntax_comma, /*,*/ + regex_constants::syntax_dash, /*-*/ + regex_constants::syntax_dot, /*.*/ + regex_constants::syntax_char, /*/*/ + regex_constants::syntax_digit, /*0*/ + regex_constants::syntax_digit, /*1*/ + regex_constants::syntax_digit, /*2*/ + regex_constants::syntax_digit, /*3*/ + regex_constants::syntax_digit, /*4*/ + regex_constants::syntax_digit, /*5*/ + regex_constants::syntax_digit, /*6*/ + regex_constants::syntax_digit, /*7*/ + regex_constants::syntax_digit, /*8*/ + regex_constants::syntax_digit, /*9*/ + regex_constants::syntax_colon, /*:*/ + regex_constants::syntax_char, /*;*/ + regex_constants::escape_type_left_word, /*<*/ + regex_constants::syntax_equal, /*=*/ + regex_constants::escape_type_right_word, /*>*/ + regex_constants::syntax_question, /*?*/ + regex_constants::syntax_char, /*@*/ + regex_constants::syntax_char, /*A*/ + regex_constants::syntax_char, /*B*/ + regex_constants::syntax_char, /*C*/ + regex_constants::syntax_char, /*D*/ + regex_constants::syntax_char, /*E*/ + regex_constants::syntax_char, /*F*/ + regex_constants::syntax_char, /*G*/ + regex_constants::syntax_char, /*H*/ + regex_constants::syntax_char, /*I*/ + regex_constants::syntax_char, /*J*/ + regex_constants::syntax_char, /*K*/ + regex_constants::syntax_char, /*L*/ + regex_constants::syntax_char, /*M*/ + regex_constants::syntax_char, /*N*/ + regex_constants::syntax_char, /*O*/ + regex_constants::syntax_char, /*P*/ + regex_constants::syntax_char, /*Q*/ + regex_constants::syntax_char, /*R*/ + regex_constants::syntax_char, /*S*/ + regex_constants::syntax_char, /*T*/ + regex_constants::syntax_char, /*U*/ + regex_constants::syntax_char, /*V*/ + regex_constants::syntax_char, /*W*/ + regex_constants::syntax_char, /*X*/ + regex_constants::syntax_char, /*Y*/ + regex_constants::syntax_char, /*Z*/ + regex_constants::syntax_open_set, /*[*/ + regex_constants::syntax_escape, /*\*/ + regex_constants::syntax_close_set, /*]*/ + regex_constants::syntax_caret, /*^*/ + regex_constants::syntax_char, /*_*/ + regex_constants::syntax_char, /*`*/ + regex_constants::syntax_char, /*a*/ + regex_constants::syntax_char, /*b*/ + regex_constants::syntax_char, /*c*/ + regex_constants::syntax_char, /*d*/ + regex_constants::syntax_char, /*e*/ + regex_constants::syntax_char, /*f*/ + regex_constants::syntax_char, /*g*/ + regex_constants::syntax_char, /*h*/ + regex_constants::syntax_char, /*i*/ + regex_constants::syntax_char, /*j*/ + regex_constants::syntax_char, /*k*/ + regex_constants::syntax_char, /*l*/ + regex_constants::syntax_char, /*m*/ + regex_constants::syntax_char, /*n*/ + regex_constants::syntax_char, /*o*/ + regex_constants::syntax_char, /*p*/ + regex_constants::syntax_char, /*q*/ + regex_constants::syntax_char, /*r*/ + regex_constants::syntax_char, /*s*/ + regex_constants::syntax_char, /*t*/ + regex_constants::syntax_char, /*u*/ + regex_constants::syntax_char, /*v*/ + regex_constants::syntax_char, /*w*/ + regex_constants::syntax_char, /*x*/ + regex_constants::syntax_char, /*y*/ + regex_constants::syntax_char, /*z*/ + regex_constants::syntax_open_brace, /*{*/ + regex_constants::syntax_or, /*|*/ + regex_constants::syntax_close_brace, /*}*/ + regex_constants::syntax_char, /*~*/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + }; + + return char_syntax[(unsigned char)c]; +} + +inline regex_constants::escape_syntax_type get_default_escape_syntax_type(char c) +{ + // + // char_syntax determines how the compiler treats a given character + // in a regular expression. + // + static regex_constants::escape_syntax_type char_syntax[] = { + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /* */ // 32 + regex_constants::escape_type_identity, /*!*/ + regex_constants::escape_type_identity, /*"*/ + regex_constants::escape_type_identity, /*#*/ + regex_constants::escape_type_identity, /*$*/ + regex_constants::escape_type_identity, /*%*/ + regex_constants::escape_type_identity, /*&*/ + regex_constants::escape_type_end_buffer, /*'*/ + regex_constants::syntax_open_mark, /*(*/ + regex_constants::syntax_close_mark, /*)*/ + regex_constants::escape_type_identity, /***/ + regex_constants::syntax_plus, /*+*/ + regex_constants::escape_type_identity, /*,*/ + regex_constants::escape_type_identity, /*-*/ + regex_constants::escape_type_identity, /*.*/ + regex_constants::escape_type_identity, /*/*/ + regex_constants::escape_type_decimal, /*0*/ + regex_constants::escape_type_backref, /*1*/ + regex_constants::escape_type_backref, /*2*/ + regex_constants::escape_type_backref, /*3*/ + regex_constants::escape_type_backref, /*4*/ + regex_constants::escape_type_backref, /*5*/ + regex_constants::escape_type_backref, /*6*/ + regex_constants::escape_type_backref, /*7*/ + regex_constants::escape_type_backref, /*8*/ + regex_constants::escape_type_backref, /*9*/ + regex_constants::escape_type_identity, /*:*/ + regex_constants::escape_type_identity, /*;*/ + regex_constants::escape_type_left_word, /*<*/ + regex_constants::escape_type_identity, /*=*/ + regex_constants::escape_type_right_word, /*>*/ + regex_constants::syntax_question, /*?*/ + regex_constants::escape_type_identity, /*@*/ + regex_constants::escape_type_start_buffer, /*A*/ + regex_constants::escape_type_not_word_assert, /*B*/ + regex_constants::escape_type_C, /*C*/ + regex_constants::escape_type_not_class, /*D*/ + regex_constants::escape_type_E, /*E*/ + regex_constants::escape_type_not_class, /*F*/ + regex_constants::escape_type_G, /*G*/ + regex_constants::escape_type_not_class, /*H*/ + regex_constants::escape_type_not_class, /*I*/ + regex_constants::escape_type_not_class, /*J*/ + regex_constants::escape_type_reset_start_mark, /*K*/ + regex_constants::escape_type_not_class, /*L*/ + regex_constants::escape_type_not_class, /*M*/ + regex_constants::escape_type_named_char, /*N*/ + regex_constants::escape_type_not_class, /*O*/ + regex_constants::escape_type_not_property, /*P*/ + regex_constants::escape_type_Q, /*Q*/ + regex_constants::escape_type_line_ending, /*R*/ + regex_constants::escape_type_not_class, /*S*/ + regex_constants::escape_type_not_class, /*T*/ + regex_constants::escape_type_not_class, /*U*/ + regex_constants::escape_type_not_class, /*V*/ + regex_constants::escape_type_not_class, /*W*/ + regex_constants::escape_type_X, /*X*/ + regex_constants::escape_type_not_class, /*Y*/ + regex_constants::escape_type_Z, /*Z*/ + regex_constants::escape_type_identity, /*[*/ + regex_constants::escape_type_identity, /*\*/ + regex_constants::escape_type_identity, /*]*/ + regex_constants::escape_type_identity, /*^*/ + regex_constants::escape_type_identity, /*_*/ + regex_constants::escape_type_start_buffer, /*`*/ + regex_constants::escape_type_control_a, /*a*/ + regex_constants::escape_type_word_assert, /*b*/ + regex_constants::escape_type_ascii_control, /*c*/ + regex_constants::escape_type_class, /*d*/ + regex_constants::escape_type_e, /*e*/ + regex_constants::escape_type_control_f, /*f*/ + regex_constants::escape_type_extended_backref, /*g*/ + regex_constants::escape_type_class, /*h*/ + regex_constants::escape_type_class, /*i*/ + regex_constants::escape_type_class, /*j*/ + regex_constants::escape_type_extended_backref, /*k*/ + regex_constants::escape_type_class, /*l*/ + regex_constants::escape_type_class, /*m*/ + regex_constants::escape_type_control_n, /*n*/ + regex_constants::escape_type_class, /*o*/ + regex_constants::escape_type_property, /*p*/ + regex_constants::escape_type_class, /*q*/ + regex_constants::escape_type_control_r, /*r*/ + regex_constants::escape_type_class, /*s*/ + regex_constants::escape_type_control_t, /*t*/ + regex_constants::escape_type_class, /*u*/ + regex_constants::escape_type_control_v, /*v*/ + regex_constants::escape_type_class, /*w*/ + regex_constants::escape_type_hex, /*x*/ + regex_constants::escape_type_class, /*y*/ + regex_constants::escape_type_end_buffer, /*z*/ + regex_constants::syntax_open_brace, /*{*/ + regex_constants::syntax_or, /*|*/ + regex_constants::syntax_close_brace, /*}*/ + regex_constants::escape_type_identity, /*~*/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + }; + + return char_syntax[(unsigned char)c]; +} + +// is charT c a combining character? +inline bool is_combining_implementation(std::uint_least16_t c) +{ + const std::uint_least16_t combining_ranges[] = { 0x0300, 0x0361, + 0x0483, 0x0486, + 0x0903, 0x0903, + 0x093E, 0x0940, + 0x0949, 0x094C, + 0x0982, 0x0983, + 0x09BE, 0x09C0, + 0x09C7, 0x09CC, + 0x09D7, 0x09D7, + 0x0A3E, 0x0A40, + 0x0A83, 0x0A83, + 0x0ABE, 0x0AC0, + 0x0AC9, 0x0ACC, + 0x0B02, 0x0B03, + 0x0B3E, 0x0B3E, + 0x0B40, 0x0B40, + 0x0B47, 0x0B4C, + 0x0B57, 0x0B57, + 0x0B83, 0x0B83, + 0x0BBE, 0x0BBF, + 0x0BC1, 0x0BCC, + 0x0BD7, 0x0BD7, + 0x0C01, 0x0C03, + 0x0C41, 0x0C44, + 0x0C82, 0x0C83, + 0x0CBE, 0x0CBE, + 0x0CC0, 0x0CC4, + 0x0CC7, 0x0CCB, + 0x0CD5, 0x0CD6, + 0x0D02, 0x0D03, + 0x0D3E, 0x0D40, + 0x0D46, 0x0D4C, + 0x0D57, 0x0D57, + 0x0F7F, 0x0F7F, + 0x20D0, 0x20E1, + 0x3099, 0x309A, + 0xFE20, 0xFE23, + 0xffff, 0xffff, }; + + const std::uint_least16_t* p = combining_ranges + 1; + while (*p < c) p += 2; + --p; + if ((c >= *p) && (c <= *(p + 1))) + return true; + return false; +} + +template +inline bool is_combining(charT c) +{ + return (c <= static_cast(0)) ? false : ((c >= static_cast((std::numeric_limits::max)())) ? false : is_combining_implementation(static_cast(c))); +} +template <> +inline bool is_combining(char) +{ + return false; +} +template <> +inline bool is_combining(signed char) +{ + return false; +} +template <> +inline bool is_combining(unsigned char) +{ + return false; +} +#ifdef _MSC_VER +template<> +inline bool is_combining(wchar_t c) +{ + return is_combining_implementation(static_cast(c)); +} +#elif !defined(__DECCXX) && !defined(__osf__) && !defined(__OSF__) && defined(WCHAR_MIN) && (WCHAR_MIN == 0) && !defined(BOOST_NO_INTRINSIC_WCHAR_T) +#if defined(WCHAR_MAX) && (WCHAR_MAX <= USHRT_MAX) +template<> +inline bool is_combining(wchar_t c) +{ + return is_combining_implementation(static_cast(c)); +} +#else +template<> +inline bool is_combining(wchar_t c) +{ + return (c >= (std::numeric_limits::max)()) ? false : is_combining_implementation(static_cast(c)); +} +#endif +#endif + +// +// is a charT c a line separator? +// +template +inline bool is_separator(charT c) +{ + return BOOST_REGEX_MAKE_BOOL( + (c == static_cast('\n')) + || (c == static_cast('\r')) + || (c == static_cast('\f')) + || (static_cast(c) == 0x2028u) + || (static_cast(c) == 0x2029u) + || (static_cast(c) == 0x85u)); +} +template <> +inline bool is_separator(char c) +{ + return BOOST_REGEX_MAKE_BOOL((c == '\n') || (c == '\r') || (c == '\f')); +} + +// +// get a default collating element: +// +inline std::string lookup_default_collate_name(const std::string& name) +{ + // + // these are the POSIX collating names: + // + static const char* def_coll_names[] = { + "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "alert", "backspace", "tab", "newline", + "vertical-tab", "form-feed", "carriage-return", "SO", "SI", "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", + "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "IS4", "IS3", "IS2", "IS1", "space", "exclamation-mark", + "quotation-mark", "number-sign", "dollar-sign", "percent-sign", "ampersand", "apostrophe", + "left-parenthesis", "right-parenthesis", "asterisk", "plus-sign", "comma", "hyphen", + "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", + "colon", "semicolon", "less-than-sign", "equals-sign", "greater-than-sign", + "question-mark", "commercial-at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", + "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "left-square-bracket", "backslash", + "right-square-bracket", "circumflex", "underscore", "grave-accent", "a", "b", "c", "d", "e", "f", + "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "left-curly-bracket", + "vertical-line", "right-curly-bracket", "tilde", "DEL", "", + }; + + // these multi-character collating elements + // should keep most Western-European locales + // happy - we should really localise these a + // little more - but this will have to do for + // now: + + static const char* def_multi_coll[] = { + "ae", + "Ae", + "AE", + "ch", + "Ch", + "CH", + "ll", + "Ll", + "LL", + "ss", + "Ss", + "SS", + "nj", + "Nj", + "NJ", + "dz", + "Dz", + "DZ", + "lj", + "Lj", + "LJ", + "", + }; + + unsigned int i = 0; + while (*def_coll_names[i]) + { + if (def_coll_names[i] == name) + { + return std::string(1, char(i)); + } + ++i; + } + i = 0; + while (*def_multi_coll[i]) + { + if (def_multi_coll[i] == name) + { + return def_multi_coll[i]; + } + ++i; + } + return std::string(); +} + +// +// get the state_id of a character classification, the individual +// traits classes then transform that state_id into a bitmask: +// +template +struct character_pointer_range +{ + const charT* p1; + const charT* p2; + + bool operator < (const character_pointer_range& r)const + { + return std::lexicographical_compare(p1, p2, r.p1, r.p2); + } + bool operator == (const character_pointer_range& r)const + { + // Not only do we check that the ranges are of equal size before + // calling std::equal, but there is no other algorithm available: + // not even a non-standard MS one. So forward to unchecked_equal + // in the MS case. +#ifdef __cpp_lib_robust_nonmodifying_seq_ops + return std::equal(p1, p2, r.p1, r.p2); +#elif defined(BOOST_REGEX_MSVC) + if (((p2 - p1) != (r.p2 - r.p1))) + return false; + const charT* with = r.p1; + const charT* pos = p1; + while (pos != p2) + if (*pos++ != *with++) return false; + return true; + +#else + return ((p2 - p1) == (r.p2 - r.p1)) && std::equal(p1, p2, r.p1); +#endif + } +}; +template +int get_default_class_id(const charT* p1, const charT* p2) +{ + static const charT data[73] = { + 'a', 'l', 'n', 'u', 'm', + 'a', 'l', 'p', 'h', 'a', + 'b', 'l', 'a', 'n', 'k', + 'c', 'n', 't', 'r', 'l', + 'd', 'i', 'g', 'i', 't', + 'g', 'r', 'a', 'p', 'h', + 'l', 'o', 'w', 'e', 'r', + 'p', 'r', 'i', 'n', 't', + 'p', 'u', 'n', 'c', 't', + 's', 'p', 'a', 'c', 'e', + 'u', 'n', 'i', 'c', 'o', 'd', 'e', + 'u', 'p', 'p', 'e', 'r', + 'v', + 'w', 'o', 'r', 'd', + 'x', 'd', 'i', 'g', 'i', 't', + }; + + static const character_pointer_range ranges[21] = + { + {data+0, data+5,}, // alnum + {data+5, data+10,}, // alpha + {data+10, data+15,}, // blank + {data+15, data+20,}, // cntrl + {data+20, data+21,}, // d + {data+20, data+25,}, // digit + {data+25, data+30,}, // graph + {data+29, data+30,}, // h + {data+30, data+31,}, // l + {data+30, data+35,}, // lower + {data+35, data+40,}, // print + {data+40, data+45,}, // punct + {data+45, data+46,}, // s + {data+45, data+50,}, // space + {data+57, data+58,}, // u + {data+50, data+57,}, // unicode + {data+57, data+62,}, // upper + {data+62, data+63,}, // v + {data+63, data+64,}, // w + {data+63, data+67,}, // word + {data+67, data+73,}, // xdigit + }; + const character_pointer_range* ranges_begin = ranges; + const character_pointer_range* ranges_end = ranges + (sizeof(ranges)/sizeof(ranges[0])); + + character_pointer_range t = { p1, p2, }; + const character_pointer_range* p = std::lower_bound(ranges_begin, ranges_end, t); + if((p != ranges_end) && (t == *p)) + return static_cast(p - ranges); + return -1; +} + +// +// helper functions: +// +template +std::ptrdiff_t global_length(const charT* p) +{ + std::ptrdiff_t n = 0; + while(*p) + { + ++p; + ++n; + } + return n; +} +template<> +inline std::ptrdiff_t global_length(const char* p) +{ + return (std::strlen)(p); +} +#ifndef BOOST_NO_WREGEX +template<> +inline std::ptrdiff_t global_length(const wchar_t* p) +{ + return (std::ptrdiff_t)(std::wcslen)(p); +} +#endif +template +inline charT global_lower(charT c) +{ + return c; +} +template +inline charT global_upper(charT c) +{ + return c; +} + +inline char do_global_lower(char c) +{ + return static_cast((std::tolower)((unsigned char)c)); +} + +inline char do_global_upper(char c) +{ + return static_cast((std::toupper)((unsigned char)c)); +} +#ifndef BOOST_NO_WREGEX +inline wchar_t do_global_lower(wchar_t c) +{ + return (std::towlower)(c); +} + +inline wchar_t do_global_upper(wchar_t c) +{ + return (std::towupper)(c); +} +#endif +// +// This sucks: declare template specialisations of global_lower/global_upper +// that just forward to the non-template implementation functions. We do +// this because there is one compiler (Compaq Tru64 C++) that doesn't seem +// to differentiate between templates and non-template overloads.... +// what's more, the primary template, plus all overloads have to be +// defined in the same translation unit (if one is inline they all must be) +// otherwise the "local template instantiation" compiler option can pick +// the wrong instantiation when linking: +// +template<> inline char global_lower(char c) { return do_global_lower(c); } +template<> inline char global_upper(char c) { return do_global_upper(c); } +#ifndef BOOST_NO_WREGEX +template<> inline wchar_t global_lower(wchar_t c) { return do_global_lower(c); } +template<> inline wchar_t global_upper(wchar_t c) { return do_global_upper(c); } +#endif + +template +int global_value(charT c) +{ + static const charT zero = '0'; + static const charT nine = '9'; + static const charT a = 'a'; + static const charT f = 'f'; + static const charT A = 'A'; + static const charT F = 'F'; + + if(c > f) return -1; + if(c >= a) return 10 + (c - a); + if(c > F) return -1; + if(c >= A) return 10 + (c - A); + if(c > nine) return -1; + if(c >= zero) return c - zero; + return -1; +} +template +std::intmax_t global_toi(const charT*& p1, const charT* p2, int radix, const traits& t) +{ + (void)t; // warning suppression + std::intmax_t limit = (std::numeric_limits::max)() / radix; + std::intmax_t next_value = t.value(*p1, radix); + if((p1 == p2) || (next_value < 0) || (next_value >= radix)) + return -1; + std::intmax_t result = 0; + while(p1 != p2) + { + next_value = t.value(*p1, radix); + if((next_value < 0) || (next_value >= radix)) + break; + result *= radix; + result += next_value; + ++p1; + if (result > limit) + return -1; + } + return result; +} + +template +inline typename std::enable_if<(sizeof(charT) > 1), const charT*>::type get_escape_R_string() +{ +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +# pragma warning(disable:4309 4245) +#endif + static const charT e1[] = { '(', '?', '-', 'x', ':', '(', '?', '>', '\x0D', '\x0A', '?', + '|', '[', '\x0A', '\x0B', '\x0C', static_cast(0x85), static_cast(0x2028), + static_cast(0x2029), ']', ')', ')', '\0' }; + static const charT e2[] = { '(', '?', '-', 'x', ':', '(', '?', '>', '\x0D', '\x0A', '?', + '|', '[', '\x0A', '\x0B', '\x0C', static_cast(0x85), ']', ')', ')', '\0' }; + + charT c = static_cast(0x2029u); + bool b = (static_cast(c) == 0x2029u); + + return (b ? e1 : e2); +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif +} + +template +inline typename std::enable_if<(sizeof(charT) == 1), const charT*>::type get_escape_R_string() +{ +#ifdef BOOST_REGEX_MSVC +# pragma warning(push) +# pragma warning(disable:4309 4245) +#endif + static const charT e2[] = { + static_cast('('), + static_cast('?'), + static_cast('-'), + static_cast('x'), + static_cast(':'), + static_cast('('), + static_cast('?'), + static_cast('>'), + static_cast('\x0D'), + static_cast('\x0A'), + static_cast('?'), + static_cast('|'), + static_cast('['), + static_cast('\x0A'), + static_cast('\x0B'), + static_cast('\x0C'), + static_cast('\x85'), + static_cast(']'), + static_cast(')'), + static_cast(')'), + static_cast('\0') + }; + return e2; +#ifdef BOOST_REGEX_MSVC +# pragma warning(pop) +#endif +} + +} // BOOST_REGEX_DETAIL_NS +} // boost + +#endif diff --git a/boost/regex/v5/regex_workaround.hpp b/boost/regex/v5/regex_workaround.hpp new file mode 100644 index 00000000..8cd9044c --- /dev/null +++ b/boost/regex/v5/regex_workaround.hpp @@ -0,0 +1,159 @@ +/* + * + * Copyright (c) 1998-2005 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE regex_workarounds.cpp + * VERSION see + * DESCRIPTION: Declares Misc workarounds. + */ + +#ifndef BOOST_REGEX_WORKAROUND_HPP +#define BOOST_REGEX_WORKAROUND_HPP + +#include +#include +#include +#include + +#ifndef BOOST_REGEX_STANDALONE +#include +#include +#endif + +#ifdef BOOST_REGEX_NO_BOOL +# define BOOST_REGEX_MAKE_BOOL(x) static_cast((x) ? true : false) +#else +# define BOOST_REGEX_MAKE_BOOL(x) static_cast(x) +#endif + +/***************************************************************************** + * + * helper functions pointer_construct/pointer_destroy: + * + ****************************************************************************/ + +#ifdef __cplusplus +namespace boost{ namespace BOOST_REGEX_DETAIL_NS{ + +#ifdef BOOST_REGEX_MSVC +#pragma warning (push) +#pragma warning (disable : 4100) +#endif + +template +inline void pointer_destroy(T* p) +{ p->~T(); (void)p; } + +#ifdef BOOST_REGEX_MSVC +#pragma warning (pop) +#endif + +template +inline void pointer_construct(T* p, const T& t) +{ new (p) T(t); } + +}} // namespaces +#endif + +/***************************************************************************** + * + * helper function copy: + * + ****************************************************************************/ + +#if defined(BOOST_WORKAROUND) +#if BOOST_WORKAROUND(BOOST_REGEX_MSVC, >= 1400) && defined(__STDC_WANT_SECURE_LIB__) && __STDC_WANT_SECURE_LIB__ +#define BOOST_REGEX_HAS_STRCPY_S +#endif +#endif + +#ifdef __cplusplus +namespace boost{ namespace BOOST_REGEX_DETAIL_NS{ + +#if defined(BOOST_REGEX_MSVC) && (BOOST_REGEX_MSVC < 1910) + // + // MSVC 10 will either emit warnings or else refuse to compile + // code that makes perfectly legitimate use of std::copy, when + // the OutputIterator type is a user-defined class (apparently all user + // defined iterators are "unsafe"). What's more Microsoft have removed their + // non-standard "unchecked" versions, even though they are still in the MS + // documentation!! Work around this as best we can: + // + template + inline OutputIterator copy( + InputIterator first, + InputIterator last, + OutputIterator dest + ) + { + while (first != last) + *dest++ = *first++; + return dest; + } +#else + using std::copy; +#endif + + +#if defined(BOOST_REGEX_HAS_STRCPY_S) + + // use safe versions of strcpy etc: + using ::strcpy_s; + using ::strcat_s; +#else + inline std::size_t strcpy_s( + char *strDestination, + std::size_t sizeInBytes, + const char *strSource + ) + { + std::size_t lenSourceWithNull = std::strlen(strSource) + 1; + if (lenSourceWithNull > sizeInBytes) + return 1; + std::memcpy(strDestination, strSource, lenSourceWithNull); + return 0; + } + inline std::size_t strcat_s( + char *strDestination, + std::size_t sizeInBytes, + const char *strSource + ) + { + std::size_t lenSourceWithNull = std::strlen(strSource) + 1; + std::size_t lenDestination = std::strlen(strDestination); + if (lenSourceWithNull + lenDestination > sizeInBytes) + return 1; + std::memcpy(strDestination + lenDestination, strSource, lenSourceWithNull); + return 0; + } + +#endif + + inline void overflow_error_if_not_zero(std::size_t i) + { + if(i) + { + std::overflow_error e("String buffer too small"); +#ifndef BOOST_REGEX_STANDALONE + boost::throw_exception(e); +#else + throw e; +#endif + } + } + +}} // namespaces + +#endif // __cplusplus + +#endif // include guard + diff --git a/boost/regex/v5/states.hpp b/boost/regex/v5/states.hpp new file mode 100644 index 00000000..60fc99d0 --- /dev/null +++ b/boost/regex/v5/states.hpp @@ -0,0 +1,299 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE states.cpp + * VERSION see + * DESCRIPTION: Declares internal state machine structures. + */ + +#ifndef BOOST_REGEX_V5_STATES_HPP +#define BOOST_REGEX_V5_STATES_HPP + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +/*** mask_type ******************************************************* +Whenever we have a choice of two alternatives, we use an array of bytes +to indicate which of the two alternatives it is possible to take for any +given input character. If mask_take is set, then we can take the next +state, and if mask_skip is set then we can take the alternative. +***********************************************************************/ +enum mask_type +{ + mask_take = 1, + mask_skip = 2, + mask_init = 4, + mask_any = mask_skip | mask_take, + mask_all = mask_any +}; + +/*** helpers ********************************************************** +These helpers let us use function overload resolution to detect whether +we have narrow or wide character strings: +***********************************************************************/ +struct _narrow_type{}; +struct _wide_type{}; +template struct is_byte; +template<> struct is_byte { typedef _narrow_type width_type; }; +template<> struct is_byte{ typedef _narrow_type width_type; }; +template<> struct is_byte { typedef _narrow_type width_type; }; +template struct is_byte { typedef _wide_type width_type; }; + +/*** enum syntax_element_type ****************************************** +Every record in the state machine falls into one of the following types: +***********************************************************************/ +enum syntax_element_type +{ + // start of a marked sub-expression, or perl-style (?...) extension + syntax_element_startmark = 0, + // end of a marked sub-expression, or perl-style (?...) extension + syntax_element_endmark = syntax_element_startmark + 1, + // any sequence of literal characters + syntax_element_literal = syntax_element_endmark + 1, + // start of line assertion: ^ + syntax_element_start_line = syntax_element_literal + 1, + // end of line assertion $ + syntax_element_end_line = syntax_element_start_line + 1, + // match any character: . + syntax_element_wild = syntax_element_end_line + 1, + // end of expression: we have a match when we get here + syntax_element_match = syntax_element_wild + 1, + // perl style word boundary: \b + syntax_element_word_boundary = syntax_element_match + 1, + // perl style within word boundary: \B + syntax_element_within_word = syntax_element_word_boundary + 1, + // start of word assertion: \< + syntax_element_word_start = syntax_element_within_word + 1, + // end of word assertion: \> + syntax_element_word_end = syntax_element_word_start + 1, + // start of buffer assertion: \` + syntax_element_buffer_start = syntax_element_word_end + 1, + // end of buffer assertion: \' + syntax_element_buffer_end = syntax_element_buffer_start + 1, + // backreference to previously matched sub-expression + syntax_element_backref = syntax_element_buffer_end + 1, + // either a wide character set [..] or one with multicharacter collating elements: + syntax_element_long_set = syntax_element_backref + 1, + // narrow character set: [...] + syntax_element_set = syntax_element_long_set + 1, + // jump to a new state in the machine: + syntax_element_jump = syntax_element_set + 1, + // choose between two production states: + syntax_element_alt = syntax_element_jump + 1, + // a repeat + syntax_element_rep = syntax_element_alt + 1, + // match a combining character sequence + syntax_element_combining = syntax_element_rep + 1, + // perl style soft buffer end: \z + syntax_element_soft_buffer_end = syntax_element_combining + 1, + // perl style continuation: \G + syntax_element_restart_continue = syntax_element_soft_buffer_end + 1, + // single character repeats: + syntax_element_dot_rep = syntax_element_restart_continue + 1, + syntax_element_char_rep = syntax_element_dot_rep + 1, + syntax_element_short_set_rep = syntax_element_char_rep + 1, + syntax_element_long_set_rep = syntax_element_short_set_rep + 1, + // a backstep for lookbehind repeats: + syntax_element_backstep = syntax_element_long_set_rep + 1, + // an assertion that a mark was matched: + syntax_element_assert_backref = syntax_element_backstep + 1, + syntax_element_toggle_case = syntax_element_assert_backref + 1, + // a recursive expression: + syntax_element_recurse = syntax_element_toggle_case + 1, + // Verbs: + syntax_element_fail = syntax_element_recurse + 1, + syntax_element_accept = syntax_element_fail + 1, + syntax_element_commit = syntax_element_accept + 1, + syntax_element_then = syntax_element_commit + 1 +}; + +#ifdef BOOST_REGEX_DEBUG +// dwa 09/26/00 - This is needed to suppress warnings about an ambiguous conversion +std::ostream& operator<<(std::ostream&, syntax_element_type); +#endif + +struct re_syntax_base; + +/*** union offset_type ************************************************ +Points to another state in the machine. During machine construction +we use integral offsets, but these are converted to pointers before +execution of the machine. +***********************************************************************/ +union offset_type +{ + re_syntax_base* p; + std::ptrdiff_t i; +}; + +/*** struct re_syntax_base ******************************************** +Base class for all states in the machine. +***********************************************************************/ +struct re_syntax_base +{ + syntax_element_type type; // what kind of state this is + offset_type next; // next state in the machine +}; + +/*** struct re_brace ************************************************** +A marked parenthesis. +***********************************************************************/ +struct re_brace : public re_syntax_base +{ + // The index to match, can be zero (don't mark the sub-expression) + // or negative (for perl style (?...) extensions): + int index; + bool icase; +}; + +/*** struct re_dot ************************************************** +Match anything. +***********************************************************************/ +enum +{ + dont_care = 1, + force_not_newline = 0, + force_newline = 2, + + test_not_newline = 2, + test_newline = 3 +}; +struct re_dot : public re_syntax_base +{ + unsigned char mask; +}; + +/*** struct re_literal ************************************************ +A string of literals, following this structure will be an +array of characters: charT[length] +***********************************************************************/ +struct re_literal : public re_syntax_base +{ + unsigned int length; +}; + +/*** struct re_case ************************************************ +Indicates whether we are moving to a case insensive block or not +***********************************************************************/ +struct re_case : public re_syntax_base +{ + bool icase; +}; + +/*** struct re_set_long *********************************************** +A wide character set of characters, following this structure will be +an array of type charT: +First csingles null-terminated strings +Then 2 * cranges NULL terminated strings +Then cequivalents NULL terminated strings +***********************************************************************/ +template +struct re_set_long : public re_syntax_base +{ + unsigned int csingles, cranges, cequivalents; + mask_type cclasses; + mask_type cnclasses; + bool isnot; + bool singleton; +}; + +/*** struct re_set **************************************************** +A set of narrow-characters, matches any of _map which is none-zero +***********************************************************************/ +struct re_set : public re_syntax_base +{ + unsigned char _map[1 << CHAR_BIT]; +}; + +/*** struct re_jump *************************************************** +Jump to a new location in the machine (not next). +***********************************************************************/ +struct re_jump : public re_syntax_base +{ + offset_type alt; // location to jump to +}; + +/*** struct re_alt *************************************************** +Jump to a new location in the machine (possibly next). +***********************************************************************/ +struct re_alt : public re_jump +{ + unsigned char _map[1 << CHAR_BIT]; // which characters can take the jump + unsigned int can_be_null; // true if we match a NULL string +}; + +/*** struct re_repeat ************************************************* +Repeat a section of the machine +***********************************************************************/ +struct re_repeat : public re_alt +{ + std::size_t min, max; // min and max allowable repeats + int state_id; // Unique identifier for this repeat + bool leading; // True if this repeat is at the start of the machine (lets us optimize some searches) + bool greedy; // True if this is a greedy repeat +}; + +/*** struct re_recurse ************************************************ +Recurse to a particular subexpression. +**********************************************************************/ +struct re_recurse : public re_jump +{ + int state_id; // identifier of first nested repeat within the recursion. +}; + +/*** struct re_commit ************************************************* +Used for the PRUNE, SKIP and COMMIT verbs which basically differ only in what happens +if no match is found and we start searching forward. +**********************************************************************/ +enum commit_type +{ + commit_prune, + commit_skip, + commit_commit +}; +struct re_commit : public re_syntax_base +{ + commit_type action; +}; + +/*** enum re_jump_size_type ******************************************* +Provides compiled size of re_jump structure (allowing for trailing alignment). +We provide this so we know how manybytes to insert when constructing the machine +(The value of padding_mask is defined in regex_raw_buffer.hpp). +***********************************************************************/ +enum re_jump_size_type +{ + re_jump_size = (sizeof(re_jump) + padding_mask) & ~(padding_mask), + re_repeater_size = (sizeof(re_repeat) + padding_mask) & ~(padding_mask), + re_alt_size = (sizeof(re_alt) + padding_mask) & ~(padding_mask) +}; + +/*** proc re_is_set_member ********************************************* +Forward declaration: we'll need this one later... +***********************************************************************/ + +template +struct regex_data; + +template +iterator re_is_set_member(iterator next, + iterator last, + const re_set_long* set_, + const regex_data& e, bool icase); + +} // namespace BOOST_REGEX_DETAIL_NS + +} // namespace boost + +#endif + + diff --git a/boost/regex/v5/sub_match.hpp b/boost/regex/v5/sub_match.hpp new file mode 100644 index 00000000..aa61b560 --- /dev/null +++ b/boost/regex/v5/sub_match.hpp @@ -0,0 +1,382 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE sub_match.cpp + * VERSION see + * DESCRIPTION: Declares template class sub_match. + */ + +#ifndef BOOST_REGEX_V5_SUB_MATCH_HPP +#define BOOST_REGEX_V5_SUB_MATCH_HPP + +namespace boost{ + +template +struct sub_match : public std::pair +{ + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef BidiIterator iterator_type; + typedef BidiIterator iterator; + typedef BidiIterator const_iterator; + + bool matched; + + sub_match() : std::pair(), matched(false) {} + sub_match(BidiIterator i) : std::pair(i, i), matched(false) {} + template + operator std::basic_string ()const + { + return matched ? std::basic_string(this->first, this->second) : std::basic_string(); + } + difference_type length()const + { + difference_type n = matched ? std::distance((BidiIterator)this->first, (BidiIterator)this->second) : 0; + return n; + } + std::basic_string str()const + { + std::basic_string result; + if(matched) + { + std::size_t len = std::distance((BidiIterator)this->first, (BidiIterator)this->second); + result.reserve(len); + BidiIterator i = this->first; + while(i != this->second) + { + result.append(1, *i); + ++i; + } + } + return result; + } + int compare(const sub_match& s)const + { + if(matched != s.matched) + return static_cast(matched) - static_cast(s.matched); + return str().compare(s.str()); + } + int compare(const std::basic_string& s)const + { + return str().compare(s); + } + int compare(const value_type* p)const + { + return str().compare(p); + } + + bool operator==(const sub_match& that)const + { return compare(that) == 0; } + bool operator !=(const sub_match& that)const + { return compare(that) != 0; } + bool operator<(const sub_match& that)const + { return compare(that) < 0; } + bool operator>(const sub_match& that)const + { return compare(that) > 0; } + bool operator<=(const sub_match& that)const + { return compare(that) <= 0; } + bool operator>=(const sub_match& that)const + { return compare(that) >= 0; } + +#ifdef BOOST_REGEX_MATCH_EXTRA + typedef std::vector > capture_sequence_type; + + const capture_sequence_type& captures()const + { + if(!m_captures) + m_captures.reset(new capture_sequence_type()); + return *m_captures; + } + // + // Private implementation API: DO NOT USE! + // + capture_sequence_type& get_captures()const + { + if(!m_captures) + m_captures.reset(new capture_sequence_type()); + return *m_captures; + } + +private: + mutable std::unique_ptr m_captures; +public: + +#endif + sub_match(const sub_match& that, bool +#ifdef BOOST_REGEX_MATCH_EXTRA + deep_copy +#endif + = true + ) + : std::pair(that), + matched(that.matched) + { +#ifdef BOOST_REGEX_MATCH_EXTRA + if(that.m_captures) + if(deep_copy) + m_captures.reset(new capture_sequence_type(*(that.m_captures))); +#endif + } + sub_match& operator=(const sub_match& that) + { + this->first = that.first; + this->second = that.second; + matched = that.matched; +#ifdef BOOST_REGEX_MATCH_EXTRA + if(that.m_captures) + get_captures() = *(that.m_captures); +#endif + return *this; + } + // + // Make this type a range, for both Boost.Range, and C++11: + // + BidiIterator begin()const { return this->first; } + BidiIterator end()const { return this->second; } +}; + +typedef sub_match csub_match; +typedef sub_match ssub_match; +#ifndef BOOST_NO_WREGEX +typedef sub_match wcsub_match; +typedef sub_match wssub_match; +#endif + +// comparison to std::basic_string<> part 1: +template +inline bool operator == (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ return s.compare(m.str()) == 0; } +template +inline bool operator != (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ return s.compare(m.str()) != 0; } +template +inline bool operator < (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ return s.compare(m.str()) < 0; } +template +inline bool operator <= (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ return s.compare(m.str()) <= 0; } +template +inline bool operator >= (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ return s.compare(m.str()) >= 0; } +template +inline bool operator > (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ return s.compare(m.str()) > 0; } +// comparison to std::basic_string<> part 2: +template +inline bool operator == (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ return m.str().compare(s) == 0; } +template +inline bool operator != (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ return m.str().compare(s) != 0; } +template +inline bool operator < (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ return m.str().compare(s) < 0; } +template +inline bool operator > (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ return m.str().compare(s) > 0; } +template +inline bool operator <= (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ return m.str().compare(s) <= 0; } +template +inline bool operator >= (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ return m.str().compare(s) >= 0; } +// comparison to const charT* part 1: +template +inline bool operator == (const sub_match& m, + typename std::iterator_traits::value_type const* s) +{ return m.str().compare(s) == 0; } +template +inline bool operator != (const sub_match& m, + typename std::iterator_traits::value_type const* s) +{ return m.str().compare(s) != 0; } +template +inline bool operator > (const sub_match& m, + typename std::iterator_traits::value_type const* s) +{ return m.str().compare(s) > 0; } +template +inline bool operator < (const sub_match& m, + typename std::iterator_traits::value_type const* s) +{ return m.str().compare(s) < 0; } +template +inline bool operator >= (const sub_match& m, + typename std::iterator_traits::value_type const* s) +{ return m.str().compare(s) >= 0; } +template +inline bool operator <= (const sub_match& m, + typename std::iterator_traits::value_type const* s) +{ return m.str().compare(s) <= 0; } +// comparison to const charT* part 2: +template +inline bool operator == (typename std::iterator_traits::value_type const* s, + const sub_match& m) +{ return m.str().compare(s) == 0; } +template +inline bool operator != (typename std::iterator_traits::value_type const* s, + const sub_match& m) +{ return m.str().compare(s) != 0; } +template +inline bool operator < (typename std::iterator_traits::value_type const* s, + const sub_match& m) +{ return m.str().compare(s) > 0; } +template +inline bool operator > (typename std::iterator_traits::value_type const* s, + const sub_match& m) +{ return m.str().compare(s) < 0; } +template +inline bool operator <= (typename std::iterator_traits::value_type const* s, + const sub_match& m) +{ return m.str().compare(s) >= 0; } +template +inline bool operator >= (typename std::iterator_traits::value_type const* s, + const sub_match& m) +{ return m.str().compare(s) <= 0; } + +// comparison to const charT& part 1: +template +inline bool operator == (const sub_match& m, + typename std::iterator_traits::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) == 0; } +template +inline bool operator != (const sub_match& m, + typename std::iterator_traits::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) != 0; } +template +inline bool operator > (const sub_match& m, + typename std::iterator_traits::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) > 0; } +template +inline bool operator < (const sub_match& m, + typename std::iterator_traits::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) < 0; } +template +inline bool operator >= (const sub_match& m, + typename std::iterator_traits::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) >= 0; } +template +inline bool operator <= (const sub_match& m, + typename std::iterator_traits::value_type const& s) +{ return m.str().compare(0, m.length(), &s, 1) <= 0; } +// comparison to const charT* part 2: +template +inline bool operator == (typename std::iterator_traits::value_type const& s, + const sub_match& m) +{ return m.str().compare(0, m.length(), &s, 1) == 0; } +template +inline bool operator != (typename std::iterator_traits::value_type const& s, + const sub_match& m) +{ return m.str().compare(0, m.length(), &s, 1) != 0; } +template +inline bool operator < (typename std::iterator_traits::value_type const& s, + const sub_match& m) +{ return m.str().compare(0, m.length(), &s, 1) > 0; } +template +inline bool operator > (typename std::iterator_traits::value_type const& s, + const sub_match& m) +{ return m.str().compare(0, m.length(), &s, 1) < 0; } +template +inline bool operator <= (typename std::iterator_traits::value_type const& s, + const sub_match& m) +{ return m.str().compare(0, m.length(), &s, 1) >= 0; } +template +inline bool operator >= (typename std::iterator_traits::value_type const& s, + const sub_match& m) +{ return m.str().compare(0, m.length(), &s, 1) <= 0; } + +// addition operators: +template +inline std::basic_string::value_type, traits, Allocator> +operator + (const std::basic_string::value_type, traits, Allocator>& s, + const sub_match& m) +{ + std::basic_string::value_type, traits, Allocator> result; + result.reserve(s.size() + m.length() + 1); + return result.append(s).append(m.first, m.second); +} +template +inline std::basic_string::value_type, traits, Allocator> +operator + (const sub_match& m, + const std::basic_string::value_type, traits, Allocator>& s) +{ + std::basic_string::value_type, traits, Allocator> result; + result.reserve(s.size() + m.length() + 1); + return result.append(m.first, m.second).append(s); +} +template +inline std::basic_string::value_type> +operator + (typename std::iterator_traits::value_type const* s, + const sub_match& m) +{ + std::basic_string::value_type> result; + result.reserve(std::char_traits::value_type>::length(s) + m.length() + 1); + return result.append(s).append(m.first, m.second); +} +template +inline std::basic_string::value_type> +operator + (const sub_match& m, + typename std::iterator_traits::value_type const * s) +{ + std::basic_string::value_type> result; + result.reserve(std::char_traits::value_type>::length(s) + m.length() + 1); + return result.append(m.first, m.second).append(s); +} +template +inline std::basic_string::value_type> +operator + (typename std::iterator_traits::value_type const& s, + const sub_match& m) +{ + std::basic_string::value_type> result; + result.reserve(m.length() + 2); + return result.append(1, s).append(m.first, m.second); +} +template +inline std::basic_string::value_type> +operator + (const sub_match& m, + typename std::iterator_traits::value_type const& s) +{ + std::basic_string::value_type> result; + result.reserve(m.length() + 2); + return result.append(m.first, m.second).append(1, s); +} +template +inline std::basic_string::value_type> +operator + (const sub_match& m1, + const sub_match& m2) +{ + std::basic_string::value_type> result; + result.reserve(m1.length() + m2.length() + 1); + return result.append(m1.first, m1.second).append(m2.first, m2.second); +} +template +std::basic_ostream& + operator << (std::basic_ostream& os, + const sub_match& s) +{ + return (os << s.str()); +} + +} // namespace boost + +#endif + diff --git a/boost/regex/v5/syntax_type.hpp b/boost/regex/v5/syntax_type.hpp new file mode 100644 index 00000000..3efdf0b0 --- /dev/null +++ b/boost/regex/v5/syntax_type.hpp @@ -0,0 +1,105 @@ +/* + * + * Copyright (c) 2003 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE syntax_type.hpp + * VERSION see + * DESCRIPTION: Declares regular expression synatx type enumerator. + */ + +#ifndef BOOST_REGEX_SYNTAX_TYPE_HPP +#define BOOST_REGEX_SYNTAX_TYPE_HPP + +namespace boost{ +namespace regex_constants{ + +typedef unsigned char syntax_type; + +// +// values chosen are binary compatible with previous version: +// +static const syntax_type syntax_char = 0; +static const syntax_type syntax_open_mark = 1; +static const syntax_type syntax_close_mark = 2; +static const syntax_type syntax_dollar = 3; +static const syntax_type syntax_caret = 4; +static const syntax_type syntax_dot = 5; +static const syntax_type syntax_star = 6; +static const syntax_type syntax_plus = 7; +static const syntax_type syntax_question = 8; +static const syntax_type syntax_open_set = 9; +static const syntax_type syntax_close_set = 10; +static const syntax_type syntax_or = 11; +static const syntax_type syntax_escape = 12; +static const syntax_type syntax_dash = 14; +static const syntax_type syntax_open_brace = 15; +static const syntax_type syntax_close_brace = 16; +static const syntax_type syntax_digit = 17; +static const syntax_type syntax_comma = 27; +static const syntax_type syntax_equal = 37; +static const syntax_type syntax_colon = 36; +static const syntax_type syntax_not = 53; + +// extensions: + +static const syntax_type syntax_hash = 13; +static const syntax_type syntax_newline = 26; + +// escapes: + +typedef syntax_type escape_syntax_type; + +static const escape_syntax_type escape_type_word_assert = 18; +static const escape_syntax_type escape_type_not_word_assert = 19; +static const escape_syntax_type escape_type_control_f = 29; +static const escape_syntax_type escape_type_control_n = 30; +static const escape_syntax_type escape_type_control_r = 31; +static const escape_syntax_type escape_type_control_t = 32; +static const escape_syntax_type escape_type_control_v = 33; +static const escape_syntax_type escape_type_ascii_control = 35; +static const escape_syntax_type escape_type_hex = 34; +static const escape_syntax_type escape_type_unicode = 0; // not used +static const escape_syntax_type escape_type_identity = 0; // not used +static const escape_syntax_type escape_type_backref = syntax_digit; +static const escape_syntax_type escape_type_decimal = syntax_digit; // not used +static const escape_syntax_type escape_type_class = 22; +static const escape_syntax_type escape_type_not_class = 23; + +// extensions: + +static const escape_syntax_type escape_type_left_word = 20; +static const escape_syntax_type escape_type_right_word = 21; +static const escape_syntax_type escape_type_start_buffer = 24; // for \` +static const escape_syntax_type escape_type_end_buffer = 25; // for \' +static const escape_syntax_type escape_type_control_a = 28; // for \a +static const escape_syntax_type escape_type_e = 38; // for \e +static const escape_syntax_type escape_type_E = 47; // for \Q\E +static const escape_syntax_type escape_type_Q = 48; // for \Q\E +static const escape_syntax_type escape_type_X = 49; // for \X +static const escape_syntax_type escape_type_C = 50; // for \C +static const escape_syntax_type escape_type_Z = 51; // for \Z +static const escape_syntax_type escape_type_G = 52; // for \G + +static const escape_syntax_type escape_type_property = 54; // for \p +static const escape_syntax_type escape_type_not_property = 55; // for \P +static const escape_syntax_type escape_type_named_char = 56; // for \N +static const escape_syntax_type escape_type_extended_backref = 57; // for \g +static const escape_syntax_type escape_type_reset_start_mark = 58; // for \K +static const escape_syntax_type escape_type_line_ending = 59; // for \R + +static const escape_syntax_type syntax_max = 60; + +} +} + + +#endif diff --git a/boost/regex/v5/w32_regex_traits.hpp b/boost/regex/v5/w32_regex_traits.hpp new file mode 100644 index 00000000..16f7ee4e --- /dev/null +++ b/boost/regex/v5/w32_regex_traits.hpp @@ -0,0 +1,1311 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE w32_regex_traits.hpp + * VERSION see + * DESCRIPTION: Declares regular expression traits class w32_regex_traits. + */ + +#ifndef BOOST_W32_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_W32_REGEX_TRAITS_HPP_INCLUDED + +#ifndef BOOST_REGEX_NO_WIN32_LOCALE + +#include +#include +#ifdef BOOST_HAS_THREADS +#include +#endif +#include +#include + +#if defined(_MSC_VER) && !defined(_WIN32_WCE) && !defined(UNDER_CE) +#pragma comment(lib, "user32.lib") +#endif + +#ifdef BOOST_REGEX_MSVC +#pragma warning(push) +#pragma warning(disable:4786) +#if BOOST_REGEX_MSVC < 1910 +#pragma warning(disable:4800) +#endif +#endif + +#ifndef BASETYPES +// +// windows.h not included, so lets forward declare what we need: +// +#ifndef NO_STRICT +#ifndef STRICT +#define STRICT 1 +#endif +#endif + +#if defined(STRICT) +#define BOOST_RE_DETAIL_DECLARE_HANDLE(x) struct x##__; typedef struct x##__ *x +#else +#define BOOST_RE_DETAIL_DECLARE_HANDLE(x) typedef void* x +#endif +// +// This must be in the global namespace: +// +extern "C" { + + BOOST_RE_DETAIL_DECLARE_HANDLE(HINSTANCE); + typedef HINSTANCE HMODULE; +} +#endif + +namespace boost{ + +// +// forward declaration is needed by some compilers: +// +template +class w32_regex_traits; + +namespace BOOST_REGEX_DETAIL_NS{ + +// +// start by typedeffing the types we'll need: +// +typedef unsigned long lcid_type; // placeholder for LCID. +typedef std::shared_ptr cat_type; // placeholder for dll HANDLE. + +// +// then add wrappers around the actual Win32 API's (ie implementation hiding): +// +lcid_type w32_get_default_locale(); +bool w32_is_lower(char, lcid_type); +#ifndef BOOST_NO_WREGEX +bool w32_is_lower(wchar_t, lcid_type); +#endif +bool w32_is_upper(char, lcid_type); +#ifndef BOOST_NO_WREGEX +bool w32_is_upper(wchar_t, lcid_type); +#endif +cat_type w32_cat_open(const std::string& name); +std::string w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::string& def); +#ifndef BOOST_NO_WREGEX +std::wstring w32_cat_get(const cat_type& cat, lcid_type state_id, int i, const std::wstring& def); +#endif +std::string w32_transform(lcid_type state_id, const char* p1, const char* p2); +#ifndef BOOST_NO_WREGEX +std::wstring w32_transform(lcid_type state_id, const wchar_t* p1, const wchar_t* p2); +#endif +char w32_tolower(char c, lcid_type); +#ifndef BOOST_NO_WREGEX +wchar_t w32_tolower(wchar_t c, lcid_type); +#endif +char w32_toupper(char c, lcid_type); +#ifndef BOOST_NO_WREGEX +wchar_t w32_toupper(wchar_t c, lcid_type); +#endif +bool w32_is(lcid_type, std::uint32_t mask, char c); +#ifndef BOOST_NO_WREGEX +bool w32_is(lcid_type, std::uint32_t mask, wchar_t c); +#endif + +#ifndef BASETYPES +// +// Forward declarations of the small number of windows types and API's we use: +// + +#if !defined(__LP64__) +using dword = unsigned long; +#else +using DWORD = unsigned int; +#endif +using word = unsigned short; +using lctype = dword; + +static constexpr dword ct_ctype1 = 0x00000001; +static constexpr dword c1_upper = 0x0001; // upper case +static constexpr dword c1_lower = 0x0002; // lower case +static constexpr dword c1_digit = 0x0004; // decimal digits +static constexpr dword c1_space = 0x0008; // spacing characters +static constexpr dword c1_punct = 0x0010; // punctuation characters +static constexpr dword c1_cntrl = 0x0020; // control characters +static constexpr dword c1_blank = 0x0040; // blank characters +static constexpr dword c1_xdigit = 0x0080; // other digits +static constexpr dword c1_alpha = 0x0100; // any linguistic character +static constexpr dword c1_defined = 0x0200; // defined character +static constexpr unsigned int cp_acp = 0; +static constexpr dword lcmap_lowercase = 0x00000100; +static constexpr dword lcmap_uppercase = 0x00000200; +static constexpr dword lcmap_sortkey = 0x00000400; // WC sort key (normalize) +static constexpr lctype locale_idefaultansicodepage = 0x00001004; + +# ifdef UNDER_CE +# ifndef WINAPI +# ifndef _WIN32_WCE_EMULATION +# define BOOST_RE_STDCALL __cdecl // Note this doesn't match the desktop definition +# else +# define BOOST_RE_STDCALL __stdcall +# endif +# endif +# else +# if defined(_M_IX86) || defined(__i386__) +# define BOOST_RE_STDCALL __stdcall +# else + // On architectures other than 32-bit x86 __stdcall is ignored. Clang also issues a warning. +# define BOOST_RE_STDCALL +# endif +# endif + +#if defined (WIN32_PLATFORM_PSPC) +#define BOOST_RE_IMPORT __declspec( dllimport ) +#elif defined (_WIN32_WCE) +#define BOOST_RE_IMPORT +#else +#define BOOST_RE_IMPORT __declspec( dllimport ) +#endif + +extern "C" { + + BOOST_RE_IMPORT int BOOST_RE_STDCALL FreeLibrary(HMODULE hLibModule); + BOOST_RE_IMPORT int BOOST_RE_STDCALL LCMapStringA(lcid_type Locale, dword dwMapFlags, const char* lpSrcStr, int cchSrc, char* lpDestStr, int cchDest); + BOOST_RE_IMPORT int BOOST_RE_STDCALL LCMapStringW(lcid_type Locale, dword dwMapFlags, const wchar_t* lpSrcStr, int cchSrc, wchar_t* lpDestStr, int cchDest); + BOOST_RE_IMPORT int BOOST_RE_STDCALL MultiByteToWideChar(unsigned int CodePage, dword dwFlags, const char* lpMultiByteStr, int cbMultiByte, wchar_t* lpWideCharStr, int cchWideChar); + BOOST_RE_IMPORT int BOOST_RE_STDCALL LCMapStringW(lcid_type Locale, dword dwMapFlags, const wchar_t* lpSrcStr, int cchSrc, wchar_t* lpDestStr, int cchDest); + BOOST_RE_IMPORT int BOOST_RE_STDCALL WideCharToMultiByte(unsigned int CodePage, dword dwFlags, const wchar_t* lpWideCharStr, int cchWideChar, char* lpMultiByteStr, int cbMultiByte, const char* lpDefaultChar, int* lpUsedDefaultChar); + BOOST_RE_IMPORT int BOOST_RE_STDCALL GetStringTypeExA(lcid_type Locale, dword dwInfoType, const char* lpSrcStr, int cchSrc, word* lpCharType); + BOOST_RE_IMPORT int BOOST_RE_STDCALL GetStringTypeExW(lcid_type Locale, dword dwInfoType, const wchar_t* lpSrcStr, int cchSrc, word* lpCharType); + BOOST_RE_IMPORT lcid_type BOOST_RE_STDCALL GetUserDefaultLCID(); + BOOST_RE_IMPORT int BOOST_RE_STDCALL GetStringTypeExA(lcid_type Locale, dword dwInfoType, const char* lpSrcStr, int cchSrc, word* lpCharType); + BOOST_RE_IMPORT int BOOST_RE_STDCALL GetStringTypeExW(lcid_type Locale, dword dwInfoType, const wchar_t* lpSrcStr, int cchSrc, word* lpCharType); + BOOST_RE_IMPORT HMODULE BOOST_RE_STDCALL LoadLibraryA(const char* lpLibFileName); + BOOST_RE_IMPORT HMODULE BOOST_RE_STDCALL LoadLibraryW(const wchar_t* lpLibFileName); + BOOST_RE_IMPORT int BOOST_RE_STDCALL LoadStringW(HINSTANCE hInstance, unsigned int uID, wchar_t* lpBuffer, int cchBufferMax); + BOOST_RE_IMPORT int BOOST_RE_STDCALL LoadStringA(HINSTANCE hInstance, unsigned int uID, char* lpBuffer, int cchBufferMax); + BOOST_RE_IMPORT int BOOST_RE_STDCALL GetLocaleInfoW(lcid_type Locale, lctype LCType, wchar_t* lpLCData, int cchData); +} + +#else +// +// We have windows.h already included: +// +using dword = DWORD; +using word = WORD; +using lctype = LCTYPE; + +static constexpr dword ct_ctype1 = 0x00000001; +static constexpr dword c1_upper = 0x0001; // upper case +static constexpr dword c1_lower = 0x0002; // lower case +static constexpr dword c1_digit = 0x0004; // decimal digits +static constexpr dword c1_space = 0x0008; // spacing characters +static constexpr dword c1_punct = 0x0010; // punctuation characters +static constexpr dword c1_cntrl = 0x0020; // control characters +static constexpr dword c1_blank = 0x0040; // blank characters +static constexpr dword c1_xdigit = 0x0080; // other digits +static constexpr dword c1_alpha = 0x0100; // any linguistic character +static constexpr dword c1_defined = 0x0200; // defined character +static constexpr unsigned int cp_acp = 0; +static constexpr dword lcmap_lowercase = 0x00000100; +static constexpr dword lcmap_uppercase = 0x00000200; +static constexpr dword lcmap_sortkey = 0x00000400; // WC sort key (normalize) +static constexpr lctype locale_idefaultansicodepage = 0x00001004; + +using ::FreeLibrary; +using ::LCMapStringA; +using ::LCMapStringW; +using ::MultiByteToWideChar; +using ::LCMapStringW; +using ::WideCharToMultiByte; +using ::GetStringTypeExA; +using ::GetStringTypeExW; +using ::GetUserDefaultLCID; +using ::GetStringTypeExA; +using ::GetStringTypeExW; +using ::LoadLibraryA; +using ::LoadLibraryW; +using ::LoadStringW; +using ::LoadStringA; +using ::GetLocaleInfoW; + +#endif +// +// class w32_regex_traits_base: +// acts as a container for locale and the facets we are using. +// +template +struct w32_regex_traits_base +{ + w32_regex_traits_base(lcid_type l) + { imbue(l); } + lcid_type imbue(lcid_type l); + + lcid_type m_locale; +}; + +template +inline lcid_type w32_regex_traits_base::imbue(lcid_type l) +{ + lcid_type result(m_locale); + m_locale = l; + return result; +} + +// +// class w32_regex_traits_char_layer: +// implements methods that require specialisation for narrow characters: +// +template +class w32_regex_traits_char_layer : public w32_regex_traits_base +{ + typedef std::basic_string string_type; + typedef std::map map_type; + typedef typename map_type::const_iterator map_iterator_type; +public: + w32_regex_traits_char_layer(const lcid_type l); + + regex_constants::syntax_type syntax_type(charT c)const + { + map_iterator_type i = m_char_map.find(c); + return ((i == m_char_map.end()) ? 0 : i->second); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + map_iterator_type i = m_char_map.find(c); + if(i == m_char_map.end()) + { + if(::boost::BOOST_REGEX_DETAIL_NS::w32_is_lower(c, this->m_locale)) return regex_constants::escape_type_class; + if(::boost::BOOST_REGEX_DETAIL_NS::w32_is_upper(c, this->m_locale)) return regex_constants::escape_type_not_class; + return 0; + } + return i->second; + } + charT tolower(charT c)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::w32_tolower(c, this->m_locale); + } + bool isctype(std::uint32_t mask, charT c)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, mask, c); + } + +private: + string_type get_default_message(regex_constants::syntax_type); + // TODO: use a hash table when available! + map_type m_char_map; +}; + +template +w32_regex_traits_char_layer::w32_regex_traits_char_layer(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l) + : w32_regex_traits_base(l) +{ + // we need to start by initialising our syntax map so we know which + // character is used for which purpose: + cat_type cat; + std::string cat_name(w32_regex_traits::get_catalog_name()); + if(cat_name.size()) + { + cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name); + if(!cat) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if(cat) + { + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + string_type mss = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i, get_default_message(i)); + for(typename string_type::size_type j = 0; j < mss.size(); ++j) + { + this->m_char_map[mss[j]] = i; + } + } + } + else + { + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + const char* ptr = get_default_syntax(i); + while(ptr && *ptr) + { + this->m_char_map[static_cast(*ptr)] = i; + ++ptr; + } + } + } +} + +template +typename w32_regex_traits_char_layer::string_type + w32_regex_traits_char_layer::get_default_message(regex_constants::syntax_type i) +{ + const char* ptr = get_default_syntax(i); + string_type result; + while(ptr && *ptr) + { + result.append(1, static_cast(*ptr)); + ++ptr; + } + return result; +} + +// +// specialised version for narrow characters: +// +template <> +class w32_regex_traits_char_layer : public w32_regex_traits_base +{ + typedef std::string string_type; +public: + w32_regex_traits_char_layer(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l) + : w32_regex_traits_base(l) + { + init(); + } + + regex_constants::syntax_type syntax_type(char c)const + { + return m_char_map[static_cast(c)]; + } + regex_constants::escape_syntax_type escape_syntax_type(char c) const + { + return m_char_map[static_cast(c)]; + } + char tolower(char c)const + { + return m_lower_map[static_cast(c)]; + } + bool isctype(std::uint32_t mask, char c)const + { + return m_type_map[static_cast(c)] & mask; + } + +private: + regex_constants::syntax_type m_char_map[1u << CHAR_BIT]; + char m_lower_map[1u << CHAR_BIT]; + std::uint16_t m_type_map[1u << CHAR_BIT]; + template + void init(); +}; + +// +// class w32_regex_traits_implementation: +// provides pimpl implementation for w32_regex_traits. +// +template +class w32_regex_traits_implementation : public w32_regex_traits_char_layer +{ +public: + typedef typename w32_regex_traits::char_class_type char_class_type; + static const char_class_type mask_word = 0x0400; // must be C1_DEFINED << 1 + static const char_class_type mask_unicode = 0x0800; // must be C1_DEFINED << 2 + static const char_class_type mask_horizontal = 0x1000; // must be C1_DEFINED << 3 + static const char_class_type mask_vertical = 0x2000; // must be C1_DEFINED << 4 + static const char_class_type mask_base = 0x3ff; // all the masks used by the CT_CTYPE1 group + + typedef std::basic_string string_type; + typedef charT char_type; + w32_regex_traits_implementation(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l); + std::string error_string(regex_constants::error_type n) const + { + if(!m_error_strings.empty()) + { + std::map::const_iterator p = m_error_strings.find(n); + return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second; + } + return get_default_error_string(n); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + char_class_type result = lookup_classname_imp(p1, p2); + if(result == 0) + { + typedef typename string_type::size_type size_type; + string_type temp(p1, p2); + for(size_type i = 0; i < temp.size(); ++i) + temp[i] = this->tolower(temp[i]); + result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size()); + } + return result; + } + string_type lookup_collatename(const charT* p1, const charT* p2) const; + string_type transform_primary(const charT* p1, const charT* p2) const; + string_type transform(const charT* p1, const charT* p2) const + { + return ::boost::BOOST_REGEX_DETAIL_NS::w32_transform(this->m_locale, p1, p2); + } +private: + std::map m_error_strings; // error messages indexed by numberic ID + std::map m_custom_class_names; // character class names + std::map m_custom_collate_names; // collating element names + unsigned m_collate_type; // the form of the collation string + charT m_collate_delim; // the collation group delimiter + // + // helpers: + // + char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const; +}; + +template +typename w32_regex_traits_implementation::string_type + w32_regex_traits_implementation::transform_primary(const charT* p1, const charT* p2) const +{ + string_type result; + // + // What we do here depends upon the format of the sort key returned by + // sort key returned by this->transform: + // + switch(m_collate_type) + { + case sort_C: + case sort_unknown: + // the best we can do is translate to lower case, then get a regular sort key: + { + result.assign(p1, p2); + typedef typename string_type::size_type size_type; + for(size_type i = 0; i < result.size(); ++i) + result[i] = this->tolower(result[i]); + result = this->transform(&*result.begin(), &*result.begin() + result.size()); + break; + } + case sort_fixed: + { + // get a regular sort key, and then truncate it: + result.assign(this->transform(p1, p2)); + result.erase(this->m_collate_delim); + break; + } + case sort_delim: + // get a regular sort key, and then truncate everything after the delim: + result.assign(this->transform(p1, p2)); + std::size_t i; + for(i = 0; i < result.size(); ++i) + { + if(result[i] == m_collate_delim) + break; + } + result.erase(i); + break; + } + if(result.empty()) + result = string_type(1, charT(0)); + return result; +} + +template +typename w32_regex_traits_implementation::string_type + w32_regex_traits_implementation::lookup_collatename(const charT* p1, const charT* p2) const +{ + typedef typename std::map::const_iterator iter_type; + if(m_custom_collate_names.size()) + { + iter_type pos = m_custom_collate_names.find(string_type(p1, p2)); + if(pos != m_custom_collate_names.end()) + return pos->second; + } + std::string name(p1, p2); + name = lookup_default_collate_name(name); + if(name.size()) + return string_type(name.begin(), name.end()); + if(p2 - p1 == 1) + return string_type(1, *p1); + return string_type(); +} + +template +w32_regex_traits_implementation::w32_regex_traits_implementation(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l) +: w32_regex_traits_char_layer(l) +{ + cat_type cat; + std::string cat_name(w32_regex_traits::get_catalog_name()); + if(cat_name.size()) + { + cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name); + if(!cat) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if(cat) + { + // + // Error messages: + // + for(boost::regex_constants::error_type i = static_cast(0); + i <= boost::regex_constants::error_unknown; + i = static_cast(i + 1)) + { + const char* p = get_default_error_string(i); + string_type default_message; + while(*p) + { + default_message.append(1, static_cast(*p)); + ++p; + } + string_type s = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i+200, default_message); + std::string result; + for(std::string::size_type j = 0; j < s.size(); ++j) + { + result.append(1, static_cast(s[j])); + } + m_error_strings[i] = result; + } + // + // Custom class names: + // + static const char_class_type masks[14] = + { + 0x0104u, // C1_ALPHA | C1_DIGIT + 0x0100u, // C1_ALPHA + 0x0020u, // C1_CNTRL + 0x0004u, // C1_DIGIT + (~(0x0020u|0x0008u) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE + 0x0002u, // C1_LOWER + (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL + 0x0010u, // C1_PUNCT + 0x0008u, // C1_SPACE + 0x0001u, // C1_UPPER + 0x0080u, // C1_XDIGIT + 0x0040u, // C1_BLANK + w32_regex_traits_implementation::mask_word, + w32_regex_traits_implementation::mask_unicode, + }; + static const string_type null_string; + for(unsigned int j = 0; j <= 13; ++j) + { + string_type s(::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, j+300, null_string)); + if(s.size()) + this->m_custom_class_names[s] = masks[j]; + } + } + // + // get the collation format used by m_pcollate: + // + m_collate_type = BOOST_REGEX_DETAIL_NS::find_sort_syntax(this, &m_collate_delim); +} + +template +typename w32_regex_traits_implementation::char_class_type + w32_regex_traits_implementation::lookup_classname_imp(const charT* p1, const charT* p2) const +{ + static const char_class_type masks[22] = + { + 0, + 0x0104u, // C1_ALPHA | C1_DIGIT + 0x0100u, // C1_ALPHA + 0x0040u, // C1_BLANK + 0x0020u, // C1_CNTRL + 0x0004u, // C1_DIGIT + 0x0004u, // C1_DIGIT + (~(0x0020u|0x0008u|0x0040) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE or C1_BLANK + w32_regex_traits_implementation::mask_horizontal, + 0x0002u, // C1_LOWER + 0x0002u, // C1_LOWER + (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL + 0x0010u, // C1_PUNCT + 0x0008u, // C1_SPACE + 0x0008u, // C1_SPACE + 0x0001u, // C1_UPPER + w32_regex_traits_implementation::mask_unicode, + 0x0001u, // C1_UPPER + w32_regex_traits_implementation::mask_vertical, + 0x0104u | w32_regex_traits_implementation::mask_word, + 0x0104u | w32_regex_traits_implementation::mask_word, + 0x0080u, // C1_XDIGIT + }; + if(m_custom_class_names.size()) + { + typedef typename std::map, char_class_type>::const_iterator map_iter; + map_iter pos = m_custom_class_names.find(string_type(p1, p2)); + if(pos != m_custom_class_names.end()) + return pos->second; + } + std::size_t state_id = 1u + (std::size_t)BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2); + if(state_id < sizeof(masks) / sizeof(masks[0])) + return masks[state_id]; + return masks[0]; +} + + +template +std::shared_ptr > create_w32_regex_traits(::boost::BOOST_REGEX_DETAIL_NS::lcid_type l) +{ + // TODO: create a cache for previously constructed objects. + return boost::object_cache< ::boost::BOOST_REGEX_DETAIL_NS::lcid_type, w32_regex_traits_implementation >::get(l, 5); +} + +} // BOOST_REGEX_DETAIL_NS + +template +class w32_regex_traits +{ +public: + typedef charT char_type; + typedef std::size_t size_type; + typedef std::basic_string string_type; + typedef ::boost::BOOST_REGEX_DETAIL_NS::lcid_type locale_type; + typedef std::uint_least32_t char_class_type; + + struct boost_extensions_tag{}; + + w32_regex_traits() + : m_pimpl(BOOST_REGEX_DETAIL_NS::create_w32_regex_traits(::boost::BOOST_REGEX_DETAIL_NS::w32_get_default_locale())) + { } + static size_type length(const char_type* p) + { + return std::char_traits::length(p); + } + regex_constants::syntax_type syntax_type(charT c)const + { + return m_pimpl->syntax_type(c); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + return m_pimpl->escape_syntax_type(c); + } + charT translate(charT c) const + { + return c; + } + charT translate_nocase(charT c) const + { + return this->m_pimpl->tolower(c); + } + charT translate(charT c, bool icase) const + { + return icase ? this->m_pimpl->tolower(c) : c; + } + charT tolower(charT c) const + { + return this->m_pimpl->tolower(c); + } + charT toupper(charT c) const + { + return ::boost::BOOST_REGEX_DETAIL_NS::w32_toupper(c, this->m_pimpl->m_locale); + } + string_type transform(const charT* p1, const charT* p2) const + { + return ::boost::BOOST_REGEX_DETAIL_NS::w32_transform(this->m_pimpl->m_locale, p1, p2); + } + string_type transform_primary(const charT* p1, const charT* p2) const + { + return m_pimpl->transform_primary(p1, p2); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_classname(p1, p2); + } + string_type lookup_collatename(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_collatename(p1, p2); + } + bool isctype(charT c, char_class_type f) const + { + if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_base) + && (this->m_pimpl->isctype(f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_base, c))) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_unicode) && BOOST_REGEX_DETAIL_NS::is_extended(c)) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_word) && (c == '_')) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_vertical) + && (::boost::BOOST_REGEX_DETAIL_NS::is_separator(c) || (c == '\v'))) + return true; + else if((f & BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_horizontal) + && this->isctype(c, 0x0008u) && !this->isctype(c, BOOST_REGEX_DETAIL_NS::w32_regex_traits_implementation::mask_vertical)) + return true; + return false; + } + std::intmax_t toi(const charT*& p1, const charT* p2, int radix)const + { + return ::boost::BOOST_REGEX_DETAIL_NS::global_toi(p1, p2, radix, *this); + } + int value(charT c, int radix)const + { + int result = (int)::boost::BOOST_REGEX_DETAIL_NS::global_value(c); + return result < radix ? result : -1; + } + locale_type imbue(locale_type l) + { + ::boost::BOOST_REGEX_DETAIL_NS::lcid_type result(getloc()); + m_pimpl = BOOST_REGEX_DETAIL_NS::create_w32_regex_traits(l); + return result; + } + locale_type getloc()const + { + return m_pimpl->m_locale; + } + std::string error_string(regex_constants::error_type n) const + { + return m_pimpl->error_string(n); + } + + // + // extension: + // set the name of the message catalog in use (defaults to "boost_regex"). + // + static std::string catalog_name(const std::string& name); + static std::string get_catalog_name(); + +private: + std::shared_ptr > m_pimpl; + // + // catalog name handler: + // + static std::string& get_catalog_name_inst(); + +#ifdef BOOST_HAS_THREADS + static std::mutex& get_mutex_inst(); +#endif +}; + +template +std::string w32_regex_traits::catalog_name(const std::string& name) +{ +#ifdef BOOST_HAS_THREADS + std::lock_guard lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + get_catalog_name_inst() = name; + return result; +} + +template +std::string& w32_regex_traits::get_catalog_name_inst() +{ + static std::string s_name; + return s_name; +} + +template +std::string w32_regex_traits::get_catalog_name() +{ +#ifdef BOOST_HAS_THREADS + std::lock_guard lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + return result; +} + +#ifdef BOOST_HAS_THREADS +template +std::mutex& w32_regex_traits::get_mutex_inst() +{ + static std::mutex s_mutex; + return s_mutex; +} +#endif + +namespace BOOST_REGEX_DETAIL_NS { + +#ifdef BOOST_NO_ANSI_APIS + inline unsigned int get_code_page_for_locale_id(lcid_type idx) + { + wchar_t code_page_string[7]; + if (boost::BOOST_REGEX_DETAIL_NS::GetLocaleInfoW(idx, locale_idefaultansicodepage, code_page_string, 7) == 0) + return 0; + + return static_cast(_wtol(code_page_string)); +} +#endif + + template + inline void w32_regex_traits_char_layer::init() + { + // we need to start by initialising our syntax map so we know which + // character is used for which purpose: + std::memset(m_char_map, 0, sizeof(m_char_map)); + cat_type cat; + std::string cat_name(w32_regex_traits::get_catalog_name()); + if (cat_name.size()) + { + cat = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_open(cat_name); + if (!cat) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + ::boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if (cat) + { + for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + string_type mss = ::boost::BOOST_REGEX_DETAIL_NS::w32_cat_get(cat, this->m_locale, i, get_default_syntax(i)); + for (string_type::size_type j = 0; j < mss.size(); ++j) + { + m_char_map[static_cast(mss[j])] = i; + } + } + } + else + { + for (regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + const char* ptr = get_default_syntax(i); + while (ptr && *ptr) + { + m_char_map[static_cast(*ptr)] = i; + ++ptr; + } + } + } + // + // finish off by calculating our escape types: + // + unsigned char i = 'A'; + do + { + if (m_char_map[i] == 0) + { + if (::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, 0x0002u, (char)i)) + m_char_map[i] = regex_constants::escape_type_class; + else if (::boost::BOOST_REGEX_DETAIL_NS::w32_is(this->m_locale, 0x0001u, (char)i)) + m_char_map[i] = regex_constants::escape_type_not_class; + } + } while (0xFF != i++); + + // + // fill in lower case map: + // + char char_map[1 << CHAR_BIT]; + for (int ii = 0; ii < (1 << CHAR_BIT); ++ii) + char_map[ii] = static_cast(ii); +#ifndef BOOST_NO_ANSI_APIS + int r = boost::BOOST_REGEX_DETAIL_NS::LCMapStringA(this->m_locale, lcmap_lowercase, char_map, 1 << CHAR_BIT, this->m_lower_map, 1 << CHAR_BIT); + BOOST_REGEX_ASSERT(r != 0); +#else + unsigned int code_page = get_code_page_for_locale_id(this->m_locale); + BOOST_REGEX_ASSERT(code_page != 0); + + wchar_t wide_char_map[1 << CHAR_BIT]; + int conv_r = boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, char_map, 1 << CHAR_BIT, wide_char_map, 1 << CHAR_BIT); + BOOST_REGEX_ASSERT(conv_r != 0); + + wchar_t wide_lower_map[1 << CHAR_BIT]; + int r = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW(this->m_locale, lcmap_lowercase, wide_char_map, 1 << CHAR_BIT, wide_lower_map, 1 << CHAR_BIT); + BOOST_REGEX_ASSERT(r != 0); + + conv_r = boost::BOOST_REGEX_DETAIL_NS::WideCharToMultiByte(code_page, 0, wide_lower_map, r, this->m_lower_map, 1 << CHAR_BIT, NULL, NULL); + BOOST_REGEX_ASSERT(conv_r != 0); +#endif + if (r < (1 << CHAR_BIT)) + { + // if we have multibyte characters then not all may have been given + // a lower case mapping: + for (int jj = r; jj < (1 << CHAR_BIT); ++jj) + this->m_lower_map[jj] = static_cast(jj); + } + +#ifndef BOOST_NO_ANSI_APIS + r = boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExA(this->m_locale, ct_ctype1, char_map, 1 << CHAR_BIT, this->m_type_map); +#else + r = boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(this->m_locale, ct_ctype1, wide_char_map, 1 << CHAR_BIT, this->m_type_map); +#endif + BOOST_REGEX_ASSERT(0 != r); + } + + inline lcid_type w32_get_default_locale() + { + return boost::BOOST_REGEX_DETAIL_NS::GetUserDefaultLCID(); + } + + inline bool w32_is_lower(char c, lcid_type idx) + { +#ifndef BOOST_NO_ANSI_APIS + word mask; + if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExA(idx, ct_ctype1, &c, 1, &mask) && (mask & c1_lower)) + return true; + return false; +#else + unsigned int code_page = get_code_page_for_locale_id(idx); + if (code_page == 0) + return false; + + wchar_t wide_c; + if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0) + return false; + + word mask; + if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(idx, ct_ctype1, &wide_c, 1, &mask) && (mask & c1_lower)) + return true; + return false; +#endif + } + + inline bool w32_is_lower(wchar_t c, lcid_type idx) + { + word mask; + if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(idx, ct_ctype1, &c, 1, &mask) && (mask & c1_lower)) + return true; + return false; + } + + inline bool w32_is_upper(char c, lcid_type idx) + { +#ifndef BOOST_NO_ANSI_APIS + word mask; + if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExA(idx, ct_ctype1, &c, 1, &mask) && (mask & c1_upper)) + return true; + return false; +#else + unsigned int code_page = get_code_page_for_locale_id(idx); + if (code_page == 0) + return false; + + wchar_t wide_c; + if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0) + return false; + + word mask; + if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(idx, ct_ctype1, &wide_c, 1, &mask) && (mask & c1_upper)) + return true; + return false; +#endif + } + + inline bool w32_is_upper(wchar_t c, lcid_type idx) + { + word mask; + if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(idx, ct_ctype1, &c, 1, &mask) && (mask & c1_upper)) + return true; + return false; + } + + inline void free_module(void* mod) + { + boost::BOOST_REGEX_DETAIL_NS::FreeLibrary(static_cast(mod)); + } + + inline cat_type w32_cat_open(const std::string& name) + { +#ifndef BOOST_NO_ANSI_APIS + cat_type result(boost::BOOST_REGEX_DETAIL_NS::LoadLibraryA(name.c_str()), &free_module); + return result; +#else + wchar_t* wide_name = (wchar_t*)_alloca((name.size() + 1) * sizeof(wchar_t)); + if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(cp_acp, 0, name.c_str(), (int)name.size(), wide_name, (int)(name.size() + 1)) == 0) + return cat_type(); + + cat_type result(boost::BOOST_REGEX_DETAIL_NS::LoadLibraryW(wide_name), &free_module); + return result; +#endif + } + + inline std::string w32_cat_get(const cat_type& cat, lcid_type, int i, const std::string& def) + { +#ifndef BOOST_NO_ANSI_APIS + char buf[256]; + if (0 == boost::BOOST_REGEX_DETAIL_NS::LoadStringA( + static_cast(cat.get()), + i, + buf, + 256 + )) + { + return def; + } +#else + wchar_t wbuf[256]; + int r = boost::BOOST_REGEX_DETAIL_NS::LoadStringW( + static_cast(cat.get()), + i, + wbuf, + 256 + ); + if (r == 0) + return def; + + + int buf_size = 1 + boost::BOOST_REGEX_DETAIL_NS::WideCharToMultiByte(cp_acp, 0, wbuf, r, NULL, 0, NULL, NULL); + char* buf = (char*)_alloca(buf_size); + if (boost::BOOST_REGEX_DETAIL_NS::WideCharToMultiByte(cp_acp, 0, wbuf, r, buf, buf_size, NULL, NULL) == 0) + return def; // failed conversion. +#endif + return std::string(buf); + } + +#ifndef BOOST_NO_WREGEX + inline std::wstring w32_cat_get(const cat_type& cat, lcid_type, int i, const std::wstring& def) + { + wchar_t buf[256]; + if (0 == boost::BOOST_REGEX_DETAIL_NS::LoadStringW(static_cast(cat.get()), i, buf, 256)) + { + return def; + } + return std::wstring(buf); + } +#endif + inline std::string w32_transform(lcid_type idx, const char* p1, const char* p2) + { +#ifndef BOOST_NO_ANSI_APIS + int bytes = boost::BOOST_REGEX_DETAIL_NS::LCMapStringA( + idx, // locale identifier + lcmap_sortkey, // mapping transformation type + p1, // source string + static_cast(p2 - p1), // number of characters in source string + 0, // destination buffer + 0 // size of destination buffer + ); + if (!bytes) + return std::string(p1, p2); + std::string result(++bytes, '\0'); + bytes = boost::BOOST_REGEX_DETAIL_NS::LCMapStringA( + idx, // locale identifier + lcmap_sortkey, // mapping transformation type + p1, // source string + static_cast(p2 - p1), // number of characters in source string + &*result.begin(), // destination buffer + bytes // size of destination buffer + ); +#else + unsigned int code_page = get_code_page_for_locale_id(idx); + if (code_page == 0) + return std::string(p1, p2); + + int src_len = static_cast(p2 - p1); + wchar_t* wide_p1 = (wchar_t*)_alloca((src_len + 1) * 2); + if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, p1, src_len, wide_p1, src_len + 1) == 0) + return std::string(p1, p2); + + int bytes = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW( + idx, // locale identifier + lcmap_sortkey, // mapping transformation type + wide_p1, // source string + src_len, // number of characters in source string + 0, // destination buffer + 0 // size of destination buffer + ); + if (!bytes) + return std::string(p1, p2); + std::string result(++bytes, '\0'); + bytes = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW( + idx, // locale identifier + lcmap_sortkey, // mapping transformation type + wide_p1, // source string + src_len, // number of characters in source string + (wchar_t*) & *result.begin(), // destination buffer + bytes // size of destination buffer + ); +#endif + if (bytes > static_cast(result.size())) + return std::string(p1, p2); + while (result.size() && result[result.size() - 1] == '\0') + { + result.erase(result.size() - 1); + } + return result; + } + +#ifndef BOOST_NO_WREGEX + inline std::wstring w32_transform(lcid_type idx, const wchar_t* p1, const wchar_t* p2) + { + int bytes = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW( + idx, // locale identifier + lcmap_sortkey, // mapping transformation type + p1, // source string + static_cast(p2 - p1), // number of characters in source string + 0, // destination buffer + 0 // size of destination buffer + ); + if (!bytes) + return std::wstring(p1, p2); + std::string result(++bytes, '\0'); + bytes = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW( + idx, // locale identifier + lcmap_sortkey, // mapping transformation type + p1, // source string + static_cast(p2 - p1), // number of characters in source string + reinterpret_cast(&*result.begin()), // destination buffer *of bytes* + bytes // size of destination buffer + ); + if (bytes > static_cast(result.size())) + return std::wstring(p1, p2); + while (result.size() && result[result.size() - 1] == L'\0') + { + result.erase(result.size() - 1); + } + std::wstring r2; + for (std::string::size_type i = 0; i < result.size(); ++i) + r2.append(1, static_cast(static_cast(result[i]))); + return r2; + } +#endif + inline char w32_tolower(char c, lcid_type idx) + { + char result[2]; +#ifndef BOOST_NO_ANSI_APIS + int b = boost::BOOST_REGEX_DETAIL_NS::LCMapStringA( + idx, // locale identifier + lcmap_lowercase, // mapping transformation type + &c, // source string + 1, // number of characters in source string + result, // destination buffer + 1); // size of destination buffer + if (b == 0) + return c; +#else + unsigned int code_page = get_code_page_for_locale_id(idx); + if (code_page == 0) + return c; + + wchar_t wide_c; + if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0) + return c; + + wchar_t wide_result; + int b = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW( + idx, // locale identifier + lcmap_lowercase, // mapping transformation type + &wide_c, // source string + 1, // number of characters in source string + &wide_result, // destination buffer + 1); // size of destination buffer + if (b == 0) + return c; + + if (boost::BOOST_REGEX_DETAIL_NS::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0) + return c; // No single byte lower case equivalent available +#endif + return result[0]; + } + +#ifndef BOOST_NO_WREGEX + inline wchar_t w32_tolower(wchar_t c, lcid_type idx) + { + wchar_t result[2]; + int b = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW( + idx, // locale identifier + lcmap_lowercase, // mapping transformation type + &c, // source string + 1, // number of characters in source string + result, // destination buffer + 1); // size of destination buffer + if (b == 0) + return c; + return result[0]; + } +#endif + inline char w32_toupper(char c, lcid_type idx) + { + char result[2]; +#ifndef BOOST_NO_ANSI_APIS + int b = boost::BOOST_REGEX_DETAIL_NS::LCMapStringA( + idx, // locale identifier + lcmap_uppercase, // mapping transformation type + &c, // source string + 1, // number of characters in source string + result, // destination buffer + 1); // size of destination buffer + if (b == 0) + return c; +#else + unsigned int code_page = get_code_page_for_locale_id(idx); + if (code_page == 0) + return c; + + wchar_t wide_c; + if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0) + return c; + + wchar_t wide_result; + int b = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW( + idx, // locale identifier + lcmap_uppercase, // mapping transformation type + &wide_c, // source string + 1, // number of characters in source string + &wide_result, // destination buffer + 1); // size of destination buffer + if (b == 0) + return c; + + if (boost::BOOST_REGEX_DETAIL_NS::WideCharToMultiByte(code_page, 0, &wide_result, 1, result, 2, NULL, NULL) == 0) + return c; // No single byte upper case equivalent available. +#endif + return result[0]; + } + +#ifndef BOOST_NO_WREGEX + inline wchar_t w32_toupper(wchar_t c, lcid_type idx) + { + wchar_t result[2]; + int b = boost::BOOST_REGEX_DETAIL_NS::LCMapStringW( + idx, // locale identifier + lcmap_uppercase, // mapping transformation type + &c, // source string + 1, // number of characters in source string + result, // destination buffer + 1); // size of destination buffer + if (b == 0) + return c; + return result[0]; + } +#endif + inline bool w32_is(lcid_type idx, std::uint32_t m, char c) + { + word mask; +#ifndef BOOST_NO_ANSI_APIS + if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExA(idx, ct_ctype1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation::mask_base)) + return true; +#else + unsigned int code_page = get_code_page_for_locale_id(idx); + if (code_page == 0) + return false; + + wchar_t wide_c; + if (boost::BOOST_REGEX_DETAIL_NS::MultiByteToWideChar(code_page, 0, &c, 1, &wide_c, 1) == 0) + return false; + + if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(idx, ct_ctype1, &wide_c, 1, &mask) && (mask & m & w32_regex_traits_implementation::mask_base)) + return true; +#endif + if ((m & w32_regex_traits_implementation::mask_word) && (c == '_')) + return true; + return false; + } + +#ifndef BOOST_NO_WREGEX + inline bool w32_is(lcid_type idx, std::uint32_t m, wchar_t c) + { + word mask; + if (boost::BOOST_REGEX_DETAIL_NS::GetStringTypeExW(idx, ct_ctype1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation::mask_base)) + return true; + if ((m & w32_regex_traits_implementation::mask_word) && (c == '_')) + return true; + if ((m & w32_regex_traits_implementation::mask_unicode) && (c > 0xff)) + return true; + return false; + } +#endif + +} // BOOST_REGEX_DETAIL_NS + + +} // boost + +#ifdef BOOST_REGEX_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_REGEX_NO_WIN32_LOCALE + +#endif diff --git a/boost/regex_fwd.hpp b/boost/regex_fwd.hpp new file mode 100644 index 00000000..99371b8c --- /dev/null +++ b/boost/regex_fwd.hpp @@ -0,0 +1,37 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org/libs/regex for documentation. + * FILE regex_fwd.cpp + * VERSION see + * DESCRIPTION: Forward declares boost::basic_regex<> and + * associated typedefs. + */ + +#ifndef BOOST_REGEX_FWD_HPP +#define BOOST_REGEX_FWD_HPP + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif + +#ifdef BOOST_REGEX_CXX03 +#include +#else +#include +#endif + +#endif + + + + diff --git a/boost/scoped_array.hpp b/boost/scoped_array.hpp new file mode 100644 index 00000000..d91889b7 --- /dev/null +++ b/boost/scoped_array.hpp @@ -0,0 +1,15 @@ +#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED +#define BOOST_SCOPED_ARRAY_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// 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) +// +// See http://www.boost.org/libs/smart_ptr/ for documentation. + +#include + +#endif // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED diff --git a/boost/scoped_ptr.hpp b/boost/scoped_ptr.hpp new file mode 100644 index 00000000..334a22e2 --- /dev/null +++ b/boost/scoped_ptr.hpp @@ -0,0 +1,15 @@ +#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED +#define BOOST_SCOPED_PTR_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// 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) +// +// See http://www.boost.org/libs/smart_ptr/ for documentation. + +#include + +#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED diff --git a/boost/smart_ptr/scoped_array.hpp b/boost/smart_ptr/scoped_array.hpp new file mode 100644 index 00000000..d3c250d0 --- /dev/null +++ b/boost/smart_ptr/scoped_array.hpp @@ -0,0 +1,133 @@ +#ifndef BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED +#define BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// 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) +// +// See http://www.boost.org/libs/smart_ptr/ for documentation. + +#include +#include +#include +#include +#include +#include + +#include + +#include // for std::ptrdiff_t + +namespace boost +{ + +// Debug hooks + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +void sp_array_constructor_hook(void * p); +void sp_array_destructor_hook(void * p); + +#endif + +// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to +// is guaranteed, either on destruction of the scoped_array or via an explicit +// reset(). Use shared_array or std::vector if your needs are more complex. + +template class scoped_array // noncopyable +{ +private: + + T * px; + + scoped_array(scoped_array const &); + scoped_array & operator=(scoped_array const &); + + typedef scoped_array this_type; + + void operator==( scoped_array const& ) const; + void operator!=( scoped_array const& ) const; + +public: + + typedef T element_type; + + explicit scoped_array( T * p = 0 ) BOOST_SP_NOEXCEPT : px( p ) + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_array_constructor_hook( px ); +#endif + } + + ~scoped_array() BOOST_SP_NOEXCEPT + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_array_destructor_hook( px ); +#endif + boost::checked_array_delete( px ); + } + + void reset(T * p = 0) BOOST_SP_NOEXCEPT_WITH_ASSERT + { + BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors + this_type(p).swap(*this); + } + + T & operator[](std::ptrdiff_t i) const BOOST_SP_NOEXCEPT_WITH_ASSERT + { + BOOST_ASSERT( px != 0 ); + BOOST_ASSERT( i >= 0 ); + return px[i]; + } + + T * get() const BOOST_SP_NOEXCEPT + { + return px; + } + +// implicit conversion to "bool" +#include + + void swap(scoped_array & b) BOOST_SP_NOEXCEPT + { + T * tmp = b.px; + b.px = px; + px = tmp; + } +}; + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template inline bool operator==( scoped_array const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator==( boost::detail::sp_nullptr_t, scoped_array const & p ) BOOST_SP_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator!=( scoped_array const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT +{ + return p.get() != 0; +} + +template inline bool operator!=( boost::detail::sp_nullptr_t, scoped_array const & p ) BOOST_SP_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + +template inline void swap(scoped_array & a, scoped_array & b) BOOST_SP_NOEXCEPT +{ + a.swap(b); +} + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED diff --git a/boost/smart_ptr/scoped_ptr.hpp b/boost/smart_ptr/scoped_ptr.hpp new file mode 100644 index 00000000..da8df191 --- /dev/null +++ b/boost/smart_ptr/scoped_ptr.hpp @@ -0,0 +1,168 @@ +#ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED + +// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. +// Copyright (c) 2001, 2002 Peter Dimov +// +// 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) +// +// See http://www.boost.org/libs/smart_ptr/ for documentation. + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef BOOST_NO_AUTO_PTR +# include // for std::auto_ptr +#endif + +#if defined( BOOST_SP_DISABLE_DEPRECATED ) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + +namespace boost +{ + +// Debug hooks + +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + +void sp_scalar_constructor_hook(void * p); +void sp_scalar_destructor_hook(void * p); + +#endif + +// scoped_ptr mimics a built-in pointer except that it guarantees deletion +// of the object pointed to, either on destruction of the scoped_ptr or via +// an explicit reset(). scoped_ptr is a simple solution for simple needs; +// use shared_ptr or std::auto_ptr if your needs are more complex. + +template class scoped_ptr // noncopyable +{ +private: + + T * px; + + scoped_ptr(scoped_ptr const &); + scoped_ptr & operator=(scoped_ptr const &); + + typedef scoped_ptr this_type; + + void operator==( scoped_ptr const& ) const; + void operator!=( scoped_ptr const& ) const; + +public: + + typedef T element_type; + + explicit scoped_ptr( T * p = 0 ) BOOST_SP_NOEXCEPT : px( p ) + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_constructor_hook( px ); +#endif + } + +#ifndef BOOST_NO_AUTO_PTR + + explicit scoped_ptr( std::auto_ptr p ) BOOST_SP_NOEXCEPT : px( p.release() ) + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_constructor_hook( px ); +#endif + } + +#endif + + ~scoped_ptr() BOOST_SP_NOEXCEPT + { +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + boost::sp_scalar_destructor_hook( px ); +#endif + boost::checked_delete( px ); + } + + void reset(T * p = 0) BOOST_SP_NOEXCEPT_WITH_ASSERT + { + BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors + this_type(p).swap(*this); + } + + T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT + { + BOOST_ASSERT( px != 0 ); + return *px; + } + + T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT + { + BOOST_ASSERT( px != 0 ); + return px; + } + + T * get() const BOOST_SP_NOEXCEPT + { + return px; + } + +// implicit conversion to "bool" +#include + + void swap(scoped_ptr & b) BOOST_SP_NOEXCEPT + { + T * tmp = b.px; + b.px = px; + px = tmp; + } +}; + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template inline bool operator==( scoped_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator==( boost::detail::sp_nullptr_t, scoped_ptr const & p ) BOOST_SP_NOEXCEPT +{ + return p.get() == 0; +} + +template inline bool operator!=( scoped_ptr const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT +{ + return p.get() != 0; +} + +template inline bool operator!=( boost::detail::sp_nullptr_t, scoped_ptr const & p ) BOOST_SP_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + +template inline void swap(scoped_ptr & a, scoped_ptr & b) BOOST_SP_NOEXCEPT +{ + a.swap(b); +} + +// get_pointer(p) is a generic way to say p.get() + +template inline T * get_pointer(scoped_ptr const & p) BOOST_SP_NOEXCEPT +{ + return p.get(); +} + +} // namespace boost + +#if defined( BOOST_SP_DISABLE_DEPRECATED ) +#pragma GCC diagnostic pop +#endif + +#endif // #ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED diff --git a/boost/type_traits/cv_traits.hpp b/boost/type_traits/cv_traits.hpp new file mode 100644 index 00000000..5bd6c4f0 --- /dev/null +++ b/boost/type_traits/cv_traits.hpp @@ -0,0 +1,24 @@ +// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard +// Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. +// +// defines traits classes for cv-qualified types: +// is_const, is_volatile, remove_const, remove_volatile, remove_cv. + +#ifndef BOOST_TT_CV_TRAITS_HPP_INCLUDED +#define BOOST_TT_CV_TRAITS_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // BOOST_TT_CV_TRAITS_HPP_INCLUDED diff --git a/boost/type_traits/object_traits.hpp b/boost/type_traits/object_traits.hpp new file mode 100644 index 00000000..c812a62e --- /dev/null +++ b/boost/type_traits/object_traits.hpp @@ -0,0 +1,33 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. +// +// defines object traits classes: +// is_object, is_scalar, is_class, is_compound, is_pod, +// has_trivial_constructor, has_trivial_copy, has_trivial_assign, +// has_trivial_destructor, is_empty. +// + +#ifndef BOOST_TT_OBJECT_TRAITS_HPP_INLCUDED +#define BOOST_TT_OBJECT_TRAITS_HPP_INLCUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // BOOST_TT_OBJECT_TRAITS_HPP_INLCUDED diff --git a/boost/type_traits/same_traits.hpp b/boost/type_traits/same_traits.hpp new file mode 100644 index 00000000..dab7dac7 --- /dev/null +++ b/boost/type_traits/same_traits.hpp @@ -0,0 +1,15 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/type_traits for most recent version including documentation. +// +// defines is_same: + +#ifndef BOOST_TT_SAME_TRAITS_HPP_INCLUDED +#define BOOST_TT_SAME_TRAITS_HPP_INCLUDED + +#include + +#endif // BOOST_TT_SAME_TRAITS_HPP_INCLUDED diff --git a/build.cmd b/build.cmd index 4308e501..ba72feb3 100644 --- a/build.cmd +++ b/build.cmd @@ -2,6 +2,7 @@ bcp ^ boost/asio/asio.hpp ^ boost/container/flat_map.hpp ^ boost/container/flat_set.hpp ^ + boost/container/list.hpp ^ boost/container/small_vector.hpp ^ boost/container/static_vector.hpp ^ boost/icl/interval_map.hpp ^ @@ -9,5 +10,11 @@ bcp ^ boost/icl/separate_interval_set.hpp ^ boost/intrusive/list.hpp ^ boost/intrusive/set.hpp ^ + boost/pointee.hpp ^ align ^ + range ^ + optional ^ + utility ^ + tuple ^ + iterator ^ --boost="%1" . diff --git a/build.sh b/build.sh index 5dfb7729..fed1927c 100755 --- a/build.sh +++ b/build.sh @@ -4,6 +4,7 @@ bcp \ boost/asio/asio.hpp \ boost/container/flat_map.hpp \ boost/container/flat_set.hpp \ + boost/container/list.hpp \ boost/container/small_vector.hpp \ boost/container/static_vector.hpp \ boost/icl/interval_map.hpp \ @@ -11,7 +12,13 @@ bcp \ boost/icl/separate_interval_set.hpp \ boost/intrusive/list.hpp \ boost/intrusive/set.hpp \ + boost/pointee.hpp \ align \ + range \ + optional \ + utility \ + tuple \ + iterator \ --boost="$1" . find . -type f -print0 | xargs -0 dos2unix \ No newline at end of file diff --git a/doc/src/boostbook.css b/doc/src/boostbook.css new file mode 100644 index 00000000..28317657 --- /dev/null +++ b/doc/src/boostbook.css @@ -0,0 +1,789 @@ + +/*============================================================================= +Copyright (c) 2004 Joel de Guzman +http://spirit.sourceforge.net/ + +Copyright 2013 Niall Douglas additions for colors and alignment. +Copyright 2013 Paul A. Bristow additions for more colors and alignments. +Copyright 2017 Tom Westerhout font fixes to support Sphinx + +Distributed under the Boost Software License, Version 1.0. (See accompany- +ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + +/*============================================================================= +Body defaults +=============================================================================*/ + + body + { + margin: 1em; + font-size: 16px; + font-family: sans-serif; + } + +/*============================================================================= +Paragraphs +=============================================================================*/ + + p, div.document, div.footer + { + text-align: left; + font-size: 10pt; + line-height: 1.15; + } + +/*============================================================================= +Program listings +=============================================================================*/ + + /* Code on paragraphs */ + p tt.computeroutput + { + font-size: 9pt; + } + + pre.synopsis + { + font-size: 9pt; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + div.highlight, + .programlisting, + .screen + { + font-size: 9pt; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + /* Program listings in tables don't get borders */ + td .programlisting, + td .screen + { + margin: 0pc 0pc 0pc 0pc; + padding: 0pc 0pc 0pc 0pc; + } + +/*============================================================================= +Headings +=============================================================================*/ + + h1, h2, h3, h4, h5, h6 + { + text-align: left; + margin: 1em 0em 0.5em 0em; + font-weight: bold; + } + + h1 { font-size: 140%; } + h2 { font-weight: bold; font-size: 140%; } + h3 { font-weight: bold; font-size: 130%; } + h4 { font-weight: bold; font-size: 120%; } + h5 { font-weight: normal; font-style: italic; font-size: 110%; } + h6 { font-weight: normal; font-style: italic; font-size: 100%; } + + /* Top page titles */ + title, + h1.title, + h2.title + h3.title, + h4.title, + h5.title, + h6.title, + .refentrytitle + { + font-weight: bold; + margin-bottom: 1pc; + } + + h1.title { font-size: 140% } + h2.title { font-size: 140% } + h3.title { font-size: 130% } + h4.title { font-size: 120% } + h5.title { font-size: 110% } + h6.title { font-size: 100% } + + .section h1 + { + margin: 0em 0em 0.5em 0em; + font-size: 140%; + } + + .section h2 { font-size: 140% } + .section h3 { font-size: 130% } + .section h4 { font-size: 120% } + .section h5 { font-size: 110% } + .section h6 { font-size: 100% } + + /* Code on titles */ + h1 tt.computeroutput { font-size: 140% } + h2 tt.computeroutput { font-size: 140% } + h3 tt.computeroutput { font-size: 130% } + h4 tt.computeroutput { font-size: 130% } + h5 tt.computeroutput { font-size: 130% } + h6 tt.computeroutput { font-size: 130% } + + +/*============================================================================= +Author +=============================================================================*/ + + h3.author + { + font-size: 100% + } + +/*============================================================================= +Lists +=============================================================================*/ + + li + { + font-size: 10pt; + line-height: 1.3; + } + + /* Unordered lists */ + ul + { + text-align: left; + } + + /* Ordered lists */ + ol + { + text-align: left; + } + +/*============================================================================= +Links +=============================================================================*/ + + a + { + text-decoration: none; /* no underline */ + } + + a:hover + { + text-decoration: underline; + } + +/*============================================================================= +Spirit style navigation +=============================================================================*/ + + .spirit-nav + { + text-align: right; + } + + .spirit-nav a + { + color: white; + padding-left: 0.5em; + } + + .spirit-nav img + { + border-width: 0px; + } + +/*============================================================================= +Copyright footer +=============================================================================*/ + .copyright-footer + { + text-align: right; + font-size: 70%; + } + + .copyright-footer p + { + text-align: right; + font-size: 80%; + } + +/*============================================================================= +Table of contents +=============================================================================*/ + + div.toc + { + margin: 1pc 4% 0pc 4%; + padding: 0.1pc 1pc 0.1pc 1pc; + font-size: 80%; + line-height: 1.15; + } + + .boost-toc + { + float: right; + padding: 0.5pc; + } + + /* Code on toc */ + .toc .computeroutput { font-size: 120% } + + /* No margin on nested menus */ + + .toc dl dl { margin: 0; } + +/*============================================================================= +Tables +=============================================================================*/ + + .table-title, + div.table p.title + { + margin-left: 4%; + padding-right: 0.5em; + padding-left: 0.5em; + } + + .informaltable table, + .table table + { + width: 92%; + margin-left: 4%; + margin-right: 4%; + } + + div.informaltable table, + div.table table + { + padding: 4px; + } + + /* Table Cells */ + div.informaltable table tr td, + div.table table tr td + { + padding: 0.5em; + text-align: left; + font-size: 9pt; + } + + div.informaltable table tr th, + div.table table tr th + { + padding: 0.5em 0.5em 0.5em 0.5em; + border: 1pt solid white; + font-size: 80%; + } + + table.simplelist + { + width: auto !important; + margin: 0em !important; + padding: 0em !important; + border: none !important; + } + table.simplelist td + { + margin: 0em !important; + padding: 0em !important; + text-align: left !important; + font-size: 9pt !important; + border: none !important; + } + +/*============================================================================= +Suppress margins in tables +=============================================================================*/ + + table th > *:first-child, + table td > *:first-child + { + margin-top: 0; + } + + table th > *:last-child, + table td > *:last-child + { + margin-bottom: 0; + } + +/*============================================================================= +Blurbs +=============================================================================*/ + + div.note, + div.tip, + div.important, + div.caution, + div.warning, + div.blurb, + p.blurb + { + font-size: 9pt; /* A little bit smaller than the main text */ + line-height: 1.2; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + div.blurb img, + p.blurb img + { + padding: 1pt; + } + +/*============================================================================= +Variable Lists +=============================================================================*/ + + div.variablelist + { + margin: 1em 0; + } + + /* Make the terms in definition lists bold */ + div.variablelist dl dt, + span.term + { + font-weight: bold; + font-size: 10pt; + } + + div.variablelist table tbody tr td + { + text-align: left; + vertical-align: top; + padding: 0em 2em 0em 0em; + font-size: 10pt; + margin: 0em 0em 0.5em 0em; + line-height: 1; + } + + div.variablelist dl dt + { + margin-bottom: 0.2em; + } + + div.variablelist dl dd + { + margin: 0em 0em 0.5em 2em; + font-size: 10pt; + } + + div.variablelist table tbody tr td p, + div.variablelist dl dd p + { + margin: 0em 0em 0.5em 0em; + line-height: 1; + } + +/*============================================================================= +Misc +=============================================================================*/ + + /* Title of books and articles in bibliographies */ + span.title + { + font-style: italic; + } + + span.underline + { + text-decoration: underline; + } + + span.strikethrough + { + text-decoration: line-through; + } + + /* Copyright, Legal Notice */ + div div.legalnotice p + { + text-align: left + } + +/*============================================================================= +Colors +=============================================================================*/ + + @media screen + { + body { + background-color: #FFFFFF; + color: #000000; + } + + /* Syntax Highlighting */ + .property, + .highlight .k, + .highlight .kc, + .highlight .kd, + .highlight .kn, + .highlight .kp, + .highlight .kr, + .highlight .kt, + .keyword { color: #0000AA; } + + .highlight .n, + .highlight .na, + .highlight .nb, + .highlight .bp, + .highlight .nc, + .highlight .no, + .highlight .nd, + .highlight .ni, + .highlight .ne, + .highlight .nf, + .highlight .py, + .highlight .nl, + .highlight .nn, + .highlight .nx, + .highlight .nt, + .highlight .nv, + .highlight .vc, + .highlight .vg, + .highlight .vi, + .identifier { color: #000000; } + + .special { color: #707070; } + + .highlight .cp, + .preprocessor { color: #402080; } + + .highlight .sc + .char { color: teal; } + + .highlight .c, + .highlight .ch, + .highlight .cm, + .highlight .cp, + .highlight .cpf, + .highlight .c1, + .highlight .cs, + .highlight .sd, + .highlight .sh, + .comment { color: #800000; } + + .highlight .s, + .highlight .sa, + .highlight .sb, + .highlight .dl, + .highlight .s2, + .highlight .se, + .highlight .si, + .highlight .sx, + .highlight .sr, + .highlight .s1, + .highlight .ss, + .string { color: teal; } + + .highlight .m, + .highlight .mf, + .highlight .mh, + .highlight .mi, + .highlight .mo, + .number { color: teal; } + + .highlight, + .white_bkd { background-color: #FFFFFF; } + + .highlight .hll, + .dk_grey_bkd { background-color: #999999; } + + /* Links */ + a, a .keyword, a .identifier, a .special, a .preprocessor + a .char, a .comment, a .string, a .number + { + color: #005a9c; + } + + a:visited, a:visited .keyword, a:visited .identifier, + a:visited .special, a:visited .preprocessor a:visited .char, + a:visited .comment, a:visited .string, a:visited .number + { + color: #9c5a9c; + } + + h1 a, h2 a, h3 a, h4 a, h5 a, h6 a, + h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover, + h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited + { + text-decoration: none; /* no underline */ + color: #000000; + } + + /* Copyright, Legal Notice */ + .copyright + { + color: #666666; + font-size: small; + } + + div div.legalnotice p + { + color: #666666; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid #DCDCDC; + } + + div.highlight, + .programlisting, + .screen + { + border: 1px solid #DCDCDC; + } + + td .programlisting, + td .screen + { + border: 0px solid #DCDCDC; + } + + /* Blurbs */ + div.note, + div.tip, + div.important, + div.caution, + div.warning, + div.blurb, + p.blurb + { + border: 1px solid #DCDCDC; + } + + /* Table of contents */ + div.toc + { + border: 1px solid #DCDCDC; + } + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid #DCDCDC; + } + + div.informaltable table tr th, + div.table table tr th + { + background-color: #F0F0F0; + border: 1px solid #DCDCDC; + } + + .copyright-footer + { + color: #8F8F8F; + } + + /* Misc */ + span.highlight + { + color: #00A000; + } + } + + @media print + { + /* Links */ + a + { + color: black; + } + + a:visited + { + color: black; + } + + .spirit-nav + { + display: none; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid gray; + } + + div.highlight, + .programlisting, + .screen + { + border: 1px solid gray; + } + + td .programlisting, + td .screen + { + border: 0px solid #DCDCDC; + } + + /* Table of contents */ + div.toc + { + border: 1px solid gray; + } + + .informaltable table, + .table table + { + border: 1px solid gray; + border-collapse: collapse; + } + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid gray; + } + + div.informaltable table tr th, + div.table table tr th + { + border: 1px solid gray; + } + + table.simplelist tr td + { + border: none !important; + } + + /* Misc */ + span.highlight + { + font-weight: bold; + } + } + +/*============================================================================= +Images +=============================================================================*/ + + span.inlinemediaobject img + { + vertical-align: middle; + } + +/*============================================================================== +Super and Subscript: style so that line spacing isn't effected, see +http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&productId=1&postId=5341 +==============================================================================*/ + +sup, +sub { +height: 0; +line-height: 1; +vertical-align: baseline; +position: relative; + +} + +/* For internet explorer: */ + +* html sup, +* html sub { +vertical-align: bottom; +} + +sup { +bottom: 1ex; +} + +sub { +top: .5ex; +} + +/*============================================================================== +Indexes: pretty much the same as the TOC. +==============================================================================*/ + + .index + { + font-size: 80%; + padding-top: 0px; + padding-bottom: 0px; + margin-top: 0px; + margin-bottom: 0px; + margin-left: 0px; + } + + .index ul + { + padding-left: 3em; + } + + .index p + { + padding: 2px; + margin: 2px; + } + + .index-entry-level-0 + { + font-weight: bold; + } + + .index em + { + font-weight: bold; + } + + +/*============================================================================== +Alignment and coloring use 'role' feature, available from Quickbook 1.6 up. +Added from Niall Douglas for role color and alignment. +http://article.gmane.org/gmane.comp.lib.boost.devel/243318 +*/ + +/* Add text alignment (see http://www.w3schools.com/cssref/pr_text_text-align.asp) */ +span.aligncenter +{ + display: inline-block; width: 100%; text-align: center; +} +span.alignright +{ + display: inline-block; width: 100%; text-align: right; +} +/* alignleft is the default. */ +span.alignleft +{ + display: inline-block; width: 100%; text-align: left; +} + +/* alignjustify stretches the word spacing so that each line has equal width +within a chosen fraction of page width (here arbitrarily 20%). +*Not* useful inside table items as the column width remains the total string width. +Nor very useful, except to temporarily restrict the width. +*/ +span.alignjustify +{ + display: inline-block; width: 20%; text-align: justify; +} + +/* Text colors. +Names at http://www.w3.org/TR/2002/WD-css3-color-20020219/ 4.3. X11 color keywords. +Quickbook Usage: [role red Some red text] + +*/ +span.red { inline-block; color: red; } +span.green { color: green; } +span.lime { color: #00FF00; } +span.blue { color: blue; } +span.navy { color: navy; } +span.yellow { color: yellow; } +span.magenta { color: magenta; } +span.indigo { color: #4B0082; } +span.cyan { color: cyan; } +span.purple { color: purple; } +span.gold { color: gold; } +span.silver { color: silver; } /* lighter gray */ +span.gray { color: #808080; } /* light gray */ diff --git a/doc/src/images/caution.png b/doc/src/images/caution.png new file mode 100644 index 0000000000000000000000000000000000000000..5b7809ca4a9c8d778087522e5ce04b6e90099595 GIT binary patch literal 1250 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbQ|Pftew|C&U%V<=|it5MYpyU{F+K zFf?Rva$<;zVn|MA$j)XcE@r5%W@u>vqT-$&hMpcE*)wGd!;~q-Q>IkUnZqz=PVt;M zK*p3gbLK2v%CK~4^3tV1#?q}@8MbbX+PXD)>(;G%_cH9=n|$sZ!?|yxmE{-7;w@N47?rU=3X_NkV zU|o{PnRTZ;lXp4>+)hZU_|Lw%*va*6=<@jI@BP^`_OsZ?pZg-2AaGf|;i2L0<>du@ zeRrO4er03}pLSxdREd>pap^;~&E+}=JYKy#vHnLI=Z$}pPyA_`zG;G~<$`Br2do;7 z$Heivv0AeyJYVI({@6?X6r+V~XS2Cs!|bddDqJz@2lKf$~4dA1c%lfOT+5KMUSWi#X5(9ePxx_W1Bsf2+N)z4*}Q$iB}K{RAP literal 0 HcmV?d00001 diff --git a/doc/src/images/home.png b/doc/src/images/home.png new file mode 100644 index 0000000000000000000000000000000000000000..5584aacb097a80e66a5320312b6e4eb017af1a06 GIT binary patch literal 358 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7T3?v)swEqJs=3*z$5DpHG+YkL80J$mwJ|V8+ zB7)tW9nKDRM~@s%h>KBER+u?+=H<(mwr$-K=fo0^iDsNj}a zlvro>7z#vFJHct5EtX@VE6z3e?1}lM4)<}k|4ieAQuK0 zgzld^2NdTl@Q5sCVBi)4Va7{$>;3=*RZCnWN`mv#O3D+9QW<;`lZ*0mQ&Tb%72Gn5 zQp@v;vWpdbBNU7b3{2X~)|>}w5Cds&E=o--$;{7F2+7P%WiT|*H!#*WFgd=yhZCqG z!qdeuq+(9;4PKV1Hyx6gnJ3)X*T8%1&d~!CcvGht8EkNzY0cztDB;<=un7h&oMQJ5 zOnAh^!sYOgmxqZbU_wKJkwW(@g)2%k8?y8!<$B~f6iH61Ubv5eVdat_!+^S!9H1Qx Mp00i_>zopr0Jz|Gn*aa+ literal 0 HcmV?d00001 diff --git a/doc/src/images/note.png b/doc/src/images/note.png new file mode 100644 index 0000000000000000000000000000000000000000..d0c3c645ab9af6318035b026dd86944b9ddc9114 GIT binary patch literal 490 zcmeAS@N?(olHy`uVBq!ia0vp^5+KY0Bp8m$B&h%?rX+877Y2q^y~;)m42&$EE{-7; zw^Ao5PC9JB<666~wbh%Oo7tJ0_rGWfi({a(qjR96>_P4H$tJl=Pxd^1p6`8M?=jE( z!hchf6<8Mi`NHe6`iia69>!lxe4C2-S>+Wvj;l63k!MNSb9|1+f-i>irDi|a^uLl% z^#-f2#pQ2lC%m~9m9JWJZL3|T8FRX>A78<>cU{Z6XGFG336=OLGkw25|29|RG_k%U z>j|M}Ih2i#-w+9_3T~N2 zspa`a*~JRJ5eh~I1}5!gYt92Th=DXX7o{eaWaj57gkwm>gfq&(JZLf6ZeXy%aV8%R&r1O{j}20XTDX{IIykaj z4Nx#hVBm6cU}k1+>Qw1kB6gA`rFdeFa~bob(-ZFQzAc!;#K4>y+$E64`2%PJgQu&X J%Q~loCIAR&aHIeL literal 0 HcmV?d00001 diff --git a/doc/src/images/up.png b/doc/src/images/up.png new file mode 100644 index 0000000000000000000000000000000000000000..17d9c3ec491ae1ba22188ce85985623c92ffa9be GIT binary patch literal 370 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7T3?v)swEqJs=3*z$5DpHG+YkL80J&NLJ|V8+ zB7$jYY0eII+qQ05v3zNFXUFBsmjeBL)sz)x&YXGl$l-*zm`9Hu{{R1f8uJZXpf0|W zAirQB7XcVt58OEcl;JG!h%9Dc;1&X5#!GkW{s0A4OI#yLg7ec#$`gxH8GI9yi}G_* zQ!*13+%k(&%kzt}ixqq$6pRcEOxnxVoCj(U18HzBN=+=u%+FH@$;?eS^Z=hXV#3jn*#4_ x=vj5p^wF)?xpx*Du6ddKc=uuXxWffq{6A*KyDFWJxdXJF!PC{xWt~$(69DY=mmvTE literal 0 HcmV?d00001 diff --git a/doc/src/images/warning.png b/doc/src/images/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..1c33db8f34a8b42b373179b46a2d8d8a10e061a9 GIT binary patch literal 1241 zcmeHH+e?!H6#vDtmgHCxG{Q}12(7`~)|MMe^RnTlY0JD#q1sIwW1DTCqzzwWg@Q=t zBC2Iceu@w4LHM97Gb5%*E%9MN*%m}jvs!{N@Pd8$H}vS?TsRzlzr#5kPPe|YG%fXL zDu6VdR$WC$&Oc)^X#ZjK-7LU>{!F!o39xr+d_Vw5fMTEwpb-s#9q<5Nzz6gIepyU?Lctpr{ZK zVzWaWPAC)#17S8h%;AIuf(Q_yeIybEqS0s^i1YdJcsv0ln9M{Xkpz;-I_^=P))~D~!!Hvpq{Dl8O{rN@cECkt>#DncX%I(O&3i_YgL-$m$VU zT3cLBLS%M1`o{TBX}S|Tbhc)vk!Yp)%rdDd&my(RPsxl%lU$)tC?(1~WuEwClUQn! n$Q8O{Mxt@ukkcT{K0> literal 0 HcmV?d00001 diff --git a/libs/align/.github/workflows/ci.yml b/libs/align/.github/workflows/ci.yml new file mode 100644 index 00000000..5afb6259 --- /dev/null +++ b/libs/align/.github/workflows/ci.yml @@ -0,0 +1,185 @@ +name: CI + +on: + pull_request: + push: + branches: + - master + - develop + +jobs: + posix: + strategy: + fail-fast: false + matrix: + include: + - toolset: gcc-4.8 + standard: "03,11" + os: ubuntu-18.04 + install: g++-4.8 + - toolset: gcc-5 + standard: "03,11,14,1z" + os: ubuntu-18.04 + install: g++-5 + - toolset: gcc-6 + standard: "03,11,14,1z" + os: ubuntu-18.04 + install: g++-6 + - toolset: gcc-7 + standard: "03,11,14,17" + os: ubuntu-18.04 + - toolset: gcc-8 + standard: "03,11,14,17,2a" + os: ubuntu-18.04 + install: g++-8 + - toolset: gcc-9 + standard: "03,11,14,17,2a" + os: ubuntu-18.04 + - toolset: gcc-10 + standard: "03,11,14,17,2a" + os: ubuntu-20.04 + install: g++-10 + - toolset: gcc-11 + standard: "03,11,14,17,2a" + os: ubuntu-20.04 + install: g++-11 + - toolset: clang + compiler: clang++-3.9 + standard: "03,11,14" + os: ubuntu-18.04 + install: clang-3.9 + - toolset: clang + compiler: clang++-4.0 + standard: "03,11,14" + os: ubuntu-18.04 + install: clang-4.0 + - toolset: clang + compiler: clang++-5.0 + standard: "03,11,14,1z" + os: ubuntu-18.04 + install: clang-5.0 + - toolset: clang + compiler: clang++-6.0 + standard: "03,11,14,17" + os: ubuntu-18.04 + install: clang-6.0 + - toolset: clang + compiler: clang++-7 + standard: "03,11,14,17" + os: ubuntu-18.04 + install: clang-7 + - toolset: clang + compiler: clang++-8 + standard: "03,11,14,17" + os: ubuntu-20.04 + install: clang-8 + - toolset: clang + compiler: clang++-9 + standard: "03,11,14,17,2a" + os: ubuntu-20.04 + install: clang-9 + - toolset: clang + compiler: clang++-10 + standard: "03,11,14,17,2a" + os: ubuntu-20.04 + install: clang-10 + - toolset: clang + compiler: clang++-11 + cxxstd: "03,11,14,17,2a" + os: ubuntu-20.04 + install: clang-11 + - toolset: clang + compiler: clang++-12 + cxxstd: "03,11,14,17,2a" + os: ubuntu-20.04 + install: clang-12 + - toolset: clang + standard: "03,11,14,17,2a" + os: macos-10.15 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v2 + + - name: Install packages + if: matrix.install + run: sudo apt install ${{matrix.install}} + + - name: Setup Boost + run: | + cd .. + git clone --depth 1 https://github.com/boostorg/boost + cd boost + cp -r $GITHUB_WORKSPACE/* libs/align + git submodule init libs/assert + git submodule init libs/config + git submodule init libs/core + git submodule init libs/static_assert + git submodule init libs/headers + git submodule init tools/build + git submodule init tools/boost_install + git submodule update + ./bootstrap.sh + ./b2 -d0 headers + + - name: Create user-config.jam + if: matrix.compiler + run: | + echo "using ${{matrix.toolset}} : : ${{matrix.compiler}} ;" > ~/user-config.jam + + - name: Run tests + run: | + cd ../boost + ./b2 -j3 libs/align/test toolset=${{matrix.toolset}} cxxstd=${{matrix.standard}} variant=debug,release + + windows: + strategy: + fail-fast: false + matrix: + include: + - toolset: msvc-14.1 + standard: "14,17,latest" + target: 32,64 + os: windows-2016 + - toolset: msvc-14.2 + standard: "14,17,latest" + target: 32,64 + os: windows-2019 + - toolset: msvc-14.3 + cxxstd: "14,17,latest" + addrmd: 32,64 + os: windows-2022 + - toolset: gcc + standard: "03,11,14,17,2a" + target: 64 + os: windows-2019 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v2 + + - name: Setup Boost + shell: cmd + run: | + cd .. + git clone --depth 1 https://github.com/boostorg/boost boost + cd boost + xcopy /s /e /q %GITHUB_WORKSPACE% libs\align\ + git submodule init libs/assert + git submodule init libs/config + git submodule init libs/core + git submodule init libs/static_assert + git submodule init libs/headers + git submodule init tools/build + git submodule init tools/boost_install + git submodule update + cmd /c bootstrap + b2 -d0 headers + + - name: Run tests + shell: cmd + run: | + cd ../boost + b2 -j3 libs/align/test toolset=${{matrix.toolset}} cxxstd=${{matrix.standard}} address-model=${{matrix.target}} variant=debug,release diff --git a/libs/align/.travis.yml b/libs/align/.travis.yml new file mode 100644 index 00000000..19ccabaf --- /dev/null +++ b/libs/align/.travis.yml @@ -0,0 +1,297 @@ +# Copyright 2017 Glen Joseph Fernandes +# (glenjofe@gmail.com) +# +# Distributed under the Boost Software License, Version 1.0. +# (http://www.boost.org/LICENSE_1_0.txt) + +language: cpp + +sudo: false + +dist: xenial + +branches: + only: + - master + - develop + +env: + matrix: + - EMPTY=true + +matrix: + + exclude: + - env: EMPTY=true + + include: + - os: linux + compiler: g++ + env: TOOLSET=gcc COMPILER=g++ STANDARD=03,11 + + - os: linux + compiler: g++-4.4 + env: TOOLSET=gcc COMPILER=g++-4.4 STANDARD=98,0x + addons: + apt: + packages: + - g++-4.4 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-4.6 + env: TOOLSET=gcc COMPILER=g++-4.6 STANDARD=03,0x + addons: + apt: + packages: + - g++-4.6 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-4.7 + env: TOOLSET=gcc COMPILER=g++-4.7 STANDARD=03,11 + addons: + apt: + packages: + - g++-4.7 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-4.8 + env: TOOLSET=gcc COMPILER=g++-4.8 STANDARD=03,11 + addons: + apt: + packages: + - g++-4.8 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-4.9 + env: TOOLSET=gcc COMPILER=g++-4.9 STANDARD=03,11 + addons: + apt: + packages: + - g++-4.9 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-5 + env: TOOLSET=gcc COMPILER=g++-5 STANDARD=03,11,14,1z + addons: + apt: + packages: + - g++-5 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-6 + env: TOOLSET=gcc COMPILER=g++-6 STANDARD=03,11,14,1z + addons: + apt: + packages: + - g++-6 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-7 + env: TOOLSET=gcc COMPILER=g++-7 STANDARD=03,11,14,17 + addons: + apt: + packages: + - g++-7 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-8 + env: TOOLSET=gcc COMPILER=g++-8 STANDARD=03,11,14,17,2a + addons: + apt: + packages: + - g++-8 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-9 + env: TOOLSET=gcc COMPILER=g++-9 STANDARD=03,11,14,17,2a + addons: + apt: + packages: + - g++-9 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++ + env: TOOLSET=clang COMPILER=clang++ STANDARD=03,11 + + - os: linux + dist: trusty + compiler: /usr/bin/clang++ + env: TOOLSET=clang COMPILER=/usr/bin/clang++ STANDARD=03,11 + addons: + apt: + packages: + - clang-3.3 + + - os: linux + dist: trusty + compiler: /usr/bin/clang++ + env: TOOLSET=clang COMPILER=/usr/bin/clang++ STANDARD=03,11 + addons: + apt: + packages: + - clang-3.4 + + - os: linux + dist: trusty + compiler: clang++-3.5 + env: TOOLSET=clang COMPILER=clang++-3.5 STANDARD=03,11,14,1z + addons: + apt: + packages: + - clang-3.5 + - libstdc++-4.9-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.5 + + - os: linux + compiler: clang++-3.6 + env: TOOLSET=clang COMPILER=clang++-3.6 STANDARD=03,11,14,1z + addons: + apt: + packages: + - clang-3.6 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-3.7 + env: TOOLSET=clang COMPILER=clang++-3.7 STANDARD=03,11,14,1z + addons: + apt: + packages: + - clang-3.7 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-3.8 + env: TOOLSET=clang COMPILER=clang++-3.8 STANDARD=03,11,14,1z + addons: + apt: + packages: + - clang-3.8 + - libstdc++-4.9-dev + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-3.9 + env: TOOLSET=clang COMPILER=clang++-3.9 STANDARD=03,11,14,1z + addons: + apt: + packages: + - clang-3.9 + - libstdc++-4.9-dev + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-4.0 + env: TOOLSET=clang COMPILER=clang++-4.0 STANDARD=03,11,14,1z + addons: + apt: + packages: + - clang-4.0 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-5.0 + env: TOOLSET=clang COMPILER=clang++-5.0 STANDARD=03,11,14,1z + addons: + apt: + packages: + - clang-5.0 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-6.0 + env: TOOLSET=clang COMPILER=clang++-6.0 STANDARD=03,11,14,17,2a + addons: + apt: + packages: + - clang-6.0 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++-7 + env: TOOLSET=clang COMPILER=clang++-7 STANDARD=03,11,14,17,2a + addons: + apt: + packages: + - clang-7 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-7 + + - os: linux + compiler: clang++-8 + env: TOOLSET=clang COMPILER=clang++-8 STANDARD=03,11,14,17,2a + addons: + apt: + packages: + - clang-8 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-xenial-8 + + - os: linux + dist: trusty + compiler: clang++-libc++ + env: TOOLSET=clang COMPILER=clang++-libc++ STANDARD=03,11,14,1z + addons: + apt: + packages: + - libc++-dev + + - os: osx + compiler: clang++ + env: TOOLSET=clang COMPILER=clang++ STANDARD=03,11,14,1z + +install: + - cd .. + - git clone -b $TRAVIS_BRANCH https://github.com/boostorg/boost + - cd boost + - git submodule init libs/assert + - git submodule init libs/config + - git submodule init libs/core + - git submodule init libs/static_assert + - git submodule init libs/headers + - git submodule init tools/build + - git submodule init tools/boost_install + - git submodule update + - cp -R $TRAVIS_BUILD_DIR/* libs/align + - ./bootstrap.sh + - ./b2 headers + +script: + - |- + echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam + - ./b2 libs/align/test toolset=$TOOLSET cxxstd=$STANDARD + +notifications: + email: + on_success: always diff --git a/libs/config/test/config_info.cpp b/libs/config/test/config_info.cpp new file mode 100644 index 00000000..4825470c --- /dev/null +++ b/libs/config/test/config_info.cpp @@ -0,0 +1,1567 @@ +// Boost config.hpp configuration test program file -----------------------// + +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Jens Maurer 2001. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright Darin Adler 2001. +// (C) Copyright Beman Dawes 2002. +// Use, modification and distribution are subject to 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) + +// See http://www.boost.org/libs/config for most recent version. +// +// Revision $Id$ +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_UNISTD_H +#include +#endif + +#if defined(__MINGW32__) +# include <_mingw.h> +#endif + +static unsigned int indent = 4; +static unsigned int width = 40; + +using std::cout; +using std::istream; + +void print_macro(const char* name, const char* value) +{ + // if name == value+1 then then macro is not defined, + // in which case we don't print anything: + if(0 != strcmp(name, value+1)) + { + for(unsigned i = 0; i < indent; ++i) std::cout.put(' '); + std::cout << std::setw(width); + cout.setf(istream::left, istream::adjustfield); + std::cout << name; + if(value[1]) + { + // macro has a value: + std::cout << value << "\n"; + } + else + { + // macro is defined but has no value: + std::cout << " [no value]\n"; + } + } +} + +#define PRINT_MACRO(X) print_macro(#X, BOOST_STRINGIZE(=X)) + +template +void print_expression(const char* expression, T val) +{ + for(unsigned i = 0; i < indent; ++i) std::cout.put(' '); + std::cout << std::setw(width); + std::cout.setf(istream::left, istream::adjustfield); + std::cout << expression << "=" << val << std::endl; +} + +#define PRINT_EXPRESSION(E) print_expression(#E, E); + +template +void print_byte_order(const char* what, T /* t */ ) +{ + T val = 0; + unsigned i; + for(i = 1; i < sizeof(T); ++i) + { + val |= (CHAR_BIT * static_cast(i)) << (CHAR_BIT * static_cast(i)); + } + const char* p = reinterpret_cast(&val); + + for(i = 0; i < indent; ++i) std::cout.put(' '); + std::cout << std::setw(width); + std::cout.setf(istream::left, istream::adjustfield); + std::cout << what << "="; + for(i = 0; i < sizeof(T); ++i) + { + std::cout << (int)p[i] << " "; + } + std::cout << std::endl; +} + +#define PRINT_ORDER(T) print_byte_order(BOOST_STRINGIZE(byte order for type T), T()) + +template +void print_sign(const char* what, T t) +{ + t = static_cast(-1); // cast suppresses warnings + for(unsigned i = 0; i < indent; ++i) std::cout.put(' '); + std::cout << "Type " << what << " is " << ((t > 0) ? "unsigned" : "signed") << std::endl; +} + +#define PRINT_SIGN(T) print_sign(#T, T()) + + +void print_compiler_macros() +{ + std::cout << BOOST_COMPILER << "\n"; + // Borland options: + PRINT_MACRO(__BORLANDC__); + PRINT_MACRO(__CDECL__); + PRINT_MACRO(_CHAR_UNSIGNED); + PRINT_MACRO(__CODEGUARD__); + PRINT_MACRO(__CONSOLE__); + PRINT_MACRO(_CPPUNWIND); + PRINT_MACRO(__cplusplus); + PRINT_MACRO(__FLAT__); + PRINT_MACRO(__FUNC__); + PRINT_MACRO(_M_IX86); + PRINT_MACRO(__MSDOS__); + PRINT_MACRO(__MT__ ); + PRINT_MACRO(__PASCAL__); + PRINT_MACRO(__STDC__); + PRINT_MACRO(__TLS__); + PRINT_MACRO(_WCHAR_T); + PRINT_MACRO(_Windows); + PRINT_MACRO(__WIN32__); + PRINT_MACRO(_WIN32); + PRINT_MACRO(_WIN64); + PRINT_MACRO(_WIN32_WCE); + PRINT_MACRO(WIN32); + PRINT_MACRO(_RTLDLL); + PRINT_MACRO(__DEBUG); + +// Internal MSVC 7 error workaround (Peter Dimov) + +#ifndef _NATIVE_WCHAR_T_DEFINED + PRINT_MACRO(_WCHAR_T_DEFINED); +#endif + // MSVC macros: + PRINT_MACRO(_ALIGNED_NEW_SUPPORTED); + PRINT_MACRO(__ATOM__); + PRINT_MACRO(__AVX__); + PRINT_MACRO(__AVX2__); + PRINT_MACRO(_CHAR_UNSIGNED); + PRINT_MACRO(_CLR_VER); + PRINT_MACRO(_CONTROL_FLOW_GUARD); + PRINT_MACRO(__cplusplus_cli); + PRINT_MACRO(__cplusplus_winrt); + PRINT_MACRO(_CPPRTTI); + PRINT_MACRO(_CPPUNWIND); + PRINT_MACRO(_DLL); + PRINT_MACRO(_INLINE_VARIABLES_SUPPORTED); + PRINT_MACRO(_ISO_VOLATILE); + PRINT_MACRO(_M_AMD64); + PRINT_MACRO(_M_ARM); + PRINT_MACRO(_M_ARM_ARMV7VE); + PRINT_MACRO(_M_ARM_FP); + PRINT_MACRO(_M_ARM64); + PRINT_MACRO(_M_CEE); + PRINT_MACRO(_M_CEE_PURE); + PRINT_MACRO(_M_CEE_SAFE); + PRINT_MACRO(_M_FP_EXCEPT); + PRINT_MACRO(_M_FP_FAST); + PRINT_MACRO(_M_FP_PRECISE); + PRINT_MACRO(_M_FP_STRICT); + PRINT_MACRO(_M_IX86); + PRINT_MACRO(_M_IX86_FP); + PRINT_MACRO(_M_X64); + PRINT_MACRO(_M_ALPHA); + PRINT_MACRO(_M_MPPC); + PRINT_MACRO(_M_MRX000); + PRINT_MACRO(_M_PPC); + PRINT_MACRO(_MANAGED); + PRINT_MACRO(_MSC_BUILD); + PRINT_MACRO(_MFC_VER); + PRINT_MACRO(_MSC_EXTENSIONS); + PRINT_MACRO(_MSC_VER); + PRINT_MACRO(_MSC_FULL_VER); + PRINT_MACRO(_MSVC_LANG); + PRINT_MACRO(_MSVC_WARNING_LEVEL); + PRINT_MACRO(__MSVC_RUNTIME_CHECKS); + PRINT_MACRO(_MT); + PRINT_MACRO(_NATIVE_WCHAR_T_DEFINED); + PRINT_MACRO(_NOEXCEPT_TYPES_SUPPORTED); + PRINT_MACRO(_OPENMP); + PRINT_MACRO(_PREFAST_); + // GNUC options: + PRINT_MACRO(__GNUC__); + PRINT_MACRO(__GNUC_MINOR__); + PRINT_MACRO(__GNUC_PATCHLEVEL__); + PRINT_MACRO(__STDC_VERSION__); + PRINT_MACRO(__GNUG__); + PRINT_MACRO(__STRICT_ANSI__); + PRINT_MACRO(__GXX_EXPERIMENTAL_CXX0X__); + PRINT_MACRO(__VERSION__); + PRINT_MACRO(__OPTIMIZE__); + PRINT_MACRO(__CHAR_UNSIGNED__); + PRINT_MACRO(__REGISTER_PREFIX__); + PRINT_MACRO(__USER_LABEL_PREFIX__); + PRINT_MACRO(__GNUPRO__); + PRINT_MACRO(__EXCEPTIONS); + PRINT_MACRO(__FreeBSD__); + PRINT_MACRO(__FreeBSD_cc_version); + PRINT_MACRO(__ELF__); + PRINT_MACRO(__GNUPRO__); + PRINT_MACRO(unix); + PRINT_MACRO(bsd); + PRINT_MACRO(vax); + PRINT_MACRO(mc68000); + PRINT_MACRO(m68k); + PRINT_MACRO(M68020); + PRINT_MACRO(_AM29K); + PRINT_MACRO(ns32000); + PRINT_MACRO(sun); + PRINT_MACRO(pyr); + PRINT_MACRO(sequent); + PRINT_MACRO(__i386__); + PRINT_MACRO(__sparc); + PRINT_MACRO(__sparc__); + PRINT_MACRO(__powerpc__); + PRINT_MACRO(__hppa); + PRINT_MACRO(__CYGWIN__); + PRINT_MACRO(__MINGW32__); + PRINT_MACRO(__GXX_RTTI); + PRINT_MACRO(__alpha__); + PRINT_MACRO(__amd64__); + PRINT_MACRO(__arm__); + PRINT_MACRO(__aarch64__); + PRINT_MACRO(__bfin); + PRINT_MACRO(__convex__); + PRINT_MACRO(__epiphany__); + PRINT_MACRO(__hppa__); + PRINT_MACRO(__ia64__); + PRINT_MACRO(__IA64); + PRINT_MACRO(__IA64__); + PRINT_MACRO(__m68k__); + PRINT_MACRO(__mips__); + PRINT_MACRO(__powerpc); + PRINT_MACRO(__powerpc__); + PRINT_MACRO(__powerpc64__); + PRINT_MACRO(__POWERPC__); + PRINT_MACRO(__ppc__); + PRINT_MACRO(__ppc64__); + PRINT_MACRO(__PPC__); + PRINT_MACRO(__PPC64__); + PRINT_MACRO(_ARCH_PPC); + PRINT_MACRO(_ARCH_PPC64); + PRINT_MACRO(__sh__); + PRINT_MACRO(__370__); + PRINT_MACRO(__THW_370__); + // HP aCC: + PRINT_MACRO(__HP_aCC); + PRINT_MACRO(_HPACC_); + PRINT_MACRO(__LP64__); + PRINT_MACRO(__RISC2_0__); + PRINT_MACRO(__STDCPP__); + PRINT_MACRO(__hppa); + PRINT_MACRO(__hpux); + PRINT_MACRO(__hp9000s800); + PRINT_MACRO(__hp9000s700); + PRINT_MACRO(_PA_RISC1_1); + PRINT_MACRO(__HPUX_SOURCE); + PRINT_MACRO(_INCLUDE__STDC_A1_SOURCE); + // SGI IRIX: + PRINT_MACRO(__sgi); + PRINT_MACRO(_COMPILER_VERSION); + // Sunpro: + PRINT_MACRO(__SUNPRO_CC); + PRINT_MACRO(__SUNPRO_CC_COMPAT); + PRINT_MACRO(__BUILTIN_VA_ARG_INCR); + PRINT_MACRO(__sun); + PRINT_MACRO(__SVR4); + PRINT_MACRO(__unix); + PRINT_MACRO(__sparcv9); + PRINT_MACRO(__i386); + PRINT_MACRO(i386); + // Metrowerks + PRINT_MACRO(__MWERKS__); + PRINT_MACRO(__MSL__); + PRINT_MACRO(__MSL_CPP__); + PRINT_MACRO(__A5__); + PRINT_MACRO(__embedded_cplusplus); + PRINT_MACRO(__fourbyteints__); + PRINT_MACRO(__IEEEdoubles__); + PRINT_MACRO(__MC68K__); + PRINT_MACRO(__MC68020__); + PRINT_MACRO(__MC68881__); + PRINT_MACRO(__MIPS__); + PRINT_MACRO(__MIPS_ISA2__); + PRINT_MACRO(__MIPS_ISA3__); + PRINT_MACRO(__MIPS_ISA4__); + PRINT_MACRO(__MWBROWSER__); + PRINT_MACRO(__profile__); + PRINT_MACRO(__powerc); + PRINT_MACRO(_powerc); + PRINT_MACRO(__POWERPC__); + PRINT_MACRO(macintosh); + PRINT_MACRO(__MACH__); + PRINT_MACRO(__APPLE__); + PRINT_MACRO(__APPLE_CC__); + // MPW (MrCpp and SCpp) + PRINT_MACRO(__MRC__); + PRINT_MACRO(__SC__); + PRINT_MACRO(__FPCE__); + PRINT_MACRO(__FPCE_IEEE__); + PRINT_MACRO(MPW_CPLUS); + PRINT_MACRO(MPW_C); + PRINT_MACRO(__MC601); + PRINT_MACRO(__POWERPC); + PRINT_MACRO(__useAppleExts__); + PRINT_MACRO(powerc); + PRINT_MACRO(MC68000); + PRINT_MACRO(THINK_PLUS); + PRINT_MACRO(mc68881); + PRINT_MACRO(__FAR_CODE__); + PRINT_MACRO(__FAR_DATA__); + PRINT_MACRO(__CFM68K__); + // EDG + PRINT_MACRO(__EDG__); + PRINT_MACRO(__EDG_VERSION__); + PRINT_MACRO(c_plusplus); // indication for strict mode + PRINT_MACRO(_BOOL); + PRINT_MACRO(_EXPLICIT); + PRINT_MACRO(__SIGNED_CHARS__); + PRINT_MACRO(_TYPENAME); + PRINT_MACRO(_WCHAR_T); + PRINT_MACRO(__ARRAY_OPERATORS); + PRINT_MACRO(__EDG_ABI_COMPATIBILITY_VERSION); + PRINT_MACRO(__EDG_IMPLICIT_USING_STD); + PRINT_MACRO(__EDG_RUNTIME_USES_NAMESPACES); + PRINT_MACRO(__BOOL_DEFINED); + PRINT_MACRO(__RTTI); + PRINT_MACRO(__PLACEMENT_DELETE); + PRINT_MACRO(__NO_LONG_LONG); + + // Intel options: + PRINT_MACRO(__INTEL__); + PRINT_MACRO(__ICC); + PRINT_MACRO(__ICL); + PRINT_MACRO(__ECC); + PRINT_MACRO(__INTEL_COMPILER); + PRINT_MACRO(__INITIAL_POINTER_SIZE); + PRINT_MACRO(_INTEGRAL_MAX_BITS); + PRINT_MACRO(__INTEL_COMPILER_BUILD_DATE); + PRINT_MACRO(__INTEL_MS_COMPAT_LEVEL); + PRINT_MACRO(__LONG_DOUBLE_SIZE__); + PRINT_MACRO(_M_X64); + PRINT_MACRO(_OPENMP); + PRINT_MACRO(_OPENMPT); + PRINT_MACRO(_PGO_INSTRUMENT); + PRINT_MACRO(__QMSPP_); + PRINT_MACRO(__INTEL_RTTI__); + PRINT_MACRO(__INTEL_CXX11_MODE__); + + // Cray options: + PRINT_MACRO(_CRAYC); + PRINT_MACRO(_RELEASE); + PRINT_MACRO(cray); + PRINT_MACRO(CRAY); + PRINT_MACRO(CRAY1); + PRINT_MACRO(_CRAY1); + PRINT_MACRO(_CRAYMPP); + PRINT_MACRO(_CRAYT3E); + PRINT_MACRO(_CRAYIEEE); + PRINT_MACRO(_ADDR32); + PRINT_MACRO(_ADDR64); + PRINT_MACRO(_LD64); + PRINT_MACRO(_FASTMD); + PRINT_MACRO(_MAXVL); + + // clang options: + PRINT_MACRO(__clang__); + PRINT_MACRO(__clang_major__); + PRINT_MACRO(__clang_minor__); + PRINT_MACRO(__clang_version__); + PRINT_MACRO(__clang_patchlevel__); + PRINT_MACRO(__apple_build_version__); + + // misc compilers not covered so far: + PRINT_MACRO(__USLC__); + PRINT_MACRO(__DECCXX); + PRINT_MACRO(__IBMCPP__); + PRINT_MACRO(_REENTRANT); + PRINT_MACRO(_PTHREADS); + PRINT_MACRO(__STDC_HOSTED__); + PRINT_MACRO(__COMO__); + PRINT_MACRO(__COMO_VERSION__); + PRINT_MACRO(__DM__); + PRINT_MACRO(__osf__); + PRINT_MACRO(__OSF__); + PRINT_MACRO(__QNXNTO__); + PRINT_MACRO(__QNX__); + PRINT_MACRO(_NTO_VERSION); + PRINT_MACRO(__OPEN64__); + PRINT_MACRO(__open64); + PRINT_MACRO(__NVCC__); + PRINT_MACRO(__CUDACC__); + PRINT_MACRO(__CUDACC_RDC__); + PRINT_MACRO(__CUDACC_VER_MAJOR__); + PRINT_MACRO(__CUDACC_VER_MINOR__); + PRINT_MACRO(__CUDACC_VER_BUILD__); + PRINT_MACRO(__CUDACC_VER__); + + // Android: + PRINT_MACRO(ANDROID); + PRINT_MACRO(__ANDROID__); +} + +void print_stdlib_macros() +{ + std::cout << BOOST_STDLIB << std::endl; + #ifdef _RWSTD_VER + // Rogue Wave 2.x config options: + PRINT_MACRO(__NO_EDG_EXCEPTION_CLASSES); + PRINT_MACRO(_RWSTD_ALLOCATOR); + PRINT_MACRO(_RWSTD_BAD_ALLOC_DEFINED); + PRINT_MACRO(_RWSTD_BAD_EXCEPTION_DEFINED); + PRINT_MACRO(_RWSTD_BOUNDS_CHECKING); + PRINT_MACRO(_RWSTD_COMPILE_INSTANTIATE); + PRINT_MACRO(_RWSTD_DEFAULT_PRECISION); + PRINT_MACRO(_RWSTD_EXCEPTION_DEFINED); + PRINT_MACRO(_RWSTD_EXCEPTION_HANDLER_IN_STD); + PRINT_MACRO(_RWSTD_EXCEPTION_PREDEFINED); + PRINT_MACRO(_RWSTD_FLT_ROUNDS_IS_CONSTANT); + PRINT_MACRO(_RWSTD_LOCALIZED_ERRORS); + PRINT_MACRO(_RWSTD_MESSAGE); + PRINT_MACRO(_RWSTD_MUTEXATTR_DEFAULT); + PRINT_MACRO(_RWSTD_NO_ANSI_SPRINTF); + PRINT_MACRO(_RWSTD_NO_ARG_MATCH); + PRINT_MACRO(_RWSTD_NO_BAD_CAST); + PRINT_MACRO(_RWSTD_NO_BASE_CLASS_MATCH); + PRINT_MACRO(_RWSTD_NO_BOOL); + PRINT_MACRO(_RWSTD_NO_BUILTIN_CTOR); + PRINT_MACRO(_RWSTD_NO_CATOPEN_CATGETS); + PRINT_MACRO(_RWSTD_NO_CLASS_PARTIAL_SPEC); + PRINT_MACRO(_RWSTD_NO_COMPLEX_DEFAULT_TEMPLATES); + PRINT_MACRO(_RWSTD_NO_COMPLICATED_EXCEPTIONS); + PRINT_MACRO(_RWSTD_NO_COMPLICATED_TYPEDEF); + PRINT_MACRO(_RWSTD_NO_CONST_INST); + PRINT_MACRO(_RWSTD_NO_CTOR_RETURN); + PRINT_MACRO(_RWSTD_NO_DEFAULT_FOR_TPARAM); + PRINT_MACRO(_RWSTD_NO_DEFAULT_TEMPLATE_ARGS); + PRINT_MACRO(_RWSTD_NO_DESTROY_BUILTIN); + PRINT_MACRO(_RWSTD_NO_DESTROY_NONBUILTIN); + PRINT_MACRO(_RWSTD_NO_EMBEDDED_TYPEDEF); + PRINT_MACRO(_RWSTD_NO_EX_SPEC); + PRINT_MACRO(_RWSTD_NO_EXCEPTIONS); + PRINT_MACRO(_RWSTD_NO_EXPLICIT); + PRINT_MACRO(_RWSTD_NO_EXPLICIT_ARG); + PRINT_MACRO(_RWSTD_NO_EXPLICIT_FUNC_INSTANTIATION); + PRINT_MACRO(_RWSTD_NO_EXPLICIT_INSTANTIATION); + PRINT_MACRO(_RWSTD_NO_EXTENSION); + PRINT_MACRO(_RWSTD_NO_FORWARD_SPECIALIZATIONS); + PRINT_MACRO(_RWSTD_NO_FPOS_T); + PRINT_MACRO(_RWSTD_NO_FRIEND_TEMPLATES); + PRINT_MACRO(_RWSTD_NO_FUNC_PARTIAL_SPEC); + PRINT_MACRO(_RWSTD_NO_GETTIMEOFDAY); + PRINT_MACRO(_RWSTD_NO_GLOBAL_TZ); + PRINT_MACRO(_RWSTD_NO_INHERITED_TYPEDEFS); + PRINT_MACRO(_RWSTD_NO_INIT_CONST_TEMPLATE_REF_ARG); + PRINT_MACRO(_RWSTD_NO_INT_TYPEDEF); + PRINT_MACRO(_RWSTD_NO_LDIV); + PRINT_MACRO(_RWSTD_NO_LEADING_UNDERSCORE); + PRINT_MACRO(_RWSTD_NO_LOCALE); + PRINT_MACRO(_RWSTD_NO_LONG_NAME); + PRINT_MACRO(_RWSTD_NO_LONGDOUBLE); + PRINT_MACRO(_RWSTD_NO_MBSTATE_T); + PRINT_MACRO(_RWSTD_NO_MEM_CLASS_TEMPLATES); + PRINT_MACRO(_RWSTD_NO_MEMBER_TEMPLATES); + PRINT_MACRO(_RWSTD_NO_MEMBER_TYPE_TPARAM); + PRINT_MACRO(_RWSTD_NO_MEMBER_WO_DEF_CTOR); + PRINT_MACRO(_RWSTD_NO_MEMMOVE); + PRINT_MACRO(_RWSTD_NO_MULTI_DIM_ARRAY); + PRINT_MACRO(_RWSTD_NO_MUTABLE); + PRINT_MACRO(_RWSTD_NO_NAME_INJECTION); + PRINT_MACRO(_RWSTD_NO_NAMESPACE); + PRINT_MACRO(_RWSTD_NO_NESTING_TEMPLATES); + PRINT_MACRO(_RWSTD_NO_NEW_BRACKETS); + PRINT_MACRO(_RWSTD_NO_NEW_DECL); + PRINT_MACRO(_RWSTD_NO_NEW_HEADER); + PRINT_MACRO(_RWSTD_NO_NEW_TEMPLATE_SYNTAX); + PRINT_MACRO(_RWSTD_NO_NONCLASS_ARROW_RETURN); + PRINT_MACRO(_RWSTD_NO_NONTYPE_ARGS); + PRINT_MACRO(_RWSTD_NO_ONLY_NEEDED_INSTANTIATION); + PRINT_MACRO(_RWSTD_NO_OVERLOAD_C_POW); + PRINT_MACRO(_RWSTD_NO_OVERLOAD_OF_TEMPLATE_FUNCTION); + PRINT_MACRO(_RWSTD_NO_OVERLOAD_WCHAR); + PRINT_MACRO(_RWSTD_NO_PART_SPEC_OVERLOAD); + PRINT_MACRO(_RWSTD_NO_RET_TEMPLATE); + PRINT_MACRO(_RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES); + PRINT_MACRO(_RWSTD_NO_STATIC_CAST); + PRINT_MACRO(_RWSTD_NO_STATIC_DEF); + PRINT_MACRO(_RWSTD_NO_STATIC_DEF2); + PRINT_MACRO(_RWSTD_NO_STATIC_DEF3); + PRINT_MACRO(_RWSTD_NO_STATIC_MEM_DEF); + PRINT_MACRO(_RWSTD_NO_STI_SIMPLE); + PRINT_MACRO(_RWSTD_NO_STI_TEMPLATE); + PRINT_MACRO(_RWSTD_NO_STREAM_LONG_DOUBLE); + PRINT_MACRO(_RWSTD_NO_STRFTIME_CAPC); + PRINT_MACRO(_RWSTD_NO_STRICT_TEMPLATE_INSTANTIATE); + PRINT_MACRO(_RWSTD_NO_SWPRINTF); + PRINT_MACRO(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE); + PRINT_MACRO(_RWSTD_NO_TEMPLATE_TEMPLATE); + PRINT_MACRO(_RWSTD_NO_THREADS); + PRINT_MACRO(_RWSTD_NO_THROW_SPEC_ON_NEW); + PRINT_MACRO(_RWSTD_NO_THROW_WITH_SHARED); + PRINT_MACRO(_RWSTD_NO_TYPEDEF_INST); + PRINT_MACRO(_RWSTD_NO_TYPEDEF_OVERLOAD); + PRINT_MACRO(_RWSTD_NO_TYPENAME); + PRINT_MACRO(_RWSTD_NO_UNDEFINED_FRIEND); + PRINT_MACRO(_RWSTD_NO_UNINITIALIZED_STATIC_DEF); + PRINT_MACRO(_RWSTD_NO_WCHAR_H); + PRINT_MACRO(_RWSTD_NO_WCTYPE_H); + PRINT_MACRO(_RWSTD_NO_WIDE_CHAR); + PRINT_MACRO(_RWSTD_NO_WINT_TYPE); + PRINT_MACRO(_RWSTD_NO_WSTR); + PRINT_MACRO(_RWSTD_NOT_ALL_WSTR_CFUNCTIONS); + PRINT_MACRO(_RWSTD_POSIX_D10_THREADS); + PRINT_MACRO(_RWSTD_POSIX_THREADS); + PRINT_MACRO(_RWSTD_REQUIRES_IEEEFP); + PRINT_MACRO(_RWSTD_SOLARIS_THREADS); + PRINT_MACRO(_RWSTD_STRUCT_TM_TZ); + PRINT_MACRO(_RWSTD_WIDE_STRING_NULL_PROBLEM); + #elif defined(__STD_RWCOMPILER_H__) + // Rogue Wave 1.x std lib: + PRINT_MACRO(__NO_EDG_EXCEPTION_CLASSES); + PRINT_MACRO(RWSTD_ALLOCATOR); + PRINT_MACRO(RWSTD_BAD_ALLOC_DEFINED); + PRINT_MACRO(RWSTD_BAD_EXCEPTION_DEFINED); + PRINT_MACRO(RWSTD_BOUNDS_CHECKING); + PRINT_MACRO(RWSTD_COMPILE_INSTANTIATE); + PRINT_MACRO(RWSTD_DEFAULT_PRECISION); + PRINT_MACRO(RWSTD_EXCEPTION_DEFINED); + PRINT_MACRO(RWSTD_EXCEPTION_HANDLER_IN_STD); + PRINT_MACRO(RWSTD_EXCEPTION_PREDEFINED); + PRINT_MACRO(RWSTD_FLT_ROUNDS_IS_CONSTANT); + PRINT_MACRO(RWSTD_LOCALIZED_ERRORS); + PRINT_MACRO(RWSTD_MESSAGE); + PRINT_MACRO(RWSTD_MUTEXATTR_DEFAULT); + PRINT_MACRO(RWSTD_NO_ANSI_SPRINTF); + PRINT_MACRO(RWSTD_NO_ARG_MATCH); + PRINT_MACRO(RWSTD_NO_BAD_CAST); + PRINT_MACRO(RWSTD_NO_BASE_CLASS_MATCH); + PRINT_MACRO(RWSTD_NO_BOOL); + PRINT_MACRO(RWSTD_NO_BUILTIN_CTOR); + PRINT_MACRO(RWSTD_NO_CATOPEN_CATGETS); + PRINT_MACRO(RWSTD_NO_CLASS_PARTIAL_SPEC); + PRINT_MACRO(RWSTD_NO_COMPLEX_DEFAULT_TEMPLATES); + PRINT_MACRO(RWSTD_NO_COMPLICATED_EXCEPTIONS); + PRINT_MACRO(RWSTD_NO_COMPLICATED_TYPEDEF); + PRINT_MACRO(RWSTD_NO_CONST_INST); + PRINT_MACRO(RWSTD_NO_CTOR_RETURN); + PRINT_MACRO(RWSTD_NO_DEFAULT_FOR_TPARAM); + PRINT_MACRO(RWSTD_NO_DEFAULT_TEMPLATE_ARGS); + PRINT_MACRO(RWSTD_NO_DESTROY_BUILTIN); + PRINT_MACRO(RWSTD_NO_DESTROY_NONBUILTIN); + PRINT_MACRO(RWSTD_NO_EMBEDDED_TYPEDEF); + PRINT_MACRO(RWSTD_NO_EX_SPEC); + PRINT_MACRO(RWSTD_NO_EXCEPTIONS); + PRINT_MACRO(RWSTD_NO_EXPLICIT); + PRINT_MACRO(RWSTD_NO_EXPLICIT_ARG); + PRINT_MACRO(RWSTD_NO_EXPLICIT_FUNC_INSTANTIATION); + PRINT_MACRO(RWSTD_NO_EXPLICIT_INSTANTIATION); + PRINT_MACRO(RWSTD_NO_EXTENSION); + PRINT_MACRO(RWSTD_NO_FORWARD_SPECIALIZATIONS); + PRINT_MACRO(RWSTD_NO_FPOS_T); + PRINT_MACRO(RWSTD_NO_FRIEND_TEMPLATES); + PRINT_MACRO(RWSTD_NO_FUNC_PARTIAL_SPEC); + PRINT_MACRO(RWSTD_NO_GETTIMEOFDAY); + PRINT_MACRO(RWSTD_NO_GLOBAL_TZ); + PRINT_MACRO(RWSTD_NO_INHERITED_TYPEDEFS); + PRINT_MACRO(RWSTD_NO_INIT_CONST_TEMPLATE_REF_ARG); + PRINT_MACRO(RWSTD_NO_INT_TYPEDEF); + PRINT_MACRO(RWSTD_NO_LDIV); + PRINT_MACRO(RWSTD_NO_LEADING_UNDERSCORE); + PRINT_MACRO(RWSTD_NO_LOCALE); + PRINT_MACRO(RWSTD_NO_LONG_NAME); + PRINT_MACRO(RWSTD_NO_LONGDOUBLE); + PRINT_MACRO(RWSTD_NO_MBSTATE_T); + PRINT_MACRO(RWSTD_NO_MEM_CLASS_TEMPLATES); + PRINT_MACRO(RWSTD_NO_MEMBER_TEMPLATES); + PRINT_MACRO(RWSTD_NO_MEMBER_TYPE_TPARAM); + PRINT_MACRO(RWSTD_NO_MEMBER_WO_DEF_CTOR); + PRINT_MACRO(RWSTD_NO_MEMMOVE); + PRINT_MACRO(RWSTD_NO_MULTI_DIM_ARRAY); + PRINT_MACRO(RWSTD_NO_MUTABLE); + PRINT_MACRO(RWSTD_NO_NAME_INJECTION); + PRINT_MACRO(RWSTD_NO_NAMESPACE); + PRINT_MACRO(RWSTD_NO_NESTING_TEMPLATES); + PRINT_MACRO(RWSTD_NO_NEW_BRACKETS); + PRINT_MACRO(RWSTD_NO_NEW_DECL); + PRINT_MACRO(RWSTD_NO_NEW_HEADER); + PRINT_MACRO(RWSTD_NO_NEW_TEMPLATE_SYNTAX); + PRINT_MACRO(RWSTD_NO_NONCLASS_ARROW_RETURN); + PRINT_MACRO(RWSTD_NO_NONTYPE_ARGS); + PRINT_MACRO(RWSTD_NO_ONLY_NEEDED_INSTANTIATION); + PRINT_MACRO(RWSTD_NO_OVERLOAD_C_POW); + PRINT_MACRO(RWSTD_NO_OVERLOAD_OF_TEMPLATE_FUNCTION); + PRINT_MACRO(RWSTD_NO_OVERLOAD_WCHAR); + PRINT_MACRO(RWSTD_NO_PART_SPEC_OVERLOAD); + PRINT_MACRO(RWSTD_NO_RET_TEMPLATE); + PRINT_MACRO(RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES); + PRINT_MACRO(RWSTD_NO_STATIC_CAST); + PRINT_MACRO(RWSTD_NO_STATIC_DEF); + PRINT_MACRO(RWSTD_NO_STATIC_DEF2); + PRINT_MACRO(RWSTD_NO_STATIC_DEF3); + PRINT_MACRO(RWSTD_NO_STATIC_MEM_DEF); + PRINT_MACRO(RWSTD_NO_STI_SIMPLE); + PRINT_MACRO(RWSTD_NO_STI_TEMPLATE); + PRINT_MACRO(RWSTD_NO_STREAM_LONG_DOUBLE); + PRINT_MACRO(RWSTD_NO_STRFTIME_CAPC); + PRINT_MACRO(RWSTD_NO_STRICT_TEMPLATE_INSTANTIATE); + PRINT_MACRO(RWSTD_NO_SWPRINTF); + PRINT_MACRO(RWSTD_NO_TEMPLATE_ON_RETURN_TYPE); + PRINT_MACRO(RWSTD_NO_TEMPLATE_TEMPLATE); + PRINT_MACRO(RWSTD_NO_THREADS); + PRINT_MACRO(RWSTD_NO_THROW_SPEC_ON_NEW); + PRINT_MACRO(RWSTD_NO_THROW_WITH_SHARED); + PRINT_MACRO(RWSTD_NO_TYPEDEF_INST); + PRINT_MACRO(RWSTD_NO_TYPEDEF_OVERLOAD); + PRINT_MACRO(RWSTD_NO_TYPENAME); + PRINT_MACRO(RWSTD_NO_UNDEFINED_FRIEND); + PRINT_MACRO(RWSTD_NO_UNINITIALIZED_STATIC_DEF); + PRINT_MACRO(RWSTD_NO_WCHAR_H); + PRINT_MACRO(RWSTD_NO_WCTYPE_H); + PRINT_MACRO(RWSTD_NO_WIDE_CHAR); + PRINT_MACRO(RWSTD_NO_WINT_TYPE); + PRINT_MACRO(RWSTD_NO_WSTR); + PRINT_MACRO(RWSTD_NOT_ALL_WSTR_CFUNCTIONS); + PRINT_MACRO(RWSTD_POSIX_D10_THREADS); + PRINT_MACRO(RWSTD_POSIX_THREADS); + PRINT_MACRO(RWSTD_REQUIRES_IEEEFP); + PRINT_MACRO(RWSTD_SOLARIS_THREADS); + PRINT_MACRO(RWSTD_STRUCT_TM_TZ); + PRINT_MACRO(RWSTD_WIDE_STRING_NULL_PROBLEM); + #endif + // Dinkumware options: + PRINT_MACRO(_CPPLIB_VER); + PRINT_MACRO(_MSVC_STL_VERSION); // VS2017 15.5+ + PRINT_MACRO(_MSVC_STL_UPDATE); // VS2017 15.5+ + PRINT_MACRO(_GLOBAL_USING); + PRINT_MACRO(_HAS_EXCEPTIONS); + PRINT_MACRO(_HAS_MEMBER_TEMPLATES_REBIND); + PRINT_MACRO(_HAS_TEMPLATE_PARTIAL_ORDERING); + // https://blogs.msdn.microsoft.com/vcblog/2016/08/12/stl-fixes-in-vs-2015-update-3/ + PRINT_MACRO(_HAS_CXX17); + PRINT_MACRO(_HAS_AUTO_PTR_ETC); + PRINT_MACRO(_HAS_OLD_IOSTREAMS_MEMBERS); + PRINT_MACRO(_HAS_FUNCTION_ASSIGN); + PRINT_MACRO(_HAS_TR1_NAMESPACE); + PRINT_MACRO(_HAS_IDENTITY_STRUCT); + // VS2017 15.5+ + PRINT_MACRO(_HAS_STATIC_RTTI); + PRINT_MACRO(_HAS_UNEXPECTED); + PRINT_MACRO(_HAS_STD_BYTE); + PRINT_MACRO(_HAS_FUNCTION_ALLOCATOR_SUPPORT); + PRINT_MACRO(_HAS_TR2_SYS_NAMESPACE); + PRINT_MACRO(_ENFORCE_MATCHING_ALLOCATORS); + PRINT_MACRO(_HAS_HAS_UNIQUE_OBJECT_REPRESENTATIONS); + PRINT_MACRO(_HAS_INLINE_VARIABLES); + PRINT_MACRO(_HAS_ALIGNED_NEW); + PRINT_MACRO(_HAS_NOEXCEPT_FUNCTION_TYPES); + PRINT_MACRO(_ITERATOR_DEBUG_LEVEL); + PRINT_MACRO(_HAS_ITERATOR_DEBUGGING); + PRINT_MACRO(_ITERATOR_DEBUG_ARRAY_OVERLOADS); + // Libc++: + PRINT_MACRO(_LIBCPP_VERSION); + // STLPort and generic SGI STL options: + PRINT_MACRO(__SGI_STL_NO_ARROW_OPERATOR); + PRINT_MACRO(__SGI_STL_OWN_IOSTREAMS); + PRINT_MACRO(__SGI_STL_PORT); + PRINT_MACRO(__STL_AUTOMATIC_TYPE_TRAITS); + PRINT_MACRO(__STL_BASE_MATCH_BUG); + PRINT_MACRO(__STL_BASE_TYPEDEF_BUG); + PRINT_MACRO(__STL_BASE_TYPEDEF_OUTSIDE_BUG); + PRINT_MACRO(__STL_BROKEN_USING_DIRECTIVE); + PRINT_MACRO(__STL_CONST_CONSTRUCTOR_BUG); + PRINT_MACRO(__STL_DEBUG); + PRINT_MACRO(__STL_DEBUG_ALLOC); + PRINT_MACRO(__STL_DEFAULT_CONSTRUCTOR_BUG); + PRINT_MACRO(__STL_DEFAULT_TYPE_PARAM); + PRINT_MACRO(__STL_DONT_REDEFINE_STD); + PRINT_MACRO(__STL_DONT_USE_BOOL_TYPEDEF); + PRINT_MACRO(__STL_HAS_NO_EXCEPTIONS); + PRINT_MACRO(__STL_HAS_NO_NAMESPACES); + PRINT_MACRO(__STL_HAS_NO_NEW_C_HEADERS); + PRINT_MACRO(__STL_HAS_NO_NEW_IOSTREAMS); + PRINT_MACRO(__STL_IMPORT_VENDOR_CSTD); + PRINT_MACRO(__STL_LIMITED_DEFAULT_TEMPLATES); + PRINT_MACRO(__STL_LINK_TIME_INSTANTIATION); + PRINT_MACRO(__STL_LONG_LONG); + PRINT_MACRO(__STL_LOOP_INLINE_PROBLEMS); + PRINT_MACRO(__STL_MEMBER_POINTER_PARAM_BUG); + PRINT_MACRO(__STL_NEED_EXPLICIT); + PRINT_MACRO(__STL_NEED_MUTABLE); + PRINT_MACRO(__STL_NEED_TYPENAME); + PRINT_MACRO(__STL_NESTED_TYPE_PARAM_BUG); + PRINT_MACRO(__STL_NO_BAD_ALLOC); + PRINT_MACRO(__STL_NO_BOOL); + PRINT_MACRO(__STL_NO_CLASS_PARTIAL_SPECIALIZATION); + PRINT_MACRO(__STL_NO_CSTD_FUNCTION_IMPORTS); + PRINT_MACRO(__STL_NO_DEFAULT_NON_TYPE_PARAM); + PRINT_MACRO(__STL_NO_EXCEPTION_HEADER); + PRINT_MACRO(__STL_NO_EXCEPTION_SPEC); + PRINT_MACRO(__STL_NO_EXCEPTIONS); + PRINT_MACRO(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS); + PRINT_MACRO(__STL_NO_FRIEND_TEMPLATES); + PRINT_MACRO(__STL_NO_FUNCTION_TMPL_PARTIAL_ORDER); + PRINT_MACRO(__STL_NO_IOSTREAMS); + PRINT_MACRO(__STL_NO_LONG_DOUBLE); + PRINT_MACRO(__STL_NO_MEMBER_TEMPLATE_CLASSES); + PRINT_MACRO(__STL_NO_MEMBER_TEMPLATE_KEYWORD); + PRINT_MACRO(__STL_NO_MEMBER_TEMPLATES); + PRINT_MACRO(__STL_NO_METHOD_SPECIALIZATION); + PRINT_MACRO(__STL_NO_NAMESPACES); + PRINT_MACRO(__STL_NO_NEW_IOSTREAMS); + PRINT_MACRO(__STL_NO_NEW_NEW_HEADER); + PRINT_MACRO(__STL_NO_NEW_STYLE_CASTS); + PRINT_MACRO(__STL_NO_PARTIAL_SPECIALIZATION_SYNTAX); + PRINT_MACRO(__STL_NO_QUALIFIED_FRIENDS); + PRINT_MACRO(__STL_NO_RELOPS_NAMESPACE); + PRINT_MACRO(__STL_NO_SGI_IOSTREAMS); + PRINT_MACRO(__STL_NO_STATIC_TEMPLATE_DATA); + PRINT_MACRO(__STL_NO_TEMPLATE_CONVERSIONS); + PRINT_MACRO(__STL_NO_WCHAR_T); + PRINT_MACRO(__STL_NON_TYPE_TMPL_PARAM_BUG); + PRINT_MACRO(__STL_NONTEMPL_BASE_MATCH_BUG); + PRINT_MACRO(__STL_PARTIAL_SPEC_NEEDS_TEMPLATE_ARGS); + PRINT_MACRO(__STL_RAND48); + PRINT_MACRO(__STL_STATIC_ARRAY_BUG); + PRINT_MACRO(__STL_STATIC_CONST_INIT_BUG); + PRINT_MACRO(__STL_STATIC_CONST_INIT_BUG); + PRINT_MACRO(__STL_THROW_RETURN_BUG); + PRINT_MACRO(__STL_TRIVIAL_CONSTRUCTOR_BUG); + PRINT_MACRO(__STL_TRIVIAL_DESTRUCTOR_BUG); + PRINT_MACRO(__STL_UNINITIALIZABLE_PRIVATE); + PRINT_MACRO(__STL_USE_ABBREVS); + PRINT_MACRO(__STL_USE_DEFALLOC); + PRINT_MACRO(__STL_USE_MALLOC); + PRINT_MACRO(__STL_USE_NEW_C_HEADERS); + PRINT_MACRO(__STL_USE_NEW_IOSTREAMS); + PRINT_MACRO(__STL_USE_NEWALLOC); + PRINT_MACRO(__STL_USE_OWN_NAMESPACE); + PRINT_MACRO(__STL_USE_SGI_ALLOCATORS); + PRINT_MACRO(__STL_WCHAR_T_IS_USHORT); + PRINT_MACRO(__STL_WEAK_ATTRIBUTE); + PRINT_MACRO(__STL_YVALS_H); + PRINT_MACRO(_NOTHREADS); + PRINT_MACRO(_PTHREADS); +#if defined(__SGI_STL_PORT) && (__SGI_STL_PORT > 0x0400) + PRINT_MACRO(_STLP_AUTOMATIC_TYPE_TRAITS); + PRINT_MACRO(_STLP_BASE_MATCH_BUG); + PRINT_MACRO(_STLP_BASE_TYPEDEF_BUG); + PRINT_MACRO(_STLP_BASE_TYPEDEF_OUTSIDE_BUG); + PRINT_MACRO(_STLP_BROKEN_USING_DIRECTIVE); + PRINT_MACRO(_STLP_CONST_CONSTRUCTOR_BUG); + PRINT_MACRO(_STLP_DEBUG); + PRINT_MACRO(_STLP_DEBUG_ALLOC); + PRINT_MACRO(_STLP_DEFAULT_CONSTRUCTOR_BUG); + PRINT_MACRO(_STLP_DEFAULT_TYPE_PARAM); + PRINT_MACRO(_STLP_DONT_REDEFINE_STD); + PRINT_MACRO(_STLP_DONT_USE_BOOL_TYPEDEF); + PRINT_MACRO(_STLP_HAS_NO_EXCEPTIONS); + PRINT_MACRO(_STLP_HAS_NO_NAMESPACES); + PRINT_MACRO(_STLP_HAS_NO_NEW_C_HEADERS); + PRINT_MACRO(_STLP_HAS_NO_NEW_IOSTREAMS); + PRINT_MACRO(_STLP_IMPORT_VENDOR_CSTD); + PRINT_MACRO(_STLP_LIMITED_DEFAULT_TEMPLATES); + PRINT_MACRO(_STLP_LINK_TIME_INSTANTIATION); + PRINT_MACRO(_STLP_LONG_LONG); + PRINT_MACRO(_STLP_LOOP_INLINE_PROBLEMS); + PRINT_MACRO(_STLP_MEMBER_POINTER_PARAM_BUG); + PRINT_MACRO(_STLP_NEED_EXPLICIT); + PRINT_MACRO(_STLP_NEED_MUTABLE); + PRINT_MACRO(_STLP_NEED_TYPENAME); + PRINT_MACRO(_STLP_NESTED_TYPE_PARAM_BUG); + PRINT_MACRO(_STLP_NO_ARROW_OPERATOR); + PRINT_MACRO(_STLP_NO_BAD_ALLOC); + PRINT_MACRO(_STLP_NO_BOOL); + PRINT_MACRO(_STLP_NO_CLASS_PARTIAL_SPECIALIZATION); + PRINT_MACRO(_STLP_NO_CSTD_FUNCTION_IMPORTS); + PRINT_MACRO(_STLP_NO_DEFAULT_NON_TYPE_PARAM); + PRINT_MACRO(_STLP_NO_EXCEPTION_HEADER); + PRINT_MACRO(_STLP_NO_EXCEPTION_SPEC); + PRINT_MACRO(_STLP_NO_EXCEPTIONS); + PRINT_MACRO(_STLP_NO_EXPLICIT_FUNCTION_TMPL_ARGS); + PRINT_MACRO(_STLP_NO_FRIEND_TEMPLATES); + PRINT_MACRO(_STLP_NO_FUNCTION_TMPL_PARTIAL_ORDER); + PRINT_MACRO(_STLP_NO_IOSTREAMS); + PRINT_MACRO(_STLP_NO_LONG_DOUBLE); + PRINT_MACRO(_STLP_NO_MEMBER_TEMPLATE_CLASSES); + PRINT_MACRO(_STLP_NO_MEMBER_TEMPLATE_KEYWORD); + PRINT_MACRO(_STLP_NO_MEMBER_TEMPLATES); + PRINT_MACRO(_STLP_NO_METHOD_SPECIALIZATION); + PRINT_MACRO(_STLP_NO_NAMESPACES); + PRINT_MACRO(_STLP_NO_NEW_IOSTREAMS); + PRINT_MACRO(_STLP_NO_NEW_NEW_HEADER); + PRINT_MACRO(_STLP_NO_NEW_STYLE_CASTS); + PRINT_MACRO(_STLP_NO_PARTIAL_SPECIALIZATION_SYNTAX); + PRINT_MACRO(_STLP_NO_QUALIFIED_FRIENDS); + PRINT_MACRO(_STLP_NO_RELOPS_NAMESPACE); + PRINT_MACRO(_STLP_NO_SGI_IOSTREAMS); + PRINT_MACRO(_STLP_NO_STATIC_TEMPLATE_DATA); + PRINT_MACRO(_STLP_NO_TEMPLATE_CONVERSIONS); + PRINT_MACRO(_STLP_NO_WCHAR_T); + PRINT_MACRO(_STLP_NON_TYPE_TMPL_PARAM_BUG); + PRINT_MACRO(_STLP_NONTEMPL_BASE_MATCH_BUG); + PRINT_MACRO(_STLP_OWN_IOSTREAMS); + PRINT_MACRO(_STLP_PARTIAL_SPEC_NEEDS_TEMPLATE_ARGS); + PRINT_MACRO(_STLP_RAND48); + PRINT_MACRO(_STLP_STATIC_ARRAY_BUG); + PRINT_MACRO(_STLP_STATIC_CONST_INIT_BUG); + PRINT_MACRO(_STLP_STATIC_CONST_INIT_BUG); + PRINT_MACRO(_STLP_THROW_RETURN_BUG); + PRINT_MACRO(_STLP_TRIVIAL_CONSTRUCTOR_BUG); + PRINT_MACRO(_STLP_TRIVIAL_DESTRUCTOR_BUG); + PRINT_MACRO(_STLP_UNINITIALIZABLE_PRIVATE); + PRINT_MACRO(_STLP_USE_ABBREVS); + PRINT_MACRO(_STLP_USE_DEFALLOC); + PRINT_MACRO(_STLP_USE_MALLOC); + PRINT_MACRO(_STLP_USE_NEW_C_HEADERS); + PRINT_MACRO(_STLP_USE_NEWALLOC); + PRINT_MACRO(_STLP_USE_OWN_NAMESPACE); + PRINT_MACRO(_STLP_USE_SGI_ALLOCATORS); + PRINT_MACRO(_STLP_WCHAR_T_IS_USHORT); + PRINT_MACRO(_STLP_WEAK_ATTRIBUTE); + PRINT_MACRO(_STLP_YVALS_H); +#endif + PRINT_MACRO(__GLIBCPP__); + PRINT_MACRO(_GLIBCPP_USE_WCHAR_T); + PRINT_MACRO(_GLIBCPP_VERSION); + PRINT_MACRO(__GLIBCXX__); + PRINT_MACRO(_GLIBCXX_USE_WCHAR_T); + PRINT_MACRO(_GLIBCXX_VERSION); + PRINT_MACRO(_GLIBCXX_USE_LONG_LONG); + PRINT_MACRO(_GLIBCXX_USE_NLS); + PRINT_MACRO(_GLIBCXX_USE_C99_MATH); + PRINT_MACRO(_GLIBCXX_USE_C99); + PRINT_MACRO(_GLIBCXX_CONCEPT_CHECKS); + PRINT_MACRO(_GLIBCXX_USE_LFS); + PRINT_MACRO(_GLIBCXX_SYMVER); + PRINT_MACRO(_GLIBCXX_MEM_LIMITS); + PRINT_MACRO(_GLIBCXX_HOSTED); + PRINT_MACRO(_GLIBCXX_SJLJ_EXCEPTIONS); + PRINT_MACRO(_GLIBCXX_RELEASE); + PRINT_MACRO(_GLIBCXX_USE_FLOAT128); + + // Modena C++ standard library + PRINT_MACRO(MSIPL_ANSI_HEADER); + PRINT_MACRO(MSIPL_BOOL_BUILTIN); + PRINT_MACRO(MSIPL_DEF_EXPLICIT); + PRINT_MACRO(MSIPL_DEF_TEMPARG); + PRINT_MACRO(MSIPL_EXPINST_ALLOWED); + PRINT_MACRO(MSIPL_EXPLICIT_FUNC_TEMPLATE_ARG); + PRINT_MACRO(MISPL_EXPLICIT_TEMPLATE_ARGUMENT); + PRINT_MACRO(MSIPL_FUNC_TEMPLATE_DEFARG); + PRINT_MACRO(MSIPL_MEMBER_TEMPLATE); + PRINT_MACRO(MSIPL_MULTITHREAD); + PRINT_MACRO(MSIPL_NON_TYPE_TEMPARG); + PRINT_MACRO(MSIPL_PARTIAL_TEMPL); + PRINT_MACRO(MSIPL_STATIC_CONST_INIT); + PRINT_MACRO(MSIPL_TEMPL_NEWSPEC); + PRINT_MACRO(MSIPL_TYPENAME); + PRINT_MACRO(MSIPL_USING_NAMESPACE); + PRINT_MACRO(MSIPL_WCHART); +} + +void print_platform_macros() +{ + std::cout << "Detected Platform: " << BOOST_PLATFORM << std::endl; + // signedness: + PRINT_SIGN(char); + PRINT_SIGN(wchar_t); + // byte ordering: + PRINT_ORDER(short); + PRINT_ORDER(int); + PRINT_ORDER(long); + // sizes: + PRINT_EXPRESSION(sizeof(wchar_t)); + PRINT_EXPRESSION(sizeof(short)); + PRINT_EXPRESSION(sizeof(int)); + PRINT_EXPRESSION(sizeof(long)); + PRINT_EXPRESSION(sizeof(size_t)); + PRINT_EXPRESSION(sizeof(ptrdiff_t)); + PRINT_EXPRESSION(sizeof(void*)); + PRINT_EXPRESSION(sizeof(void(*)(void))); + PRINT_EXPRESSION(sizeof(float)); + PRINT_EXPRESSION(sizeof(double)); + PRINT_EXPRESSION(sizeof(long double)); + // limits: + PRINT_MACRO(CHAR_BIT); + PRINT_MACRO(CHAR_MAX); + PRINT_MACRO(WCHAR_MAX); + PRINT_MACRO(SHRT_MAX); + PRINT_MACRO(INT_MAX); + PRINT_MACRO(LONG_MAX); + PRINT_MACRO(LLONG_MAX); + PRINT_MACRO(LONG_LONG_MAX); + PRINT_MACRO(LONGLONG_MAX); + PRINT_MACRO(ULLONG_MAX); // uses these, so we need to know them + PRINT_MACRO(ULONG_LONG_MAX); + PRINT_MACRO(ULONGLONG_MAX); + // general C99: + PRINT_MACRO(__STDC_IEC_559__); + PRINT_MACRO(__STDC_IEC_559_COMPLEX__); + PRINT_MACRO(__STDC_ISO_10646__); + // GNU: + PRINT_MACRO(__GLIBC__); + PRINT_MACRO(__GLIBC_MINOR__); + PRINT_MACRO(__GNU_LIBRARY__); + PRINT_MACRO(_BSD_SOURCE); + PRINT_MACRO(_GNU_SOURCE); + PRINT_MACRO(_ISOC99_SOURCE); + PRINT_MACRO(_ISOC9X_SOURCE); + PRINT_MACRO(_LARGEFILE_SOURCE); + PRINT_MACRO(_LARGEFILE64_SOURCE); + PRINT_MACRO(_SVID_SOURCE); + PRINT_MACRO(_THREAD_SAFE); + PRINT_MACRO(_XOPEN_SOURCE_EXTENDED); + PRINT_MACRO(XPG); + PRINT_MACRO(__MINGW32_MAJOR_VERSION); + PRINT_MACRO(__MINGW32_MINOR_VERSION); + // POSIX: + PRINT_MACRO(_POSIX_ADVISORY_INFO); + PRINT_MACRO(_POSIX_ASYNCHRONOUS_IO); + PRINT_MACRO(_POSIX_BARRIERS); + PRINT_MACRO(_POSIX_C_SOURCE); + PRINT_MACRO(_POSIX_CHOWN_RESTRICTED); + PRINT_MACRO(_POSIX_CLOCK_SELECTION); + PRINT_MACRO(_POSIX_CPUTIME); + PRINT_MACRO(_POSIX_FSYNC); + PRINT_MACRO(_POSIX_JOB_CONTROL); + PRINT_MACRO(_POSIX_MAPPED_FILES); + PRINT_MACRO(_POSIX_MEMLOCK); + PRINT_MACRO(_POSIX_MEMLOCK_RANGE); + PRINT_MACRO(_POSIX_MEMORY_PROTECTION); + PRINT_MACRO(_POSIX_MESSAGE_PASSING); + PRINT_MACRO(_POSIX_MONOTONIC_CLOCK); + PRINT_MACRO(_POSIX_NO_TRUNC); + PRINT_MACRO(_POSIX_PRIORITIZED_IO); + PRINT_MACRO(_POSIX_PRIORITY_SCHEDULING); + PRINT_MACRO(_POSIX_RAW_SOCKETS); + PRINT_MACRO(_POSIX_READER_WRITER_LOCKS); + PRINT_MACRO(_POSIX_REALTIME_SIGNALS); + PRINT_MACRO(_POSIX_REGEXP); + PRINT_MACRO(_POSIX_SAVED_IDS); + PRINT_MACRO(_POSIX_SEMAPHORES); + PRINT_MACRO(_POSIX_SHARED_MEMORY_OBJECTS); + PRINT_MACRO(_POSIX_SHELL); + PRINT_MACRO(_POSIX_SOURCE); + PRINT_MACRO(_POSIX_SPAWN); + PRINT_MACRO(_POSIX_SPIN_LOCKS); + PRINT_MACRO(_POSIX_SPORADIC_SERVER); + PRINT_MACRO(_POSIX_SYNCHRONIZED_IO); + PRINT_MACRO(_POSIX_THREAD_ATTR_STACKADDR); + PRINT_MACRO(_POSIX_THREAD_ATTR_STACKSIZE); + PRINT_MACRO(_POSIX_THREAD_CPUTIME); + PRINT_MACRO(_POSIX_THREAD_PRIO_INHERIT); + PRINT_MACRO(_POSIX_THREAD_PRIO_PROTECT); + PRINT_MACRO(_POSIX_THREAD_PRIORITY_SCHEDULING); + PRINT_MACRO(_POSIX_THREAD_PROCESS_SHARED); + PRINT_MACRO(_POSIX_THREAD_SAFE_FUNCTIONS); + PRINT_MACRO(_POSIX_THREAD_SPORADIC_SERVER); + PRINT_MACRO(_POSIX_THREADS); + PRINT_MACRO(_POSIX_TIMEOUTS); + PRINT_MACRO(_POSIX_TIMERS); + PRINT_MACRO(_POSIX_TRACE); + PRINT_MACRO(_POSIX_TRACE_EVENT_FILTER); + PRINT_MACRO(_POSIX_TRACE_INHERIT); + PRINT_MACRO(_POSIX_TRACE_LOG); + PRINT_MACRO(_POSIX_TYPED_MEMORY_OBJECTS); + PRINT_MACRO(_POSIX_VDISABLE); + PRINT_MACRO(_POSIX_VERSION); + PRINT_MACRO(_POSIX2_C_BIND); + PRINT_MACRO(_POSIX2_C_DEV); + PRINT_MACRO(_POSIX2_CHAR_TERM); + PRINT_MACRO(_POSIX2_FORT_DEV); + PRINT_MACRO(_POSIX2_FORT_RUN); + PRINT_MACRO(_POSIX2_LOCALEDEF); + PRINT_MACRO(_POSIX2_PBS); + PRINT_MACRO(_POSIX2_PBS_ACCOUNTING); + PRINT_MACRO(_POSIX2_PBS_CHECKPOINT); + PRINT_MACRO(_POSIX2_PBS_LOCATE); + PRINT_MACRO(_POSIX2_PBS_MESSAGE); + PRINT_MACRO(_POSIX2_PBS_TRACK); + PRINT_MACRO(_POSIX2_SW_DEV); + PRINT_MACRO(_POSIX2_UPE); + PRINT_MACRO(_POSIX2_VERSION); + PRINT_MACRO(_V6_ILP32_OFF32); + PRINT_MACRO(_V6_ILP32_OFFBIG); + PRINT_MACRO(_V6_LP64_OFF64); + PRINT_MACRO(_V6_LPBIG_OFFBIG); + PRINT_MACRO(_XBS5_ILP32_OFF32); + PRINT_MACRO(_XBS5_ILP32_OFFBIG); + PRINT_MACRO(_XBS5_LP64_OFF64); + PRINT_MACRO(_XBS5_LPBIG_OFFBIG); + PRINT_MACRO(_XOPEN_CRYPT); + PRINT_MACRO(_XOPEN_ENH_I18N); + PRINT_MACRO(_XOPEN_LEGACY); + PRINT_MACRO(_XOPEN_REALTIME); + PRINT_MACRO(_XOPEN_REALTIME_THREADS); + PRINT_MACRO(_XOPEN_SHM); + PRINT_MACRO(_XOPEN_SOURCE); + PRINT_MACRO(_XOPEN_STREAMS); + PRINT_MACRO(_XOPEN_UNIX); + PRINT_MACRO(_XOPEN_VERSION); + // Misc: + PRINT_MACRO(__USE_BSD); + PRINT_MACRO(_FILE_OFFSET_BITS); +} + +void print_boost_macros() +{ + std::cout << "Boost version " << BOOST_STRINGIZE(BOOST_VERSION) << std::endl; + // config setup macros first: + PRINT_MACRO(BOOST_USER_CONFIG); + PRINT_MACRO(BOOST_COMPILER_CONFIG); + PRINT_MACRO(BOOST_STDLIB_CONFIG); + PRINT_MACRO(BOOST_PLATFORM_CONFIG); + PRINT_MACRO(BOOST_NO_CONFIG); + PRINT_MACRO(BOOST_NO_USER_CONFIG); + PRINT_MACRO(BOOST_NO_COMPILER_CONFIG); + PRINT_MACRO(BOOST_NO_STDLIB_CONFIG); + PRINT_MACRO(BOOST_NO_PLATFORM_CONFIG); + // then defect and feature macros: + PRINT_MACRO(BOOST_DISABLE_THREADS); + PRINT_MACRO(BOOST_DISABLE_WIN32); + PRINT_MACRO(BOOST_HAS_THREADS); + PRINT_MACRO(BOOST_WINDOWS); + + // BEGIN GENERATED BLOCK DO NOT EDIT THIS!!!!!! + PRINT_MACRO(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG); + PRINT_MACRO(BOOST_DEDUCED_TYPENAME); + PRINT_MACRO(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL); + PRINT_MACRO(BOOST_HAS_BETHREADS); + PRINT_MACRO(BOOST_HAS_CLOCK_GETTIME); + PRINT_MACRO(BOOST_HAS_DIRENT_H); + PRINT_MACRO(BOOST_HAS_EXPM1); + PRINT_MACRO(BOOST_HAS_FLOAT128); + PRINT_MACRO(BOOST_HAS_FTIME); + PRINT_MACRO(BOOST_HAS_GETSYSTEMTIMEASFILETIME); + PRINT_MACRO(BOOST_HAS_GETTIMEOFDAY); + PRINT_MACRO(BOOST_HAS_HASH); + PRINT_MACRO(BOOST_HAS_INT128); + PRINT_MACRO(BOOST_HAS_LOG1P); + PRINT_MACRO(BOOST_HAS_LONG_LONG); + PRINT_MACRO(BOOST_HAS_MACRO_USE_FACET); + PRINT_MACRO(BOOST_HAS_MS_INT64); + PRINT_MACRO(BOOST_HAS_NANOSLEEP); + PRINT_MACRO(BOOST_HAS_NL_TYPES_H); + PRINT_MACRO(BOOST_HAS_NRVO); + PRINT_MACRO(BOOST_HAS_PARTIAL_STD_ALLOCATOR); + PRINT_MACRO(BOOST_HAS_PRAGMA_DETECT_MISMATCH); + PRINT_MACRO(BOOST_HAS_PTHREADS); + PRINT_MACRO(BOOST_HAS_PTHREAD_DELAY_NP); + PRINT_MACRO(BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE); + PRINT_MACRO(BOOST_HAS_PTHREAD_YIELD); + PRINT_MACRO(BOOST_HAS_RVALUE_REFS); + PRINT_MACRO(BOOST_HAS_SCHED_YIELD); + PRINT_MACRO(BOOST_HAS_SGI_TYPE_TRAITS); + PRINT_MACRO(BOOST_HAS_SIGACTION); + PRINT_MACRO(BOOST_HAS_SLIST); + PRINT_MACRO(BOOST_HAS_STATIC_ASSERT); + PRINT_MACRO(BOOST_HAS_STDINT_H); + PRINT_MACRO(BOOST_HAS_STLP_USE_FACET); + PRINT_MACRO(BOOST_HAS_TWO_ARG_USE_FACET); + PRINT_MACRO(BOOST_HAS_UNISTD_H); + PRINT_MACRO(BOOST_HAS_VARIADIC_TMPL); + PRINT_MACRO(BOOST_HAS_WINTHREADS); + PRINT_MACRO(BOOST_MSVC6_MEMBER_TEMPLATES); + PRINT_MACRO(BOOST_MSVC_STD_ITERATOR); + PRINT_MACRO(BOOST_NO_ADL_BARRIER); + PRINT_MACRO(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP); + PRINT_MACRO(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS); + PRINT_MACRO(BOOST_NO_AUTO_PTR); + PRINT_MACRO(BOOST_NO_COMPLETE_VALUE_INITIALIZATION); + PRINT_MACRO(BOOST_NO_CTYPE_FUNCTIONS); + PRINT_MACRO(BOOST_NO_CV_SPECIALIZATIONS); + PRINT_MACRO(BOOST_NO_CV_VOID_SPECIALIZATIONS); + PRINT_MACRO(BOOST_NO_CWCHAR); + PRINT_MACRO(BOOST_NO_CWCTYPE); + PRINT_MACRO(BOOST_NO_CXX03); + PRINT_MACRO(BOOST_NO_CXX11); + PRINT_MACRO(BOOST_NO_CXX11_ADDRESSOF); + PRINT_MACRO(BOOST_NO_CXX11_ALIGNAS); + PRINT_MACRO(BOOST_NO_CXX11_ALIGNOF); + PRINT_MACRO(BOOST_NO_CXX11_ALLOCATOR); + PRINT_MACRO(BOOST_NO_CXX11_ATOMIC_SMART_PTR); + PRINT_MACRO(BOOST_NO_CXX11_AUTO_DECLARATIONS); + PRINT_MACRO(BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS); + PRINT_MACRO(BOOST_NO_CXX11_CHAR16_T); + PRINT_MACRO(BOOST_NO_CXX11_CHAR32_T); + PRINT_MACRO(BOOST_NO_CXX11_CONSTEXPR); + PRINT_MACRO(BOOST_NO_CXX11_DECLTYPE); + PRINT_MACRO(BOOST_NO_CXX11_DECLTYPE_N3276); + PRINT_MACRO(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS); + PRINT_MACRO(BOOST_NO_CXX11_DEFAULTED_MOVES); + PRINT_MACRO(BOOST_NO_CXX11_DELETED_FUNCTIONS); + PRINT_MACRO(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS); + PRINT_MACRO(BOOST_NO_CXX11_EXTERN_TEMPLATE); + PRINT_MACRO(BOOST_NO_CXX11_FINAL); + PRINT_MACRO(BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS); + PRINT_MACRO(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS); + PRINT_MACRO(BOOST_NO_CXX11_HDR_ARRAY); + PRINT_MACRO(BOOST_NO_CXX11_HDR_ATOMIC); + PRINT_MACRO(BOOST_NO_CXX11_HDR_CHRONO); + PRINT_MACRO(BOOST_NO_CXX11_HDR_CODECVT); + PRINT_MACRO(BOOST_NO_CXX11_HDR_CONDITION_VARIABLE); + PRINT_MACRO(BOOST_NO_CXX11_HDR_EXCEPTION); + PRINT_MACRO(BOOST_NO_CXX11_HDR_FORWARD_LIST); + PRINT_MACRO(BOOST_NO_CXX11_HDR_FUNCTIONAL); + PRINT_MACRO(BOOST_NO_CXX11_HDR_FUTURE); + PRINT_MACRO(BOOST_NO_CXX11_HDR_INITIALIZER_LIST); + PRINT_MACRO(BOOST_NO_CXX11_HDR_MUTEX); + PRINT_MACRO(BOOST_NO_CXX11_HDR_RANDOM); + PRINT_MACRO(BOOST_NO_CXX11_HDR_RATIO); + PRINT_MACRO(BOOST_NO_CXX11_HDR_REGEX); + PRINT_MACRO(BOOST_NO_CXX11_HDR_SYSTEM_ERROR); + PRINT_MACRO(BOOST_NO_CXX11_HDR_THREAD); + PRINT_MACRO(BOOST_NO_CXX11_HDR_TUPLE); + PRINT_MACRO(BOOST_NO_CXX11_HDR_TYPEINDEX); + PRINT_MACRO(BOOST_NO_CXX11_HDR_TYPE_TRAITS); + PRINT_MACRO(BOOST_NO_CXX11_HDR_UNORDERED_MAP); + PRINT_MACRO(BOOST_NO_CXX11_HDR_UNORDERED_SET); + PRINT_MACRO(BOOST_NO_CXX11_INLINE_NAMESPACES); + PRINT_MACRO(BOOST_NO_CXX11_LAMBDAS); + PRINT_MACRO(BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS); + PRINT_MACRO(BOOST_NO_CXX11_NOEXCEPT); + PRINT_MACRO(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS); + PRINT_MACRO(BOOST_NO_CXX11_NULLPTR); + PRINT_MACRO(BOOST_NO_CXX11_NUMERIC_LIMITS); + PRINT_MACRO(BOOST_NO_CXX11_OVERRIDE); + PRINT_MACRO(BOOST_NO_CXX11_POINTER_TRAITS); + PRINT_MACRO(BOOST_NO_CXX11_RANGE_BASED_FOR); + PRINT_MACRO(BOOST_NO_CXX11_RAW_LITERALS); + PRINT_MACRO(BOOST_NO_CXX11_REF_QUALIFIERS); + PRINT_MACRO(BOOST_NO_CXX11_RVALUE_REFERENCES); + PRINT_MACRO(BOOST_NO_CXX11_SCOPED_ENUMS); + PRINT_MACRO(BOOST_NO_CXX11_SFINAE_EXPR); + PRINT_MACRO(BOOST_NO_CXX11_SMART_PTR); + PRINT_MACRO(BOOST_NO_CXX11_STATIC_ASSERT); + PRINT_MACRO(BOOST_NO_CXX11_STD_ALIGN); + PRINT_MACRO(BOOST_NO_CXX11_TEMPLATE_ALIASES); + PRINT_MACRO(BOOST_NO_CXX11_THREAD_LOCAL); + PRINT_MACRO(BOOST_NO_CXX11_TRAILING_RESULT_TYPES); + PRINT_MACRO(BOOST_NO_CXX11_UNICODE_LITERALS); + PRINT_MACRO(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX); + PRINT_MACRO(BOOST_NO_CXX11_UNRESTRICTED_UNION); + PRINT_MACRO(BOOST_NO_CXX11_USER_DEFINED_LITERALS); + PRINT_MACRO(BOOST_NO_CXX11_VARIADIC_MACROS); + PRINT_MACRO(BOOST_NO_CXX11_VARIADIC_TEMPLATES); + PRINT_MACRO(BOOST_NO_CXX14); + PRINT_MACRO(BOOST_NO_CXX14_AGGREGATE_NSDMI); + PRINT_MACRO(BOOST_NO_CXX14_BINARY_LITERALS); + PRINT_MACRO(BOOST_NO_CXX14_CONSTEXPR); + PRINT_MACRO(BOOST_NO_CXX14_DECLTYPE_AUTO); + PRINT_MACRO(BOOST_NO_CXX14_DIGIT_SEPARATORS); + PRINT_MACRO(BOOST_NO_CXX14_GENERIC_LAMBDAS); + PRINT_MACRO(BOOST_NO_CXX14_HDR_SHARED_MUTEX); + PRINT_MACRO(BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES); + PRINT_MACRO(BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION); + PRINT_MACRO(BOOST_NO_CXX14_STD_EXCHANGE); + PRINT_MACRO(BOOST_NO_CXX14_VARIABLE_TEMPLATES); + PRINT_MACRO(BOOST_NO_CXX17); + PRINT_MACRO(BOOST_NO_CXX17_DEDUCTION_GUIDES); + PRINT_MACRO(BOOST_NO_CXX17_FOLD_EXPRESSIONS); + PRINT_MACRO(BOOST_NO_CXX17_HDR_ANY); + PRINT_MACRO(BOOST_NO_CXX17_HDR_CHARCONV); + PRINT_MACRO(BOOST_NO_CXX17_HDR_EXECUTION); + PRINT_MACRO(BOOST_NO_CXX17_HDR_FILESYSTEM); + PRINT_MACRO(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE); + PRINT_MACRO(BOOST_NO_CXX17_HDR_OPTIONAL); + PRINT_MACRO(BOOST_NO_CXX17_HDR_STRING_VIEW); + PRINT_MACRO(BOOST_NO_CXX17_HDR_VARIANT); + PRINT_MACRO(BOOST_NO_CXX17_IF_CONSTEXPR); + PRINT_MACRO(BOOST_NO_CXX17_INLINE_VARIABLES); + PRINT_MACRO(BOOST_NO_CXX17_ITERATOR_TRAITS); + PRINT_MACRO(BOOST_NO_CXX17_STD_APPLY); + PRINT_MACRO(BOOST_NO_CXX17_STD_INVOKE); + PRINT_MACRO(BOOST_NO_CXX17_STRUCTURED_BINDINGS); + PRINT_MACRO(BOOST_NO_CXX20_HDR_BARRIER); + PRINT_MACRO(BOOST_NO_CXX20_HDR_BIT); + PRINT_MACRO(BOOST_NO_CXX20_HDR_COMPARE); + PRINT_MACRO(BOOST_NO_CXX20_HDR_CONCEPTS); + PRINT_MACRO(BOOST_NO_CXX20_HDR_COROUTINE); + PRINT_MACRO(BOOST_NO_CXX20_HDR_FORMAT); + PRINT_MACRO(BOOST_NO_CXX20_HDR_LATCH); + PRINT_MACRO(BOOST_NO_CXX20_HDR_NUMBERS); + PRINT_MACRO(BOOST_NO_CXX20_HDR_RANGES); + PRINT_MACRO(BOOST_NO_CXX20_HDR_SEMAPHORE); + PRINT_MACRO(BOOST_NO_CXX20_HDR_SOURCE_LOCATION); + PRINT_MACRO(BOOST_NO_CXX20_HDR_SPAN); + PRINT_MACRO(BOOST_NO_CXX20_HDR_STOP_TOKEN); + PRINT_MACRO(BOOST_NO_CXX20_HDR_SYNCSTREAM); + PRINT_MACRO(BOOST_NO_CXX20_HDR_VERSION); + PRINT_MACRO(BOOST_NO_CXX23_HDR_EXPECTED); + PRINT_MACRO(BOOST_NO_CXX23_HDR_FLAT_MAP); + PRINT_MACRO(BOOST_NO_CXX23_HDR_FLAT_SET); + PRINT_MACRO(BOOST_NO_CXX23_HDR_GENERATOR); + PRINT_MACRO(BOOST_NO_CXX23_HDR_MDSPAN); + PRINT_MACRO(BOOST_NO_CXX23_HDR_PRINT); + PRINT_MACRO(BOOST_NO_CXX23_HDR_SPANSTREAM); + PRINT_MACRO(BOOST_NO_CXX23_HDR_STACKTRACE); + PRINT_MACRO(BOOST_NO_CXX23_HDR_STDFLOAT); + PRINT_MACRO(BOOST_NO_CXX98_BINDERS); + PRINT_MACRO(BOOST_NO_CXX98_FUNCTION_BASE); + PRINT_MACRO(BOOST_NO_CXX98_RANDOM_SHUFFLE); + PRINT_MACRO(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS); + PRINT_MACRO(BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS); + PRINT_MACRO(BOOST_NO_EXCEPTIONS); + PRINT_MACRO(BOOST_NO_EXCEPTION_STD_NAMESPACE); + PRINT_MACRO(BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS); + PRINT_MACRO(BOOST_NO_FENV_H); + PRINT_MACRO(BOOST_NO_FUNCTION_TEMPLATE_ORDERING); + PRINT_MACRO(BOOST_NO_FUNCTION_TYPE_SPECIALIZATIONS); + PRINT_MACRO(BOOST_NO_INCLASS_MEMBER_INITIALIZATION); + PRINT_MACRO(BOOST_NO_INTEGRAL_INT64_T); + PRINT_MACRO(BOOST_NO_INTRINSIC_WCHAR_T); + PRINT_MACRO(BOOST_NO_IOSFWD); + PRINT_MACRO(BOOST_NO_IOSTREAM); + PRINT_MACRO(BOOST_NO_IS_ABSTRACT); + PRINT_MACRO(BOOST_NO_LIMITS); + PRINT_MACRO(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS); + PRINT_MACRO(BOOST_NO_LONG_LONG); + PRINT_MACRO(BOOST_NO_LONG_LONG_NUMERIC_LIMITS); + PRINT_MACRO(BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS); + PRINT_MACRO(BOOST_NO_MEMBER_TEMPLATES); + PRINT_MACRO(BOOST_NO_MEMBER_TEMPLATE_FRIENDS); + PRINT_MACRO(BOOST_NO_MEMBER_TEMPLATE_KEYWORD); + PRINT_MACRO(BOOST_NO_MS_INT64_NUMERIC_LIMITS); + PRINT_MACRO(BOOST_NO_NESTED_FRIENDSHIP); + PRINT_MACRO(BOOST_NO_OPERATORS_IN_NAMESPACE); + PRINT_MACRO(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS); + PRINT_MACRO(BOOST_NO_POINTER_TO_MEMBER_CONST); + PRINT_MACRO(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS); + PRINT_MACRO(BOOST_NO_PRIVATE_IN_AGGREGATE); + PRINT_MACRO(BOOST_NO_RESTRICT_REFERENCES); + PRINT_MACRO(BOOST_NO_RTTI); + PRINT_MACRO(BOOST_NO_SFINAE); + PRINT_MACRO(BOOST_NO_SFINAE_EXPR); + PRINT_MACRO(BOOST_NO_STDC_NAMESPACE); + PRINT_MACRO(BOOST_NO_STD_ALLOCATOR); + PRINT_MACRO(BOOST_NO_STD_DISTANCE); + PRINT_MACRO(BOOST_NO_STD_ITERATOR); + PRINT_MACRO(BOOST_NO_STD_ITERATOR_TRAITS); + PRINT_MACRO(BOOST_NO_STD_LOCALE); + PRINT_MACRO(BOOST_NO_STD_MESSAGES); + PRINT_MACRO(BOOST_NO_STD_MIN_MAX); + PRINT_MACRO(BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN); + PRINT_MACRO(BOOST_NO_STD_TYPEINFO); + PRINT_MACRO(BOOST_NO_STD_USE_FACET); + PRINT_MACRO(BOOST_NO_STD_WSTREAMBUF); + PRINT_MACRO(BOOST_NO_STD_WSTRING); + PRINT_MACRO(BOOST_NO_STRINGSTREAM); + PRINT_MACRO(BOOST_NO_SWPRINTF); + PRINT_MACRO(BOOST_NO_TEMPLATED_IOSTREAMS); + PRINT_MACRO(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS); + PRINT_MACRO(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION); + PRINT_MACRO(BOOST_NO_TEMPLATE_TEMPLATES); + PRINT_MACRO(BOOST_NO_TWO_PHASE_NAME_LOOKUP); + PRINT_MACRO(BOOST_NO_TYPEID); + PRINT_MACRO(BOOST_NO_TYPENAME_WITH_CTOR); + PRINT_MACRO(BOOST_NO_UNREACHABLE_RETURN_DETECTION); + PRINT_MACRO(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE); + PRINT_MACRO(BOOST_NO_USING_TEMPLATE); + PRINT_MACRO(BOOST_NO_VOID_RETURNS); + + + + + + + + + + + + + + + + + + // END GENERATED BLOCK + + PRINT_MACRO(BOOST_CXX_VERSION); + PRINT_MACRO(BOOST_INTEL); + PRINT_MACRO(BOOST_MSVC); + PRINT_MACRO(BOOST_GCC); + PRINT_MACRO(BOOST_CLANG); + PRINT_MACRO(BOOST_CLANG_VERSION); + PRINT_MACRO(BOOST_LIBSTDCXX_VERSION); + PRINT_MACRO(BOOST_MSSTL_VERSION); + PRINT_MACRO(BOOST_STD_EXTENSION_NAMESPACE); + PRINT_MACRO(BOOST_UNREACHABLE_RETURN(0)); + PRINT_MACRO(BOOST_CONSTEXPR); + PRINT_MACRO(BOOST_CONSTEXPR_OR_CONST); + PRINT_MACRO(BOOST_STATIC_CONSTEXPR); + PRINT_MACRO(BOOST_NOEXCEPT); + PRINT_MACRO(BOOST_FORCEINLINE); + PRINT_MACRO(BOOST_NOINLINE); + PRINT_MACRO(BOOST_FALLTHROUGH); + PRINT_MACRO(BOOST_MAY_ALIAS); + PRINT_MACRO(BOOST_NO_MAY_ALIAS); + PRINT_MACRO(BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS); + PRINT_MACRO(BOOST_ATTRIBUTE_UNUSED); + PRINT_MACRO(BOOST_UNLIKELY); + PRINT_MACRO(BOOST_NORETURN); +} + +#ifdef __has_include +#if __has_include() +# include +#endif +#if __has_include() && (BOOST_CXX_VERSION > 201100) +# include +#endif +#endif + +void print_sd6_macros() +{ + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0096r5.html + + // Library macros are only really available if we have : + + PRINT_MACRO(__cpp_lib_addressof_constexpr); + PRINT_MACRO(__cpp_lib_allocator_traits_is_always_equal); + PRINT_MACRO(__cpp_lib_any); + PRINT_MACRO(__cpp_lib_apply); + PRINT_MACRO(__cpp_lib_array_constexpr); + PRINT_MACRO(__cpp_lib_as_const); + PRINT_MACRO(__cpp_lib_assume_aligned); + PRINT_MACRO(__cpp_lib_atomic_flag_test); + PRINT_MACRO(__cpp_lib_atomic_float); + PRINT_MACRO(__cpp_lib_atomic_is_always_lock_free); + PRINT_MACRO(__cpp_lib_atomic_lock_free_type_aliases); + PRINT_MACRO(__cpp_lib_atomic_ref); + PRINT_MACRO(__cpp_lib_atomic_shared_ptr); + PRINT_MACRO(__cpp_lib_atomic_value_initialization); + PRINT_MACRO(__cpp_lib_atomic_wait); + PRINT_MACRO(__cpp_lib_barrier); + PRINT_MACRO(__cpp_lib_bind_front); + PRINT_MACRO(__cpp_lib_bit_cast); + PRINT_MACRO(__cpp_lib_bitops); + PRINT_MACRO(__cpp_lib_bool_constant); + PRINT_MACRO(__cpp_lib_bounded_array_traits); + PRINT_MACRO(__cpp_lib_boyer_moore_searcher); + PRINT_MACRO(__cpp_lib_byte); + PRINT_MACRO(__cpp_lib_char8_t); + PRINT_MACRO(__cpp_lib_chrono); + PRINT_MACRO(__cpp_lib_chrono_udls); + PRINT_MACRO(__cpp_lib_clamp); + PRINT_MACRO(__cpp_lib_complex_udls); + PRINT_MACRO(__cpp_lib_concepts); + PRINT_MACRO(__cpp_lib_constexpr_algorithms); + PRINT_MACRO(__cpp_lib_constexpr_complex); + PRINT_MACRO(__cpp_lib_constexpr_dynamic_alloc); + PRINT_MACRO(__cpp_lib_constexpr_functional); + PRINT_MACRO(__cpp_lib_constexpr_iterator); + PRINT_MACRO(__cpp_lib_constexpr_memory); + PRINT_MACRO(__cpp_lib_constexpr_numeric); + PRINT_MACRO(__cpp_lib_constexpr_string); + PRINT_MACRO(__cpp_lib_constexpr_string_view); + PRINT_MACRO(__cpp_lib_constexpr_tuple); + PRINT_MACRO(__cpp_lib_constexpr_utility); + PRINT_MACRO(__cpp_lib_constexpr_vector); + PRINT_MACRO(__cpp_lib_coroutine); + PRINT_MACRO(__cpp_lib_destroying_delete); + PRINT_MACRO(__cpp_lib_enable_shared_from_this); + PRINT_MACRO(__cpp_lib_endian); + PRINT_MACRO(__cpp_lib_erase_if); + PRINT_MACRO(__cpp_lib_exchange_function); + PRINT_MACRO(__cpp_lib_execution); + PRINT_MACRO(__cpp_lib_expected); + PRINT_MACRO(__cpp_lib_filesystem); + PRINT_MACRO(__cpp_lib_flat_map); + PRINT_MACRO(__cpp_lib_flat_set); + PRINT_MACRO(__cpp_lib_format); + PRINT_MACRO(__cpp_lib_gcd_lcm); + PRINT_MACRO(__cpp_lib_generator); + PRINT_MACRO(__cpp_lib_generic_associative_lookup); + PRINT_MACRO(__cpp_lib_generic_unordered_lookup); + PRINT_MACRO(__cpp_lib_hardware_interference_size); + PRINT_MACRO(__cpp_lib_has_unique_object_representations); + PRINT_MACRO(__cpp_lib_hypot); + PRINT_MACRO(__cpp_lib_incomplete_container_elements); + PRINT_MACRO(__cpp_lib_int_pow2); + PRINT_MACRO(__cpp_lib_integer_comparison_functions); + PRINT_MACRO(__cpp_lib_integer_sequence); + PRINT_MACRO(__cpp_lib_integral_constant_callable); + PRINT_MACRO(__cpp_lib_interpolate); + PRINT_MACRO(__cpp_lib_invoke); + PRINT_MACRO(__cpp_lib_is_aggregate); + PRINT_MACRO(__cpp_lib_is_constant_evaluated); + PRINT_MACRO(__cpp_lib_is_final); + PRINT_MACRO(__cpp_lib_is_invocable); + PRINT_MACRO(__cpp_lib_is_layout_compatible); + PRINT_MACRO(__cpp_lib_is_nothrow_convertible); + PRINT_MACRO(__cpp_lib_is_null_pointer); + PRINT_MACRO(__cpp_lib_is_pointer_interconvertible); + PRINT_MACRO(__cpp_lib_is_swappable); + PRINT_MACRO(__cpp_lib_jthread); + PRINT_MACRO(__cpp_lib_latch); + PRINT_MACRO(__cpp_lib_launder); + PRINT_MACRO(__cpp_lib_list_remove_return_type); + PRINT_MACRO(__cpp_lib_logical_traits); + PRINT_MACRO(__cpp_lib_make_from_tuple); + PRINT_MACRO(__cpp_lib_make_reverse_iterator); + PRINT_MACRO(__cpp_lib_make_unique); + PRINT_MACRO(__cpp_lib_map_try_emplace); + PRINT_MACRO(__cpp_lib_math_constants); + PRINT_MACRO(__cpp_lib_math_special_functions); + PRINT_MACRO(__cpp_lib_mdspan); + PRINT_MACRO(__cpp_lib_memory_resource); + PRINT_MACRO(__cpp_lib_node_extract); + PRINT_MACRO(__cpp_lib_nonmember_container_access); + PRINT_MACRO(__cpp_lib_not_fn); + PRINT_MACRO(__cpp_lib_null_iterators); + PRINT_MACRO(__cpp_lib_optional); + PRINT_MACRO(__cpp_lib_parallel_algorithm); + PRINT_MACRO(__cpp_lib_polymorphic_allocator); + PRINT_MACRO(__cpp_lib_print); + PRINT_MACRO(__cpp_lib_quoted_string_io); + PRINT_MACRO(__cpp_lib_ranges); + PRINT_MACRO(__cpp_lib_raw_memory_algorithms); + PRINT_MACRO(__cpp_lib_remove_cvref); + PRINT_MACRO(__cpp_lib_result_of_sfinae); + PRINT_MACRO(__cpp_lib_robust_nonmodifying_seq_ops); + PRINT_MACRO(__cpp_lib_sample); + PRINT_MACRO(__cpp_lib_scoped_lock); + PRINT_MACRO(__cpp_lib_semaphore); + PRINT_MACRO(__cpp_lib_shared_mutex); + PRINT_MACRO(__cpp_lib_shared_ptr_arrays); + PRINT_MACRO(__cpp_lib_shared_ptr_weak_type); + PRINT_MACRO(__cpp_lib_shared_timed_mutex); + PRINT_MACRO(__cpp_lib_shift); + PRINT_MACRO(__cpp_lib_smart_ptr_for_overwrite); + PRINT_MACRO(__cpp_lib_source_location); + PRINT_MACRO(__cpp_lib_span); + PRINT_MACRO(__cpp_lib_spanstream); + PRINT_MACRO(__cpp_lib_ssize); + PRINT_MACRO(__cpp_lib_stacktrace); + PRINT_MACRO(__cpp_lib_starts_ends_with); + PRINT_MACRO(__cpp_lib_string_udls); + PRINT_MACRO(__cpp_lib_string_view); + PRINT_MACRO(__cpp_lib_syncbuf); + PRINT_MACRO(__cpp_lib_three_way_comparison); + PRINT_MACRO(__cpp_lib_to_address); + PRINT_MACRO(__cpp_lib_to_array); + PRINT_MACRO(__cpp_lib_to_chars); + PRINT_MACRO(__cpp_lib_transformation_trait_aliases); + PRINT_MACRO(__cpp_lib_transparent_operators); + PRINT_MACRO(__cpp_lib_tuple_element_t); + PRINT_MACRO(__cpp_lib_tuples_by_type); + PRINT_MACRO(__cpp_lib_type_identity); + PRINT_MACRO(__cpp_lib_type_trait_variable_templates); + PRINT_MACRO(__cpp_lib_uncaught_exceptions); + PRINT_MACRO(__cpp_lib_unordered_map_try_emplace); + PRINT_MACRO(__cpp_lib_unwrap_ref); + PRINT_MACRO(__cpp_lib_variant); + PRINT_MACRO(__cpp_lib_void_t); + + // C++20: + PRINT_MACRO(__cpp_aggregate_paren_init); + PRINT_MACRO(__cpp_char8_t); + PRINT_MACRO(__cpp_char8_type); + PRINT_MACRO(__cpp_conditional_explicit); + PRINT_MACRO(__cpp_coroutines); + PRINT_MACRO(__cpp_impl_destroying_delete); + PRINT_MACRO(__cpp_impl_three_way_comparison); + PRINT_MACRO(__cpp_nontype_template_parameter_class); + + // C++17: + PRINT_MACRO(__cpp_hex_float); + PRINT_MACRO(__cpp_inline_variables); + PRINT_MACRO(__cpp_aligned_new); + PRINT_MACRO(__cpp_guaranteed_copy_elision); + PRINT_MACRO(__cpp_noexcept_function_type); + PRINT_MACRO(__cpp_fold_expressions); + PRINT_MACRO(__cpp_capture_star_this); + PRINT_MACRO(__cpp_constexpr); + PRINT_MACRO(__cpp_if_constexpr); + PRINT_MACRO(__cpp_range_based_for); + PRINT_MACRO(__cpp_static_assert); + PRINT_MACRO(__cpp_deduction_guides); + PRINT_MACRO(__cpp_nontype_template_parameter_auto); + PRINT_MACRO(__cpp_namespace_attributes); + PRINT_MACRO(__cpp_enumerator_attributes); + PRINT_MACRO(__cpp_inheriting_constructors); + PRINT_MACRO(__cpp_variadic_using); + PRINT_MACRO(__cpp_structured_bindings); + PRINT_MACRO(__cpp_aggregate_bases); + PRINT_MACRO(__cpp_nontype_template_args); + PRINT_MACRO(__cpp_template_template_args); + + // C++14: + PRINT_MACRO(__cpp_binary_literals); + PRINT_MACRO(__cpp_init_captures); + PRINT_MACRO(__cpp_generic_lambdas); + PRINT_MACRO(__cpp_sized_deallocation); + PRINT_MACRO(__cpp_decltype_auto); + PRINT_MACRO(__cpp_return_type_deduction); + PRINT_MACRO(__cpp_aggregate_nsdmi); + PRINT_MACRO(__cpp_variable_templates); + + // C++11: + PRINT_MACRO(__cpp_unicode_characters); + PRINT_MACRO(__cpp_raw_strings); + PRINT_MACRO(__cpp_unicode_literals); + PRINT_MACRO(__cpp_user_defined_literals); + PRINT_MACRO(__cpp_threadsafe_static_init); + PRINT_MACRO(__cpp_lambdas); + PRINT_MACRO(__cpp_decltype); + PRINT_MACRO(__cpp_attributes); + PRINT_MACRO(__cpp_rvalue_references); + PRINT_MACRO(__cpp_variadic_templates); + PRINT_MACRO(__cpp_initializer_lists); + PRINT_MACRO(__cpp_delegating_constructors); + PRINT_MACRO(__cpp_nsdmi); + PRINT_MACRO(__cpp_ref_qualifiers); + PRINT_MACRO(__cpp_alias_templates); + + // C++98: + PRINT_MACRO(__cpp_rtti); + PRINT_MACRO(__cpp_exceptions); + + // : + PRINT_MACRO(ATOMIC_INT_LOCK_FREE); + PRINT_MACRO(ATOMIC_SHORT_LOCK_FREE); + PRINT_MACRO(ATOMIC_LONG_LOCK_FREE); + PRINT_MACRO(ATOMIC_LLONG_LOCK_FREE); + PRINT_MACRO(ATOMIC_POINTER_LOCK_FREE); + PRINT_MACRO(ATOMIC_CHAR_LOCK_FREE); + PRINT_MACRO(ATOMIC_WCHAR_T_LOCK_FREE); + PRINT_MACRO(ATOMIC_CHAR8_T_LOCK_FREE); + PRINT_MACRO(ATOMIC_CHAR16_T_LOCK_FREE); + PRINT_MACRO(ATOMIC_CHAR32_T_LOCK_FREE); +} + +void print_separator() +{ + std::cout << +"\n\n*********************************************************************\n\n"; +} + +int main() +{ + + // boost compiler workaround defines + print_compiler_macros(); + print_separator(); + print_stdlib_macros(); + print_separator(); + print_platform_macros(); + print_separator(); + print_boost_macros(); + print_separator(); + print_sd6_macros(); + + return 0; +} diff --git a/libs/iterator/.gitattributes b/libs/iterator/.gitattributes new file mode 100644 index 00000000..3e84d7c7 --- /dev/null +++ b/libs/iterator/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain diff --git a/libs/iterator/.github/workflows/ci.yml b/libs/iterator/.github/workflows/ci.yml new file mode 100644 index 00000000..49fa3352 --- /dev/null +++ b/libs/iterator/.github/workflows/ci.yml @@ -0,0 +1,508 @@ +# Copyright 2021-2022 Andrey Semashev +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +name: CI + +on: + pull_request: + push: + branches: + - master + - develop + - feature/** + +concurrency: + group: ${{format('{0}:{1}', github.repository, github.ref)}} + cancel-in-progress: true + +env: + GIT_FETCH_JOBS: 8 + NET_RETRY_COUNT: 5 + DEFAULT_BUILD_VARIANT: debug,release + +jobs: + posix: + defaults: + run: + shell: bash + + strategy: + fail-fast: false + matrix: + include: + # Linux, gcc + - toolset: gcc-4.6 + cxxstd: "0x" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - g++-4.6 + sources: + - "ppa:ubuntu-toolchain-r/test" + - toolset: gcc-4.7 + cxxstd: "11" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - g++-4.7 + - toolset: gcc-4.8 + cxxstd: "11" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - g++-4.8 + - toolset: gcc-4.9 + cxxstd: "11" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - g++-4.9 + - toolset: gcc-5 + cxxstd: "11,14,1z" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - g++-5 + - toolset: gcc-6 + cxxstd: "11,14,1z" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - g++-6 + - toolset: gcc-7 + cxxstd: "11,14,17" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - g++-7 + - toolset: gcc-8 + cxxstd: "11,14,17,2a" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - g++-8 + - toolset: gcc-9 + cxxstd: "11,14,17,2a" + os: ubuntu-20.04 + install: + - g++-9 + - toolset: gcc-10 + cxxstd: "11,14,17,20" + os: ubuntu-20.04 + install: + - g++-10 + - toolset: gcc-11 + cxxstd: "11,14,17,20,23" + os: ubuntu-22.04 + install: + - g++-11 + - toolset: gcc-12 + cxxstd: "11,14,17,20,23" + os: ubuntu-22.04 + install: + - g++-12 + - name: UBSAN + toolset: gcc-11 + cxxstd: "11,14,17,20,23" + ubsan: 1 + build_variant: debug + os: ubuntu-22.04 + install: + - g++-11 + + # Linux, clang + - toolset: clang + compiler: clang++-3.5 + cxxstd: "11" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - clang-3.5 + - toolset: clang + compiler: clang++-3.6 + cxxstd: "11,14" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - clang-3.6 + - toolset: clang + compiler: clang++-3.7 + cxxstd: "11,14" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - clang-3.7 + - toolset: clang + compiler: clang++-3.8 + cxxstd: "11,14" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - clang-3.8 + - toolset: clang + compiler: clang++-3.9 + cxxstd: "11,14" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-3.9 + - toolset: clang + compiler: clang++-4.0 + cxxstd: "11,14" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-4.0 + - toolset: clang + compiler: clang++-5.0 + cxxstd: "11,14,1z" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-5.0 + - toolset: clang + compiler: clang++-6.0 + cxxstd: "11,14,17" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-6.0 + - toolset: clang + compiler: clang++-7 + cxxstd: "11,14,17" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-7 + # Note: clang-8 does not fully support C++20, so it is not compatible with libstdc++-8 in this mode + - toolset: clang + compiler: clang++-8 + cxxstd: "11,14,17,2a" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-8 + - g++-7 + gcc_toolchain: 7 + - toolset: clang + compiler: clang++-9 + cxxstd: "11,14,17,2a" + os: ubuntu-20.04 + install: + - clang-9 + - toolset: clang + compiler: clang++-10 + cxxstd: "11,14,17,20" + os: ubuntu-20.04 + install: + - clang-10 + - toolset: clang + compiler: clang++-11 + cxxstd: "11,14,17,20" + os: ubuntu-22.04 + install: + - clang-11 + - toolset: clang + compiler: clang++-12 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-12 + - g++-11 + gcc_toolchain: 11 + - toolset: clang + compiler: clang++-13 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-13 + - g++-11 + gcc_toolchain: 11 + - toolset: clang + compiler: clang++-14 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-14 + - g++-11 + gcc_toolchain: 11 + - toolset: clang + compiler: clang++-15 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-15 + - g++-11 + gcc_toolchain: 11 + - toolset: clang + compiler: clang++-15 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-15 + - libc++-15-dev + - libc++abi-15-dev + cxxflags: -stdlib=libc++ + linkflags: -stdlib=libc++ + - toolset: clang + compiler: clang++-16 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-16 + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + - toolset: clang + compiler: clang++-16 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-16 + - libc++-16-dev + - libc++abi-16-dev + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + cxxflags: -stdlib=libc++ + linkflags: -stdlib=libc++ + - name: UBSAN + toolset: clang + compiler: clang++-15 + cxxstd: "11,14,17,20,2b" + cxxflags: -stdlib=libc++ + linkflags: -stdlib=libc++ + ubsan: 1 + build_variant: debug + os: ubuntu-22.04 + install: + - clang-15 + - libc++-15-dev + - libc++abi-15-dev + + - toolset: clang + cxxstd: "11,14,17,2a" + os: macos-11 + + - name: CMake tests + cmake_tests: 1 + os: ubuntu-20.04 + + timeout-minutes: 60 + runs-on: ${{matrix.os}} + container: ${{matrix.container}} + + steps: + - name: Setup environment + run: | + if [ -f "/etc/debian_version" ] + then + echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV + export DEBIAN_FRONTEND=noninteractive + fi + if [ -n "${{matrix.container}}" ] + then + echo "GHA_CONTAINER=${{matrix.container}}" >> $GITHUB_ENV + if [ -f "/etc/debian_version" ] + then + apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + if [ "$(apt-cache search "^python-is-python3$" | wc -l)" -ne 0 ] + then + PYTHON_PACKAGE="python-is-python3" + else + PYTHON_PACKAGE="python" + fi + apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common tzdata wget curl apt-transport-https ca-certificates make build-essential g++ $PYTHON_PACKAGE python3 perl git cmake + fi + fi + git config --global pack.threads 0 + + - uses: actions/checkout@v3 + + - name: Install packages + if: matrix.install + run: | + declare -a SOURCE_KEYS SOURCES + if [ -n "${{join(matrix.source_keys, ' ')}}" ] + then + SOURCE_KEYS=("${{join(matrix.source_keys, '" "')}}") + fi + if [ -n "${{join(matrix.sources, ' ')}}" ] + then + SOURCES=("${{join(matrix.sources, '" "')}}") + fi + for key in "${SOURCE_KEYS[@]}" + do + for i in {1..$NET_RETRY_COUNT} + do + echo "Adding key: $key" + wget -O - "$key" | sudo apt-key add - && break || sleep 2 + done + done + if [ ${#SOURCES[@]} -gt 0 ] + then + APT_ADD_REPO_COMMON_ARGS=("-y") + APT_ADD_REPO_SUPPORTED_ARGS="$(apt-add-repository --help | perl -ne 'if (/^\s*-n/) { print "n"; } elsif (/^\s*-P/) { print "P"; } elsif (/^\s*-S/) { print "S"; } elsif (/^\s*-U/) { print "U"; }')" + if [ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*n*}" ] + then + APT_ADD_REPO_COMMON_ARGS+=("-n") + fi + APT_ADD_REPO_HAS_SOURCE_ARGS="$([ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*P*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*S*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*U*}" ] && echo 1 || echo 0)" + for source in "${SOURCES[@]}" + do + for i in {1..$NET_RETRY_COUNT} + do + APT_ADD_REPO_ARGS=("${APT_ADD_REPO_COMMON_ARGS[@]}") + if [ $APT_ADD_REPO_HAS_SOURCE_ARGS -ne 0 ] + then + case "$source" in + "ppa:"*) + APT_ADD_REPO_ARGS+=("-P") + ;; + "deb "*) + APT_ADD_REPO_ARGS+=("-S") + ;; + *) + APT_ADD_REPO_ARGS+=("-U") + ;; + esac + fi + APT_ADD_REPO_ARGS+=("$source") + echo "apt-add-repository ${APT_ADD_REPO_ARGS[@]}" + sudo -E apt-add-repository "${APT_ADD_REPO_ARGS[@]}" && break || sleep 2 + done + done + fi + sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y ${{join(matrix.install, ' ')}} + + - name: Setup GCC Toolchain + if: matrix.gcc_toolchain + run: | + GCC_TOOLCHAIN_ROOT="$HOME/gcc-toolchain" + echo "GCC_TOOLCHAIN_ROOT=\"$GCC_TOOLCHAIN_ROOT\"" >> $GITHUB_ENV + MULTIARCH_TRIPLET="$(dpkg-architecture -qDEB_HOST_MULTIARCH)" + mkdir -p "$GCC_TOOLCHAIN_ROOT" + ln -s /usr/include "$GCC_TOOLCHAIN_ROOT/include" + ln -s /usr/bin "$GCC_TOOLCHAIN_ROOT/bin" + mkdir -p "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET" + ln -s "/usr/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" = "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + BUILD_JOBS=$((nproc || sysctl -n hw.ncpu) 2> /dev/null) + echo "BUILD_JOBS=$BUILD_JOBS" >> $GITHUB_ENV + echo "CMAKE_BUILD_PARALLEL_LEVEL=$BUILD_JOBS" >> $GITHUB_ENV + DEPINST_ARGS=() + GIT_VERSION="$(git --version | sed -e 's/git version //')" + GIT_HAS_JOBS=1 + if [ -f "/etc/debian_version" ] + then + if $(dpkg --compare-versions "$GIT_VERSION" lt 2.8.0) + then + GIT_HAS_JOBS=0 + fi + else + declare -a GIT_VER=(${GIT_VERSION//./ }) + declare -a GIT_MIN_VER=(2 8 0) + for ((i=0; i<${#GIT_VER[@]}; i++)) + do + if [ -z "${GIT_MIN_VER[i]}" ] + then + GIT_MIN_VER[i]=0 + fi + if [ "${GIT_VER[i]}" -lt "${GIT_MIN_VER[i]}" ] + then + GIT_HAS_JOBS=0 + break + fi + done + fi + if [ "$GIT_HAS_JOBS" -ne 0 ] + then + DEPINST_ARGS+=("--git_args" "--jobs $GIT_FETCH_JOBS") + fi + cd .. + git clone -b "$BOOST_BRANCH" --depth 1 "https://github.com/boostorg/boost.git" "boost-root" + cd boost-root + mkdir -p libs/$LIBRARY + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + DEPINST_ARGS+=("$LIBRARY") + python tools/boostdep/depinst/depinst.py "${DEPINST_ARGS[@]}" + if [ -z "${{matrix.cmake_tests}}" ] + then + ./bootstrap.sh + ./b2 headers + if [ -n "${{matrix.compiler}}" -o -n "$GCC_TOOLCHAIN_ROOT" ] + then + echo -n "using ${{matrix.toolset}} : : ${{matrix.compiler}}" > ~/user-config.jam + if [ -n "$GCC_TOOLCHAIN_ROOT" ] + then + echo -n " : \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\" \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\"" >> ~/user-config.jam + fi + echo " ;" >> ~/user-config.jam + fi + fi + + - name: Run tests + if: matrix.cmake_tests == '' + run: | + cd ../boost-root + B2_ARGS=("-j" "$BUILD_JOBS" "toolset=${{matrix.toolset}}" "cxxstd=${{matrix.cxxstd}}") + if [ -n "${{matrix.build_variant}}" ] + then + B2_ARGS+=("variant=${{matrix.build_variant}}") + else + B2_ARGS+=("variant=$DEFAULT_BUILD_VARIANT") + fi + if [ -n "${{matrix.threading}}" ] + then + B2_ARGS+=("threading=${{matrix.threading}}") + fi + if [ -n "${{matrix.ubsan}}" ] + then + export UBSAN_OPTIONS="print_stacktrace=1" + B2_ARGS+=("cxxflags=-fsanitize=undefined -fno-sanitize-recover=undefined" "linkflags=-fsanitize=undefined -fuse-ld=gold" "define=UBSAN=1" "debug-symbols=on" "visibility=global") + fi + if [ -n "${{matrix.cxxflags}}" ] + then + B2_ARGS+=("cxxflags=${{matrix.cxxflags}}") + fi + if [ -n "${{matrix.linkflags}}" ] + then + B2_ARGS+=("linkflags=${{matrix.linkflags}}") + fi + B2_ARGS+=("libs/$LIBRARY/test") + ./b2 "${B2_ARGS[@]}" + + - name: Run CMake tests + if: matrix.cmake_tests + run: | + if [ -n "${{matrix.macosx_version_min}}" ] + then + export MACOSX_DEPLOYMENT_TARGET="${{matrix.macosx_version_min}}" + fi + cd ../boost-root + mkdir __build_static__ && cd __build_static__ + cmake ../libs/$LIBRARY/test/test_cmake + cmake --build . --target boost_${LIBRARY}_cmake_self_test -j $BUILD_JOBS + cd .. + mkdir __build_shared__ && cd __build_shared__ + cmake -DBUILD_SHARED_LIBS=On ../libs/$LIBRARY/test/test_cmake + cmake --build . --target boost_${LIBRARY}_cmake_self_test -j $BUILD_JOBS diff --git a/libs/iterator/CMakeLists.txt b/libs/iterator/CMakeLists.txt new file mode 100644 index 00000000..a0dcf847 --- /dev/null +++ b/libs/iterator/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright 2018 Peter Dimov +# Copyright 2018 Andrey Semashev +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.5...3.20) + +project(boost_iterator VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) + +add_library(boost_iterator INTERFACE) +add_library(Boost::iterator ALIAS boost_iterator) + +target_include_directories(boost_iterator INTERFACE include) + +target_link_libraries(boost_iterator + INTERFACE + Boost::assert + Boost::concept_check + Boost::config + Boost::core + Boost::detail + Boost::function_types + Boost::fusion + Boost::mpl + Boost::optional + Boost::smart_ptr + Boost::static_assert + Boost::type_traits + Boost::utility +) diff --git a/libs/iterator/README.md b/libs/iterator/README.md new file mode 100644 index 00000000..bba90465 --- /dev/null +++ b/libs/iterator/README.md @@ -0,0 +1,27 @@ +# Boost.Iterator + +Boost.Iterator, part of collection of the [Boost C++ Libraries](https://github.com/boostorg), provides tools for building and working with iterators in C++. The library also provides a number of iterator classes that can be used out of the box. + +### Directories + +* **doc** - Documentation sources +* **include** - Interface headers of Boost.Iterator +* **test** - Boost.Iterator unit tests +* **example** - Boost.Iterator usage examples + +### More information + +* [Documentation](https://boost.org/libs/iterator) +* [Report bugs](https://github.com/boostorg/iterator/issues/new). Be sure to mention Boost version, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well. +* Submit your patches as [pull requests](https://github.com/boostorg/iterator/compare) against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). + +### Build status + +Branch | GitHub Actions | AppVeyor | Test Matrix | Dependencies | +:-------------: | -------------- | -------- | ----------- | ------------ | +[`master`](https://github.com/boostorg/iterator/tree/master) | [![GitHub Actions](https://github.com/boostorg/iterator/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/boostorg/iterator/actions?query=branch%3Amaster) | [![AppVeyor](https://ci.appveyor.com/api/projects/status/ud8ug5aai8vd30hg/branch/master?svg=true)](https://ci.appveyor.com/project/Lastique/iterator/branch/master) | [![Tests](https://img.shields.io/badge/matrix-master-brightgreen.svg)](http://www.boost.org/development/tests/master/developer/iterator.html) | [![Dependencies](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/iterator.html) +[`develop`](https://github.com/boostorg/iterator/tree/develop) | [![GitHub Actions](https://github.com/boostorg/iterator/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/boostorg/iterator/actions?query=branch%3Adevelop) | [![AppVeyor](https://ci.appveyor.com/api/projects/status/ud8ug5aai8vd30hg/branch/develop?svg=true)](https://ci.appveyor.com/project/Lastique/iterator/branch/develop) | [![Tests](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](http://www.boost.org/development/tests/develop/developer/iterator.html) | [![Dependencies](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/iterator.html) + +### License + +Distributed under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). diff --git a/libs/iterator/appveyor.yml b/libs/iterator/appveyor.yml new file mode 100644 index 00000000..03d2535b --- /dev/null +++ b/libs/iterator/appveyor.yml @@ -0,0 +1,102 @@ +# Copyright 2017 Edward Diener +# Copyright 2019 Andrey Semashev +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +version: 1.0.{build}-{branch} + +shallow_clone: true + +branches: + only: + - master + - develop + - /feature\/.*/ + +environment: + matrix: + - TOOLSET: msvc-12.0 + ADDRMD: 32,64 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - TOOLSET: msvc-14.0 + CXXSTD: 14,latest + ADDRMD: 32,64 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - TOOLSET: msvc-14.1 + CXXSTD: 14,17,latest + ADDRMD: 32,64 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + - TOOLSET: msvc-14.2 + ADDRMD: 32,64 + CXXSTD: 14,17,20,latest + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + - TOOLSET: msvc-14.3 + ADDRMD: 32,64 + CXXSTD: 14,17,20,latest + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + - TOOLSET: clang-win + ADDRMD: 32,64 + CXXSTD: 14,17,latest + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + - TOOLSET: gcc + CXXSTD: 11,14,1z + ADDPATH: C:\cygwin\bin; + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - TOOLSET: gcc + CXXSTD: 11,14,1z + ADDPATH: C:\cygwin64\bin; + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - TOOLSET: gcc + CXXSTD: 11,14,1z + ADDPATH: C:\mingw\bin; + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - TOOLSET: gcc + CXXSTD: 11,14,1z + ADDPATH: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin; + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - TOOLSET: gcc + CXXSTD: 11,14,1z + ADDPATH: C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev0\mingw64\bin; + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - TEST_CMAKE: 1 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + +install: + - set GIT_FETCH_JOBS=8 + - set BOOST_BRANCH=develop + - if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master + - cd .. + - git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + - cd boost-root + - git submodule init tools/build + - git submodule init tools/boostdep + - git submodule init tools/boost_install + - git submodule init libs/headers + - git submodule init libs/config + - git submodule update --jobs %GIT_FETCH_JOBS% + - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\iterator + - python tools/boostdep/depinst/depinst.py --git_args "--jobs %GIT_FETCH_JOBS%" iterator + - cmd /c bootstrap + - b2 -d0 headers + +build: off + +test_script: + - PATH=%ADDPATH%%PATH% + - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% + - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% + - b2 -j %NUMBER_OF_PROCESSORS% libs/iterator/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% + +for: + - matrix: + only: [TEST_CMAKE: 1] + test_script: + - mkdir __build_static__ + - cd __build_static__ + - cmake ../libs/iterator/test/test_cmake + - cmake --build . --target boost_iterator_cmake_self_test -j %NUMBER_OF_PROCESSORS% + - cd .. + - mkdir __build_shared__ + - cd __build_shared__ + - cmake -DBUILD_SHARED_LIBS=On ../libs/iterator/test/test_cmake + - cmake --build . --target boost_iterator_cmake_self_test -j %NUMBER_OF_PROCESSORS% diff --git a/libs/iterator/doc/BidirectionalTraversal.html b/libs/iterator/doc/BidirectionalTraversal.html new file mode 100644 index 00000000..9c45f400 --- /dev/null +++ b/libs/iterator/doc/BidirectionalTraversal.html @@ -0,0 +1,76 @@ + + + + + + +Bidirectional Traversal Concept + + + +
+

Bidirectional Traversal Concept

+ + + + +

A class or built-in type X models the Bidirectional Traversal +concept if, in addition to X meeting the requirements of Forward +Traversal Iterator, the following expressions are valid and respect +the stated semantics.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal +Iterator)
ExpressionReturn TypeAssertion/Semantics / +Pre-/Post-condition
--rX&pre: there exists +s such that r +== ++s. post: +s is +dereferenceable. +--(++r) == r. +--r == --s +implies r == +s. &r == &--r.
r--convertible to const X&
+{
+  X tmp = r;
+  --r;
+  return tmp;
+}
+
+
iterator_traversal<X>::typeConvertible to +bidirectional_traversal_tag 
+
+ + + diff --git a/libs/iterator/doc/BidirectionalTraversal.rst b/libs/iterator/doc/BidirectionalTraversal.rst new file mode 100644 index 00000000..a62b8bd9 --- /dev/null +++ b/libs/iterator/doc/BidirectionalTraversal.rst @@ -0,0 +1,41 @@ +.. Copyright David Abrahams 2006. 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) + +Bidirectional Traversal Concept +............................... + +A class or built-in type ``X`` models the *Bidirectional Traversal* +concept if, in addition to ``X`` meeting the requirements of Forward +Traversal Iterator, the following expressions are valid and respect +the stated semantics. + ++--------------------------------------------------------------------------------------+ +|Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal | +|Iterator) | ++--------------------------------+-------------------------------+---------------------+ +|Expression |Return Type |Assertion/Semantics /| +| | |Pre-/Post-condition | ++================================+===============================+=====================+ +|``--r`` |``X&`` |pre: there exists | +| | |``s`` such that ``r | +| | |== ++s``. post: | +| | |``s`` is | +| | |dereferenceable. | +| | |``--(++r) == r``. | +| | |``--r == --s`` | +| | |implies ``r == | +| | |s``. ``&r == &--r``. | ++--------------------------------+-------------------------------+---------------------+ +|``r--`` |convertible to ``const X&`` |:: | +| | | | +| | | { | +| | | X tmp = r; | +| | | --r; | +| | | return tmp; | +| | | } | ++--------------------------------+-------------------------------+---------------------+ +|``iterator_traversal::type`` |Convertible to | | +| |``bidirectional_traversal_tag``| | +| | | | ++--------------------------------+-------------------------------+---------------------+ diff --git a/libs/iterator/doc/ForwardTraversal.html b/libs/iterator/doc/ForwardTraversal.html new file mode 100644 index 00000000..702064dd --- /dev/null +++ b/libs/iterator/doc/ForwardTraversal.html @@ -0,0 +1,67 @@ + + + + + + +Forward Traversal Concept + + + +
+

Forward Traversal Concept

+ + + + +

A class or built-in type X models the Forward Traversal +concept if, in addition to X meeting the requirements of Default +Constructible and Single Pass Iterator, the following expressions are +valid and respect the stated semantics.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Forward Traversal Iterator Requirements (in addition to Default Constructible and Single Pass Iterator)
ExpressionReturn TypeAssertion/Note
X u;X&note: u may have a +singular value.
++rX&r == s and r is +dereferenceable implies +++r == ++s.
iterator_traits<X>::difference_typeA signed integral type representing +the distance between iterators 
iterator_traversal<X>::typeConvertible to +forward_traversal_tag 
+
+ + + diff --git a/libs/iterator/doc/ForwardTraversal.rst b/libs/iterator/doc/ForwardTraversal.rst new file mode 100644 index 00000000..80dd9c7c --- /dev/null +++ b/libs/iterator/doc/ForwardTraversal.rst @@ -0,0 +1,31 @@ +.. Copyright David Abrahams 2006. 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) + +Forward Traversal Concept +......................... + +A class or built-in type ``X`` models the *Forward Traversal* +concept if, in addition to ``X`` meeting the requirements of Default +Constructible and Single Pass Iterator, the following expressions are +valid and respect the stated semantics. + ++--------------------------------------------------------------------------------------------------------+ +|Forward Traversal Iterator Requirements (in addition to Default Constructible and Single Pass Iterator) | ++---------------------------------------+-----------------------------------+----------------------------+ +|Expression |Return Type |Assertion/Note | ++=======================================+===================================+============================+ +|``X u;`` |``X&`` |note: ``u`` may have a | +| | |singular value. | ++---------------------------------------+-----------------------------------+----------------------------+ +|``++r`` |``X&`` |``r == s`` and ``r`` is | +| | |dereferenceable implies | +| | |``++r == ++s.`` | ++---------------------------------------+-----------------------------------+----------------------------+ +|``iterator_traits::difference_type``|A signed integral type representing| | +| |the distance between iterators | | +| | | | ++---------------------------------------+-----------------------------------+----------------------------+ +|``iterator_traversal::type`` |Convertible to | | +| |``forward_traversal_tag`` | | ++---------------------------------------+-----------------------------------+----------------------------+ diff --git a/libs/iterator/doc/GNUmakefile b/libs/iterator/doc/GNUmakefile new file mode 100644 index 00000000..85917f78 --- /dev/null +++ b/libs/iterator/doc/GNUmakefile @@ -0,0 +1,15 @@ +# Copyright David Abrahams 2004. 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) + +ECHO = /bin/echo + +all: + @${ECHO} "/libs/iterator/doc/GNUmakefile should be replaced by" + @${ECHO} + @${ECHO} " http://www.boost-consulting.com/writing/GNUmakefile," + @${ECHO} + @${ECHO} "before proceeding. That file is not included in the Boost" + @${ECHO} "distribution because it is licensed under the GPL, which violates" + @${ECHO} "Boost license requirements." + diff --git a/libs/iterator/doc/IncrementableIterator.html b/libs/iterator/doc/IncrementableIterator.html new file mode 100644 index 00000000..ae47b99e --- /dev/null +++ b/libs/iterator/doc/IncrementableIterator.html @@ -0,0 +1,66 @@ + + + + + + +Incrementable Iterator Concept + + + +
+

Incrementable Iterator Concept

+ + + + +

A class or built-in type X models the Incrementable Iterator +concept if, in addition to X being Assignable and Copy +Constructible, the following expressions are valid and respect the +stated semantics.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible)
ExpressionReturn TypeAssertion/Semantics
++rX&&r == &++r
r++X
+{
+   X tmp = r;
+   ++r;
+   return tmp;
+}
+
+
iterator_traversal<X>::typeConvertible to +incrementable_traversal_tag 
+
+ + + diff --git a/libs/iterator/doc/IncrementableIterator.rst b/libs/iterator/doc/IncrementableIterator.rst new file mode 100644 index 00000000..a1f92ec1 --- /dev/null +++ b/libs/iterator/doc/IncrementableIterator.rst @@ -0,0 +1,32 @@ +.. Copyright David Abrahams 2006. 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) + +Incrementable Iterator Concept +.............................. + +A class or built-in type ``X`` models the *Incrementable Iterator* +concept if, in addition to ``X`` being Assignable and Copy +Constructible, the following expressions are valid and respect the +stated semantics. + + ++-------------------------------------------------------------------------------------+ +|Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible) | +| | ++--------------------------------+-------------------------------+--------------------+ +|Expression |Return Type |Assertion/Semantics | ++================================+===============================+====================+ +|``++r`` |``X&`` |``&r == &++r`` | ++--------------------------------+-------------------------------+--------------------+ +|``r++`` |``X`` |:: | +| | | | +| | | { | +| | | X tmp = r; | +| | | ++r; | +| | | return tmp; | +| | | } | ++--------------------------------+-------------------------------+--------------------+ +|``iterator_traversal::type`` |Convertible to | | +| |``incrementable_traversal_tag``| | ++--------------------------------+-------------------------------+--------------------+ diff --git a/libs/iterator/doc/InteroperableIterator.rst b/libs/iterator/doc/InteroperableIterator.rst new file mode 100644 index 00000000..3632ff24 --- /dev/null +++ b/libs/iterator/doc/InteroperableIterator.rst @@ -0,0 +1,61 @@ +.. Copyright David Abrahams 2006. 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) + +Interoperable Iterator Concept +.............................. + +A class or built-in type ``X`` that models Single Pass Iterator is +*interoperable with* a class or built-in type ``Y`` that also models +Single Pass Iterator if the following expressions are valid and +respect the stated semantics. In the tables below, ``x`` is an object +of type ``X``, ``y`` is an object of type ``Y``, ``Distance`` is +``iterator_traits::difference_type``, and ``n`` represents a +constant object of type ``Distance``. + ++-----------+-----------------------+---------------------------------------------------+ +|Expression |Return Type |Assertion/Precondition/Postcondition | ++===========+=======================+===================================================+ +|``y = x`` |``Y`` |post: ``y == x`` | ++-----------+-----------------------+---------------------------------------------------+ +|``Y(x)`` |``Y`` |post: ``Y(x) == x`` | ++-----------+-----------------------+---------------------------------------------------+ +|``x == y`` |convertible to ``bool``|``==`` is an equivalence relation over its domain. | ++-----------+-----------------------+---------------------------------------------------+ +|``y == x`` |convertible to ``bool``|``==`` is an equivalence relation over its domain. | ++-----------+-----------------------+---------------------------------------------------+ +|``x != y`` |convertible to ``bool``|``bool(a==b) != bool(a!=b)`` over its domain. | ++-----------+-----------------------+---------------------------------------------------+ +|``y != x`` |convertible to ``bool``|``bool(a==b) != bool(a!=b)`` over its domain. | ++-----------+-----------------------+---------------------------------------------------+ + +If ``X`` and ``Y`` both model Random Access Traversal Iterator then +the following additional requirements must be met. + ++-----------+-----------------------+---------------------+--------------------------------------+ +|Expression |Return Type |Operational Semantics|Assertion/ Precondition | ++===========+=======================+=====================+======================================+ +|``x < y`` |convertible to ``bool``|``y - x > 0`` |``<`` is a total ordering relation | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``y < x`` |convertible to ``bool``|``x - y > 0`` |``<`` is a total ordering relation | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``x > y`` |convertible to ``bool``|``y < x`` |``>`` is a total ordering relation | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``y > x`` |convertible to ``bool``|``x < y`` |``>`` is a total ordering relation | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``x >= y`` |convertible to ``bool``|``!(x < y)`` | | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``y >= x`` |convertible to ``bool``|``!(y < x)`` | | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``x <= y`` |convertible to ``bool``|``!(x > y)`` | | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``y <= x`` |convertible to ``bool``|``!(y > x)`` | | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``y - x`` |``Distance`` |``distance(Y(x),y)`` |pre: there exists a value ``n`` of | +| | | |``Distance`` such that ``x + n == y``.| +| | | |``y == x + (y - x)``. | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``x - y`` |``Distance`` |``distance(y,Y(x))`` |pre: there exists a value ``n`` of | +| | | |``Distance`` such that ``y + n == x``.| +| | | |``x == y + (x - y)``. | ++-----------+-----------------------+---------------------+--------------------------------------+ diff --git a/libs/iterator/doc/Jamfile.v2 b/libs/iterator/doc/Jamfile.v2 new file mode 100644 index 00000000..c75d268f --- /dev/null +++ b/libs/iterator/doc/Jamfile.v2 @@ -0,0 +1,27 @@ +# Copyright Thomas Witt 2005. Use, modification, and distribution are +# subject to 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) + +using quickbook ; + +xml iterator + : + quickbook/iterator.qbk + ; + +boostbook standalone + : + iterator + : + "boost.root=../../../.." + toc.max.depth=3 + toc.section.depth=3 + chunk.section.depth=2 + pdf:"boost.url.prefix=http://www.boost.org/doc/libs/release/libs/iterator/doc/html" + ; + +############################################################################### +alias boostdoc ; +explicit boostdoc ; +alias boostrelease : standalone ; +explicit boostrelease ; diff --git a/libs/iterator/doc/LvalueIterator.html b/libs/iterator/doc/LvalueIterator.html new file mode 100644 index 00000000..c20626c1 --- /dev/null +++ b/libs/iterator/doc/LvalueIterator.html @@ -0,0 +1,56 @@ + + + + + + +Lvalue Iterator Concept + + + +
+

Lvalue Iterator Concept

+ + + + +

The Lvalue Iterator concept adds the requirement that the return +type of operator* type be a reference to the value type of the +iterator.

+ +++++ + + + + + + + + + + + + + + +
Lvalue Iterator Requirements
ExpressionReturn TypeNote/Assertion
*aT&T is cv +iterator_traits<X>::value_type +where cv is an optional +cv-qualification. +pre: a is +dereferenceable. If a +== b then *a is +equivalent to *b.
+
+ + + diff --git a/libs/iterator/doc/LvalueIterator.rst b/libs/iterator/doc/LvalueIterator.rst new file mode 100644 index 00000000..39c26729 --- /dev/null +++ b/libs/iterator/doc/LvalueIterator.rst @@ -0,0 +1,25 @@ +.. Copyright David Abrahams 2006. 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) + +Lvalue Iterator Concept +....................... + +The *Lvalue Iterator* concept adds the requirement that the return +type of ``operator*`` type be a reference to the value type of the +iterator. + ++-------------------------------------------------------------+ +| Lvalue Iterator Requirements | ++-------------+-----------+-----------------------------------+ +|Expression |Return Type|Note/Assertion | ++=============+===========+===================================+ +|``*a`` | ``T&`` |``T`` is *cv* | +| | |``iterator_traits::value_type`` | +| | |where *cv* is an optional | +| | |cv-qualification. | +| | |pre: ``a`` is | +| | |dereferenceable. If ``a | +| | |== b`` then ``*a`` is | +| | |equivalent to ``*b``. | ++-------------+-----------+-----------------------------------+ diff --git a/libs/iterator/doc/RandomAccessTraversal.html b/libs/iterator/doc/RandomAccessTraversal.html new file mode 100644 index 00000000..4c681a6f --- /dev/null +++ b/libs/iterator/doc/RandomAccessTraversal.html @@ -0,0 +1,134 @@ + + + + + + +Random Access Traversal Concept + + + +
+

Random Access Traversal Concept

+ + + + +

A class or built-in type X models the Random Access Traversal +concept if the following expressions are valid and respect the stated +semantics. In the table below, Distance is +iterator_traits<X>::difference_type and n represents a +constant object of type Distance.

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal)
ExpressionReturn TypeOperational SemanticsAssertion/ +Precondition
r += nX&
+{
+  Distance m = n;
+  if (m >= 0)
+    while (m--)
+      ++r;
+  else
+    while (m++)
+      --r;
+  return r;
+}
+
+
 
a + n, n + aX{ X tmp = a; return tmp ++= n; } 
r -= nX&return r += -n 
a - nX{ X tmp = a; return tmp +-= n; } 
b - aDistancea < b ?  distance(a,b) +: -distance(b,a)pre: there exists a +value n of +Distance such that +a + n == b. b +== a + (b - a).
a[n]convertible to T*(a + n)pre: a is a Readable +Iterator
a[n] = vconvertible to T*(a + n) = vpre: a is a Writable +iterator
a < bconvertible to boolb - a > 0< is a total +ordering relation
a > bconvertible to boolb < a> is a total +ordering relation
a >= bconvertible to bool!(a < b) 
a <= bconvertible to bool!(a > b) 
iterator_traversal<X>::typeConvertible to +random_access_traversal_tag  
+
+ + + diff --git a/libs/iterator/doc/RandomAccessTraversal.rst b/libs/iterator/doc/RandomAccessTraversal.rst new file mode 100644 index 00000000..490faf6f --- /dev/null +++ b/libs/iterator/doc/RandomAccessTraversal.rst @@ -0,0 +1,67 @@ +.. Copyright David Abrahams 2006. 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) + +Random Access Traversal Concept +............................... + +A class or built-in type ``X`` models the *Random Access Traversal* +concept if the following expressions are valid and respect the stated +semantics. In the table below, ``Distance`` is +``iterator_traits::difference_type`` and ``n`` represents a +constant object of type ``Distance``. + ++------------------------------------------------------------------------------------------------------------------+ +|Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal) | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|Expression |Return Type |Operational Semantics |Assertion/ | +| | | |Precondition | ++===============================+=================================+=========================+======================+ +|``r += n`` |``X&`` |:: | | +| | | | | +| | | { | | +| | | Distance m = n; | | +| | | if (m >= 0) | | +| | | while (m--) | | +| | | ++r; | | +| | | else | | +| | | while (m++) | | +| | | --r; | | +| | | return r; | | +| | | } | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a + n``, ``n + a`` |``X`` |``{ X tmp = a; return tmp| | +| | |+= n; }`` | | +| | | | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``r -= n`` |``X&`` |``return r += -n`` | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a - n`` |``X`` |``{ X tmp = a; return tmp| | +| | |-= n; }`` | | +| | | | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``b - a`` |``Distance`` |``a < b ? distance(a,b) |pre: there exists a | +| | |: -distance(b,a)`` |value ``n`` of | +| | | |``Distance`` such that| +| | | |``a + n == b``. ``b | +| | | |== a + (b - a)``. | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a[n]`` |convertible to T |``*(a + n)`` |pre: a is a *Readable | +| | | |Iterator* | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a[n] = v`` |convertible to T |``*(a + n) = v`` |pre: a is a *Writable | +| | | |iterator* | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a < b`` |convertible to ``bool`` |``b - a > 0`` |``<`` is a total | +| | | |ordering relation | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a > b`` |convertible to ``bool`` |``b < a`` |``>`` is a total | +| | | |ordering relation | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a >= b`` |convertible to ``bool`` |``!(a < b)`` | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a <= b`` |convertible to ``bool`` |``!(a > b)`` | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``iterator_traversal::type``|Convertible to | | | +| |``random_access_traversal_tag`` | | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ diff --git a/libs/iterator/doc/ReadableIterator.html b/libs/iterator/doc/ReadableIterator.html new file mode 100644 index 00000000..04be0217 --- /dev/null +++ b/libs/iterator/doc/ReadableIterator.html @@ -0,0 +1,64 @@ + + + + + + +Readable Iterator Concept + + + +
+

Readable Iterator Concept

+ + + + +

A class or built-in type X models the Readable Iterator concept +for value type T if, in addition to X being Assignable and +Copy Constructible, the following expressions are valid and respect +the stated semantics. U is the type of any specified member of +type T.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
Readable Iterator Requirements (in addition to Assignable and Copy Constructible)
ExpressionReturn TypeNote/Precondition
iterator_traits<X>::value_typeTAny non-reference, +non-cv-qualified type
*aConvertible to T
+
pre: a is dereferenceable. If a == b then *a
+
is equivalent to *b.
+
+
a->mU&pre: pre: (*a).m is well-defined. Equivalent to (*a).m.
+
+ + + diff --git a/libs/iterator/doc/ReadableIterator.rst b/libs/iterator/doc/ReadableIterator.rst new file mode 100644 index 00000000..27f79f85 --- /dev/null +++ b/libs/iterator/doc/ReadableIterator.rst @@ -0,0 +1,26 @@ +.. Copyright David Abrahams 2006. 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) + +Readable Iterator Concept +......................... + +A class or built-in type ``X`` models the *Readable Iterator* concept +for value type ``T`` if, in addition to ``X`` being Assignable and +Copy Constructible, the following expressions are valid and respect +the stated semantics. ``U`` is the type of any specified member of +type ``T``. + ++-----------------------------------------------------------------------------------------------------------------------------+ +|Readable Iterator Requirements (in addition to Assignable and Copy Constructible) | ++-----------------------------------+------------------------+----------------------------------------------------------------+ +|Expression |Return Type |Note/Precondition | ++===================================+========================+================================================================+ +|``iterator_traits::value_type`` |``T`` |Any non-reference, | +| | |non-cv-qualified type | ++-----------------------------------+------------------------+----------------------------------------------------------------+ +|``*a`` | Convertible to ``T`` |pre: ``a`` is dereferenceable. If ``a == b`` then ``*a`` | +| | | is equivalent to ``*b``. | ++-----------------------------------+------------------------+----------------------------------------------------------------+ +|``a->m`` |``U&`` |pre: ``pre: (*a).m`` is well-defined. Equivalent to ``(*a).m``. | ++-----------------------------------+------------------------+----------------------------------------------------------------+ diff --git a/libs/iterator/doc/SinglePassIterator.html b/libs/iterator/doc/SinglePassIterator.html new file mode 100644 index 00000000..bc2835d5 --- /dev/null +++ b/libs/iterator/doc/SinglePassIterator.html @@ -0,0 +1,68 @@ + + + + + + +Single Pass Iterator Concept + + + +
+

Single Pass Iterator Concept

+ + + + +

A class or built-in type X models the Single Pass Iterator +concept if the following expressions are valid and respect the stated +semantics.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality +Comparable)
ExpressionReturn TypeAssertion/Semantics / +Pre-/Post-condition
++rX&pre: r is +dereferenceable; post: +r is dereferenceable or +r is past-the-end
a == bconvertible to bool== is an equivalence +relation over its domain
a != bconvertible to bool!(a == b)
iterator_traversal<X>::typeConvertible to +single_pass_traversal_tag 
+
+ + + diff --git a/libs/iterator/doc/SinglePassIterator.rst b/libs/iterator/doc/SinglePassIterator.rst new file mode 100644 index 00000000..eaa50e0a --- /dev/null +++ b/libs/iterator/doc/SinglePassIterator.rst @@ -0,0 +1,32 @@ +.. Copyright David Abrahams 2006. 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) + +Single Pass Iterator Concept +............................ + +A class or built-in type ``X`` models the *Single Pass Iterator* +concept if the following expressions are valid and respect the stated +semantics. + + ++------------------------------------------------------------------------------------------+ +|Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality | +|Comparable) | ++--------------------------------+-----------------------------+---------------------------+ +|Expression |Return Type |Assertion/Semantics / | +| | |Pre-/Post-condition | ++================================+=============================+===========================+ +|``++r`` |``X&`` |pre: ``r`` is | +| | |dereferenceable; post: | +| | |``r`` is dereferenceable or| +| | |``r`` is past-the-end | ++--------------------------------+-----------------------------+---------------------------+ +|``a == b`` |convertible to ``bool`` |``==`` is an equivalence | +| | |relation over its domain | ++--------------------------------+-----------------------------+---------------------------+ +|``a != b`` |convertible to ``bool`` |``!(a == b)`` | ++--------------------------------+-----------------------------+---------------------------+ +|``iterator_traversal::type`` |Convertible to | | +| |``single_pass_traversal_tag``| | ++--------------------------------+-----------------------------+---------------------------+ diff --git a/libs/iterator/doc/SwappableIterator.html b/libs/iterator/doc/SwappableIterator.html new file mode 100644 index 00000000..e3c1eaeb --- /dev/null +++ b/libs/iterator/doc/SwappableIterator.html @@ -0,0 +1,54 @@ + + + + + + +Swappable Iterator Concept + + + +
+

Swappable Iterator Concept

+ + + + +

A class or built-in type X models the Swappable Iterator concept +if, in addition to X being Copy Constructible, the following +expressions are valid and respect the stated semantics.

+ +++++ + + + + + + + + + + + + + + +
Swappable Iterator Requirements (in addition to Copy Constructible)
ExpressionReturn TypePostcondition
iter_swap(a, b)voidthe pointed to values are +exchanged
+
+
[Note: An iterator that is a model of the Readable and Writable Iterator concepts
+
is also a model of Swappable Iterator. --end note]
+
+
+ + + diff --git a/libs/iterator/doc/SwappableIterator.rst b/libs/iterator/doc/SwappableIterator.rst new file mode 100644 index 00000000..55554e7e --- /dev/null +++ b/libs/iterator/doc/SwappableIterator.rst @@ -0,0 +1,23 @@ +.. Copyright David Abrahams 2006. 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) + +Swappable Iterator Concept +.......................... + +A class or built-in type ``X`` models the *Swappable Iterator* concept +if, in addition to ``X`` being Copy Constructible, the following +expressions are valid and respect the stated semantics. + ++---------------------------------------------------------------------+ +|Swappable Iterator Requirements (in addition to Copy Constructible) | ++-------------------------+-------------+-----------------------------+ +|Expression |Return Type |Postcondition | ++=========================+=============+=============================+ +|``iter_swap(a, b)`` |``void`` |the pointed to values are | +| | |exchanged | ++-------------------------+-------------+-----------------------------+ + +[*Note:* An iterator that is a model of the *Readable* and *Writable Iterator* concepts + is also a model of *Swappable Iterator*. *--end note*] + diff --git a/libs/iterator/doc/WritableIterator.html b/libs/iterator/doc/WritableIterator.html new file mode 100644 index 00000000..72474745 --- /dev/null +++ b/libs/iterator/doc/WritableIterator.html @@ -0,0 +1,52 @@ + + + + + + +Writable Iterator Concept + + + +
+

Writable Iterator Concept

+ + + + +

A class or built-in type X models the Writable Iterator concept +if, in addition to X being Copy Constructible, the following +expressions are valid and respect the stated semantics. Writable +Iterators have an associated set of value types.

+ +++++ + + + + + + + + + + + + + + +
Writable Iterator Requirements (in addition to Copy Constructible)
ExpressionReturn TypePrecondition
*a = o pre: The type of o +is in the set of +value types of X
+
+ + + diff --git a/libs/iterator/doc/WritableIterator.rst b/libs/iterator/doc/WritableIterator.rst new file mode 100644 index 00000000..49b6e160 --- /dev/null +++ b/libs/iterator/doc/WritableIterator.rst @@ -0,0 +1,21 @@ +.. Copyright David Abrahams 2006. 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) + +Writable Iterator Concept +......................... + +A class or built-in type ``X`` models the *Writable Iterator* concept +if, in addition to ``X`` being Copy Constructible, the following +expressions are valid and respect the stated semantics. Writable +Iterators have an associated *set of value types*. + ++---------------------------------------------------------------------+ +|Writable Iterator Requirements (in addition to Copy Constructible) | ++-------------------------+--------------+----------------------------+ +|Expression |Return Type |Precondition | ++=========================+==============+============================+ +|``*a = o`` | | pre: The type of ``o`` | +| | | is in the set of | +| | | value types of ``X`` | ++-------------------------+--------------+----------------------------+ diff --git a/libs/iterator/doc/access.png b/libs/iterator/doc/access.png new file mode 100644 index 0000000000000000000000000000000000000000..80011dcc7c82a35cbc173b314a9e247db0bf3f8c GIT binary patch literal 11127 zcmbWd2{e`O`!D>YutV7>MCP#&Au`WHkug)5w<$vunWxxhB?%#fOpzf&h7dA^keST$ zoO$M4{=awq&%4e!>%42d*81-HZoBN=mqVOjn*eseKKhW3S zAKcF1{=dIW<(+)|_|fjvd~LL> zp3$bg&&l-@A4J_WR8>2Eo&AI=vmWm4eGqYZ>eP4t{(S;M!l2{ec8g>QA44rIt+F>Q zX0vm1Qx0WacLcqE{`@H`CzoP}n$R)wijI#Dbsn@WO-?qFk@0spo@$DSjgCHtz@^44 zH)mR7@h@MeeCT?5ay&mje|yU_ltC!3kC2eC#q7DHr0>V+ot5G3?QN^W{mnTdJQ)Rr zroKM%Xoqrr)+jw49ZP%r{Pgqy0%~gN&5ez%t*!UU8PU;KZ|3IZS@2L^A!z97xf0Pd zH#e6M7gy!FKAB&0!pp-Wi5IX$Y^Q|1LQXCqAnUc7kWPmpg^lb4?_@pO)1C)|Fl z!;F`Uiwn0Be#OGVl9ZH$_|kdr)%Nz@VPe9pPc|IxuHhqa=kN@{!6-a`6Em}|$p%8? z$Ct<7$ZzSpt_+o=E5!x|1Tfs86MAko)%YqsJ)K(c>Cr?G9fAHmri;Ii9to}{u zvg*$_!k1p88;Y@Fh*Z?SMS&m;qV8Ms6)%=_Imr>LIAwu^#H6I( zriI_Xe@9)YgNw|z#c4izM1YJxFNdG?^>v&EK1w1brPj8#w$@ng8t-GOs|3~OP$nuW zD*F0=J2}iAoo^zuw_n30B=1~s5>8y5oRnsbvj1Cljv@E+XI@_3#ib>G^k|ib%g*v3 zx-K_2H%BKw_58~6GAS9Ehr7E)d;IqDARlU?J5%)>($LUgD{z=#Up=w8kFMjh{GDr1 zNiIDGf&CaPvP67;{E)eKnIG|S%~78Vy5=jRaw8xXKE{EaxM{x&7i zjT_m2{%E+lxk*S!*x1;Rk&!)k(9T`GSJ&FQ)FE-YwY$5!zJ3mwo|}{KI(R4}lU7!C zS3m$3q{LI)$iP61jm@$#{2Cq}-q){RQ&Li9XJ<22lkt$F&E(Ugm2YFq%geHdmy}5x z)sOA$?6{4p|5kfd8uNyFH=RSCJbBX9)m2eZk)>~FnABjZp55bhxPyz2zq`HtMYm8| zL17N|lS4aK@&zm>Cnu-F-M_Q#2@F^fm(`yBewXLZ;hLXeVdv+0`1xh;*pF4y(9pCS z^K?d>be1-*y;BJO{#`V-^?|BtY;3HHgF|y`E2dBvp7p_l2a4Uwtec%FGR<17Q6b)A z@0Di(CTblcJL5IMa4IY%+Qd~aCUaba4%$RDtARh><0?YA!_>i->rLZ zMkXDbnI3s-d!HV=zynT@vaw}CJ+1G1vaqC&c^_Vq)-^J+x3xXmTc2ufRumKzL@^|^ z19r%tKQAcw4f=P(^?ODJtAW9Yudnaytc57;SZ^;b!_jPlJu@>iv_|SnaIfn#Ke#%szd|_`=WQYx9=$_ z73p%KOk7;Py?fVF>9Tf{g9C7v0SjvtA0IDqyrp^X-aT(`@tZ`1gu`Xen0O7fwdGUP zU`ywn4gv@%G&D4di;Fh`tnBQr4#uhS!dBMS)&fY?u@qT$oUAv|Fd7D_L^H*{AzBVUs#BXkN;y;oFHf~je4N03Bb>`GU6_vT_RNAbv?KYjwj z!osj{UDtIap+A27K(KEbOt*J-QtMV%SD}PSN?9J!ihH7v=H_O}N-r-j#21hxbp+sA zN`aP&3P6sKLHWUh=-AjAhl#p^5$x;NmlIWBQMA<5{_XD0t-H3jx63j{cFYkI5pn8$ zm4zwtRInQdwW?pIKrBygs!Uq27C~5M366EzF1pZXGvo) zOd+z2Q7!(LvFN^@9w^^7fUMNSq`$_CP4BCX)t^#!Qz#!(cE@ICpENc$uC6{+_qcs$ z!r|_>rz0EN+s9kosvSvUhtOjeosEh7-5M}|jWjj8J3Ggxr}^s+dV70gVq%^@f1Z(% z0n@?4!s6jgEg2b%e&Pq#y}dof`}YC4V8TN$?7|J*xN(E5PdK5yud~y*XwX&EP|bCB zbp)sc04lKn+aD1XrkTpM>cgYW4vG0U@7`V6!i7S-!Ojj#2z>`5Wu(%@sLH*hxcJHl z-&KXw)KuACCwY0i==)dy`l=`^J2^NQ7wXOz(qIeV=j&He>E^jjK3?9=SbZ(6tJKto zd+V6u;h~{Nj~)$mcA_aLngAMJnwy&gy6^Ar-@bht=z$+OK8?rei5Jx?Z7r=AfZsvH zbg9BkuW1eedApneDfIO}jHlHo5cPD-ZE8Jyh`JyRHH}ZRH{voz5+dsq+4}1jDe3}g zNU`nU*Wln_m@rZu=$`@5)BtemV)2=Qg0^E|U_jRa)Ig(n9V}#?9`x5t&&=45RN$UXpOVs2=xT%V=jrkB zkAM&yzV3w{DK7rhy#TXretqV%R*oqK!+-@ehN4XnuzMRBd69_dC^?e}ZxJXNW2B-i z4^-=SOEGAjqJzYo(7;FJ$?-HYToNy`RM3q^Ekj0u#BHhPlvA*Tvd9mqu zLHi_>*SN#oxVSiW`uu_dbk(!I?rw~&?HNWq9jO3Pl&@QeBRw!Smi+$x{L<243tKY# z&6`QWF9@Ww^74|BlOvRAL|q+VGlhhN>MTFy=bw((`kO@bc6P!nmFcZM-Wg65ap~*r zg<6$DNt_-zLb(H10(Lgq-VSqP%_phZOveYX6L^X7mY?ad1Z=P=d>p=!pR~8T+tI~E zp-|EkKdMC*1MiiysU|5qEX{Q!OFW+rHjZtYYWej`-1Q$Ko%Qh}nuO%pzwuhYV0Ty7 zvWkk-bH~8C`tl4CqN2L{`Yf!h_Tc{D>Pq+SF%Wu+k9BtPK&^6ewly{3UloV>d+%QM zw{I>37;`hT3zs?d%L+bz9B+I@Z57PI#dW-tUqj%x-?=rl7Pq_@5f;W2sR#oSe%`)) z3)iF#h}_$AghWXh2l8|637I)L&{6TRv6;IQjo7ac z#I|m4Y&>^%4n$Xb>^`0O75(z%OER)Hk-=Vj4935H;>y*lmTm7}!qS-W#MVB(&}nnPR?NyolkgT(UcO9^nW=*^DHkzoIZZ}(hl9Dr#INw*EcXQ(B8h% z5JoZ2#KDmRdnk?S8s1fAC5tA$)C{|755vu}Bk4hknysB(S46?<*ROMOataIAmj{c! z*^m96S`QR+Zu56zD>(uG3+w%j8Q27!e8Z6%9|~3kn2@G=Wnpc7&~M};=C<*vs>+}z&kF(RC*t~Vye*C|fH3;qJ8b{= zI5pYl?XR#WC*HLYBcKa9m%ax})kI+AG&J41gu zyL({3RV@XOpt7=3@hFZ;*>IcCzy5(5e^PGlav`P(@N*Ap1}K7srKPH58j}?I>p6xi zh6$0fj3Lcw6ENdodZq4|ehLmcfD7(1jR!vB8i->?=s1Ot6@NlJ= zg^!O|OvpGA}?CO7ku{`gpmh!_VJeZe=`(zV6y?^Zs_f5w7}6#w`<2N=BaR z0aiNxi)(8XKU;!hpr}^|3eO{wjFG@tFI~FSH?h3P>;LMmae-3O?t*c~q%dIq=Dm;0TotBmc zdS<-pQwX4Fge1MPXC)4NIy^iaL{;Y|K3wtMy_S{&@o9E6@%GqvH%Aa3sXLRWXeh1h z?1j0xU7!^qwmR6w{JcEF66;<+TtdJlwTr*-&~$X%q(0)bw$ps~`|^#93=MCA?6tCT zou~_FnH?RdvnV=`g9DBHg#VGAUfejzFc1Uc>vs#BR~~g$2wMM?IVSV0@xijQvmXJ4 z@i|&=0&@V0ek@i~ITwVYy1M$o!2u_EPHrwIJ-y^z{ZK__DE5cgRWHuell5yPz<;P- zSj}DdF}KNWQ1K}*ui9}=WlMNxuWNXigNsWn?*Xd$*RNEKY`_s{!Fp|Ucl5an!3tv% z7Zt?oU`81kjlm*|C)*nvI{@IdEUzeLefg5!y#O3{w8rN&+2`bmwY9MAoyak-14X#u zD933&6i5VM&>89JiDDjowY4c_Wx74IuLAS(^3LO5*45Qj%kBXX>soM9_uzjGh0EqP z#vNW>?q+B>n(-hZ=9a-huZ~gSpe_7bgB}b1Ly8(ZP#Vz4;EbSa4tME-2eN!Nc8_sD zIhEQCgBb%14Y~?AitI|)>Fh*(5P&HRD^+FX@6TsKf!Jk<#iQW<{3j0^{I2m?9L-6b z-cwc=h2@CB-Y{Edu~SeM5ND!|?cz8LXvLPeZ`h zML#ASu>E}0xDj*`rA0+W1qID5E&G%rn#lV6VS@{-w}?okpPwIS3*ozWFW}+rY;7r< zEdj%W(FZIZh>SUJ+|JGp+28@QtY{B+A5*f_`1+nfrSnw^ivIq7YD!9GR#p|sG{9{b z^ZLbBkrfs0=H}@D?@rW{#9^*kKEJk(ae8`tq1P~`rqH}Pxw`6_ntXNVCxSZMfeOLm zZ)|SHDbKbaA@N^*mPL4KJ)kXYnr=t_9jX3i(h}NY=dnBSQswkuI*VRtTc8;Z_ zq=rvgp|SG~Dg~@H^>6KlaaX&JWn$i2IbTWo|1#Us=84|Dx6(DN_7rj=ef}StEkfKs z#JD2o|8DV(?gmmMw2S+kd;@<2caPm$Ln?}jC}LtDqtcZW z+=iStZ^qxTiE%jo{aZy#tGBODTTZTFm+MJ%GKF}?Ip70I(Mhwrbkbw1UKMI zfIQc6SOHzGtgfcDlkhqDP-_elabRdDmGo9@s~IntGRrF~ARW|9U@O30NJ^rOYPljC zqNSq)eicE0skL=z)70kXW_w$k;dj?{n0MDGDe3*|wu4Gp+URXSgnF${f|Ty_$0vUG z?w!7Y!D%Deg%H`v=j8~3n&?VX0H>+Rv=Bi=X}Lv3kH$_)jdYnVF}HI>i0atSl@k z9=Yt>bFZicp)~hAy=`rCLqb~qmOGw5e?BcWRXgACc)EoQ))4dyk)EC&5T^C@ z^*ucg_4LX?edgqZNz#Lb3XKkwtlO&Cyfvn!xp{ha_H|Ru8WRceHeZ}FAz|2h0qjYY zaV?H;B8(OTef?&$4Y)8pww~3e9aL0qti7dW?ECiv-Q9dPeVp&^Z7g(WBEHZRg%9{e za!c%nOWj;uKW<3@AG=6QOxH(dA`%%HIWG*hN(a=As;WZBq^+%OYFZitFq0GT(rg8& z2Nhxm|D-E*1qd&fPp!Kaf4CUYq^YG<^?NTUZFpS^yP4htw@SKbfLCm8|ON zoX-DW?4s(=pKoG28yaSy?gfQ+0Hwh2{U>(MS|QQOIjaP`1)P_@F%MSP)?ysRD#UEc%^1{M`6%LQbeUgW+ z?f@v9$n~#Zc?kl}EcncBZvC=1Z{Mb-r$=*RttceC=q6K6Qd1dkMhnkc`20^Jj;&aJ z4sIMOSxwn0r|nXId|?HCc(;C*T%047Ylj{Nvu;-#Y?n> z8S~-8^;hy_x~ymv7-d!qdi?3~bmo?p)Yq;_p{6D$)r|KG=2l^7&CjD4mgnakKnhMV za&diu1q}};0($Gj#lps>ncdS8N1`SwFFxheMD`#fKq*PWXLNWttbXG4b)m_b8M$FEtaL++h7 zh_=l-Tiz;u0$8jin1Zr6K0Y?`-e+-tVX#LV`GYl1`FCq;rR#cXKtMyMqa_dJe|%|Z zb^t5gN@qJIB_$7!N-)sDW&mCeDMw&n;OEbaaLM#fpBj(G1o46oHmFHdlf|Kdx-JL` z18AwLM$i}8D=85U0a$0{=3Xz(>mFc@r|BC~3*4S&a@$>{v34JD3_=U=^FyX|S?o>6 zoDNKco}Ta&KFn*^pB?XFVgT?;KYfzzd2OtGBjd2hFnl3=Ad4>Sc|D~g5SPiaB;v+t z1<{^}SDrkL=hxLF$j7+bz{ZqaskzYNkbV!1Wiwm2L_`B#6f-Hz{BsCY0O-Ggzq@Ck zit+LRPzDD1+|iMO>(TW1xUs1z7@CmJgpTZ;Qu1tv;X~w84g=S{g+Wk|0+CGD0DlbL zVzTc4Nx8131zu-e0O8|DkKiVo=T}!*Nkb4sJQ<`}!_+!nG$tG;ca4I0lBN0xDc!mXEhy06o@{Ci7tFy61WlvN2UFkxVp#7+r2*y9^S@uiqVBfNQoYJ6NRrM zni7p$=ARamj~2Xu%>f0IpXk_2C$4)x9jnfM{NlLiU0e$$r-@)32SHrf% zm07#Hy41^iPuF|=I4wd$Q?u*WRus?i z<&2ZtX0lAlEy<%nEoM~Lu3aM7PgP@wd!5|e2Xp~%9Dq;8i)^6AeS7gE?s5Yw+^N<6 z*rL6SjR)8O5G>$Eb!}}qy<0wu0fmJh!SIf5ZEXeL{$_LqFp=@`ap0&|Ikcf|AV4{L znyfPt91wteIcWI18z0sIXa;B;z+k`z&;Wqe(2rTOP--CEaO187ma;5QcV0+D5Q2aW z5Uw0Ld5|`N3vc38>9)x#3^8o#mKNgs>C-2;8aVm5xBB-gvciv*rCL%_0^pm_ZdhRa60{PSi~x+F z51KYAo6th1j<#2>UteBWxS`MMv9nC)b3`IdNkRf<6xi=T7dwgWaC55yn)2CxMq-2UZ%#`O4_;K;^;Jdw)lw`Sn zIkT#YCVl0pot>7Z=6R$*Hy7wM(7%b{MIZ$IeSM8n>xqep@GvlO5ntfNpmf^I72t1hx+>kEq`Ap2#`+KfKA$lB7gA$3?bPSn!x$E$z4xyCxJ`# zjg1i_Am6~z0(YTx<|aEkSUC`{zf#Ez>*sAA5KF#o7McS{yT4%$VGT?z1c_997a94? z(eW%mh~?DdW!F{Y{Lv#3s66vbq7LNR*qD)u%H^PXNNIk55CRX$5w>QM-7CD%d=b71 zO-c%Lni2BPj~^WlwiaM;avOdx`}k3^$J-?M{gV{$>z7@o8ZSWsfw_{(!vIE#R*v=; zqnhfxJe8hNli+ap4B}f{yjA6~dzMlkuGIj)l#r+aYILP$AJWfMU%T*yMkjR%L{d&} z=H&PgtR$;gFdu}SvWkn}HJC0eEuHR7Ma=i18@Egr$2PCYLbO$0E(Bv((#>uE8zhL} zSVEEnl^6Q!Tcq#E<~5m&#Dmj7@T1|fFu0-3LCyvbB~H}B!y7N2N=Tw0yC$X;RZQ0a zZN0U#&$bT&>BgAX?g)qp5F`-v$xfaJth_+I?}>ox1n>Z_ularH{k(54yEp(rs{uKRAK62v2bv3f@MwNE<4+(Ferf~ z8kvG>A6tiK&meOeD78z7jipFb$Wq*QY0e%Shu)joDtuuM> z{M+4|5+PlJ`}_9on;~!_i_+{@M7umC(MkxoKl%h0gPVfEyS( z@?(rMZf|3z6$~t*o8Ns-y`7x4PPf>=y%rMMm-#(jzpN?-rI-Yk4nz{ED_ATR&Qib_ zFZKWn6e2#oB8!XtYs(Ue=@*aP?`~|mtYQ3($9%Pz`h)A3=YeGB7Ld!y3P)QeXCV&e#&bHlv zvo>&?28!q}BqA>-uMq{Nr$abB3uTSF>-V3NK-TQw{@%LvbpGle2x+yoE$r;L*cayK z%UsryjCaAlfkBfcdgI0djBh^|-pFH^eyEr|ug%#@kOd9f3W$IJfGB}LJkggj4Ls-n zR@~)fWj`Alz8F?fNxK5Tz^#fW(@|5~n40p!4guOj3&I%=3Ac@(kaK`rATC~AQ!@r7 z(b{SQdLPm|IIDn`)&zh*f1a3_82(~zJ_B<(FYgx4%g*lZ`UwYeZbRj?F2Gh+CZ?!_ z1dio4nC2keu}VX;*+}Uti?mSVzYin1bZavoQVVHLk!R9yqQ9L`i)~;q`T?-p@HX z3|N>l7jRy7%n>fz4;3#2(RoWYJ^fpDn~~A4V-8g9+{}y=O6dCQz`#Z*nZ}u%D1-y^k{CuCS zd6MY+5Z8TDV~2zjK|s2bh5$SIY0Lvm01PFM$)6V?JibINfFPk^VLD$Pu`CmTEk(Nn zcBkui09If{`<^GTReT(eNl%x{>}FzQq(964{!eNf&TF7d z6cmCoGGQeO;Zv)4##taPm%_{T-Y<5>E66Umo&e5W1cW5c~!t#(_Qs zmWb!J7vXcnbn~V)@KeBkbls;<%y6(}dU_f-3WOpwBF>ViNH6j*mK!%h@C0C`FW{u) z=iAo@UV2<=OY-zx>&)xTSm6}FRxx-WP&)inmsSJ>1<6nsfc;+%I?rHsb~X>!>s?}^ z9YmlE;bCEpFJ1(o0qrZw%cW3oTClM2HdV2!hlhx;urvx@{*H`vl_@GI<-oxuI689g z-bDi?@aG=hEUBq68owAyY4`N$>LIr%EwOYN;1wLI0QV}z8k~MG)TK_)s0;j}GCRp) z9`ekj@O5BNgC}NZZjQ?UmU;pJd2+|v%F0N!*Wt_a_^jiP6BWBF_6#k zbpcg_@OpCH^>R@6=%_gGI7HIMCMQ0g>T~D7fFffg*mob#GhiVi1Azk$B;AWMH=UXE zo}r<)v9WKv1qTNQp*Va2ToWj2-8Nhmaz@}vcQB3N>Vm>gYI`DXd(|d6oBa2f`JV&l dfB)MFofb1{mc?808l0p>?#Zdh=1Cj-{SW;cB+>u? literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/access2old.png b/libs/iterator/doc/access2old.png new file mode 100644 index 0000000000000000000000000000000000000000..8a87b84fa565e7b2469926163a668804afd7d65e GIT binary patch literal 42175 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 literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/advance.rst b/libs/iterator/doc/advance.rst new file mode 100644 index 00000000..34aa055b --- /dev/null +++ b/libs/iterator/doc/advance.rst @@ -0,0 +1,75 @@ +.. Copyright (C) 2017 Michel Morin. + 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) + +======= +advance +======= + +``boost::iterators::advance`` is an adapted version of ``std::advance`` for +the Boost iterator traversal concepts. + + +Header +------ + +```` + + +Synopsis +-------- + +:: + + template + constexpr void advance(Iterator& it, Distance n); + + +Description +----------- + +Moves ``it`` forward by ``n`` increments +(or backward by ``|n|`` decrements if ``n`` is negative). + + +Requirements +------------ + +``Iterator`` should model Incrementable Iterator. + + +Preconditions +------------- + +Let ``it``\ :sub:`i` be the iterator obtained by incrementing +(or decrementing if ``n`` is negative) ``it`` by *i*. All the iterators +``it``\ :sub:`i` for *i* = 0, 1, 2, ..., ``|n|`` should be valid. + +If ``Iterator`` does not model Bidirectional Traversal Iterator, +``n`` should be non-negative. + + +Complexity +---------- + +If ``Iterator`` models Random Access Traversal Iterator, it takes constant time; +otherwise it takes linear time. + + +Notes +----- + +- This function is not a customization point and is protected against + being found by argument-dependent lookup (ADL). +- This function is ``constexpr`` only in C++14 or later. + + +-------------------------------------------------------------------------------- + +| Author: Michel Morin +| Copyright |C| 2017 Michel Morin +| Distributed under the `Boost Software License, Version 1.0 + `_. + +.. |C| unicode:: U+00A9 .. COPYRIGHT SIGN diff --git a/libs/iterator/doc/counting_iterator.html b/libs/iterator/doc/counting_iterator.html new file mode 100644 index 00000000..1cb5a17e --- /dev/null +++ b/libs/iterator/doc/counting_iterator.html @@ -0,0 +1,301 @@ + + + + + + +Counting Iterator + + + + + + + +
+

Counting Iterator

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2006-09-11
Copyright:Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
+ + + + +++ + + + +
abstract:

How would you fill up a vector with the numbers zero +through one hundred using std::copy()? The only iterator +operation missing from builtin integer types is an +operator*() that returns the current value of the integer. +The counting iterator adaptor adds this crucial piece of +functionality to whatever type it wraps. One can use the +counting iterator adaptor not only with integer types, but with +any incrementable type.

+ + + +

counting_iterator adapts an object by adding an operator* that +returns the current value of the object. All other iterator operations +are forwarded to the adapted object.

+
+
+
+

counting_iterator synopsis

+ + + +
+template <
+    class Incrementable
+  , class CategoryOrTraversal = use_default
+  , class Difference = use_default
+>
+class counting_iterator
+{
+public:
+    typedef Incrementable value_type;
+    typedef const Incrementable& reference;
+    typedef const Incrementable* pointer;
+    typedef /* see below */ difference_type;
+    typedef /* see below */ iterator_category;
+
+    counting_iterator();
+    counting_iterator(counting_iterator const& rhs);
+    explicit counting_iterator(Incrementable x);
+    Incrementable const& base() const;
+    reference operator*() const;
+    counting_iterator& operator++();
+    counting_iterator& operator--();
+private:
+    Incrementable m_inc; // exposition
+};
+
+

If the Difference argument is use_default then +difference_type is an unspecified signed integral +type. Otherwise difference_type is Difference.

+

iterator_category is determined according to the following +algorithm:

+
+if (CategoryOrTraversal is not use_default)
+    return CategoryOrTraversal
+else if (numeric_limits<Incrementable>::is_specialized)
+    return iterator-category(
+        random_access_traversal_tag, Incrementable, const Incrementable&)
+else
+    return iterator-category(
+         iterator_traversal<Incrementable>::type,
+         Incrementable, const Incrementable&)
+
+
+
[Note: implementers are encouraged to provide an implementation of
+
operator- and a difference_type that avoids overflows in +the cases where std::numeric_limits<Incrementable>::is_specialized +is true.]
+
+
+
+

counting_iterator requirements

+

The Incrementable argument shall be Copy Constructible and Assignable.

+

If iterator_category is convertible to forward_iterator_tag +or forward_traversal_tag, the following must be well-formed:

+
+Incrementable i, j;
+++i;         // pre-increment
+i == j;      // operator equal
+
+

If iterator_category is convertible to +bidirectional_iterator_tag or bidirectional_traversal_tag, +the following expression must also be well-formed:

+
+--i
+
+

If iterator_category is convertible to +random_access_iterator_tag or random_access_traversal_tag, +the following must must also be valid:

+
+counting_iterator::difference_type n;
+i += n;
+n = i - j;
+i < j;
+
+
+
+

counting_iterator models

+

Specializations of counting_iterator model Readable Lvalue +Iterator. In addition, they model the concepts corresponding to the +iterator tags to which their iterator_category is convertible. +Also, if CategoryOrTraversal is not use_default then +counting_iterator models the concept corresponding to the iterator +tag CategoryOrTraversal. Otherwise, if +numeric_limits<Incrementable>::is_specialized, then +counting_iterator models Random Access Traversal Iterator. +Otherwise, counting_iterator models the same iterator traversal +concepts modeled by Incrementable.

+

counting_iterator<X,C1,D1> is interoperable with +counting_iterator<Y,C2,D2> if and only if X is +interoperable with Y.

+
+
+

counting_iterator operations

+

In addition to the operations required by the concepts modeled by +counting_iterator, counting_iterator provides the following +operations.

+

counting_iterator();

+ +++ + + + + + +
Requires:Incrementable is Default Constructible.
Effects:Default construct the member m_inc.
+

counting_iterator(counting_iterator const& rhs);

+ +++ + + + +
Effects:Construct member m_inc from rhs.m_inc.
+

explicit counting_iterator(Incrementable x);

+ +++ + + + +
Effects:Construct member m_inc from x.
+

reference operator*() const;

+ +++ + + + +
Returns:m_inc
+

counting_iterator& operator++();

+ +++ + + + + + +
Effects:++m_inc
Returns:*this
+

counting_iterator& operator--();

+ +++ + + + + + +
Effects:--m_inc
Returns:*this
+

Incrementable const& base() const;

+ +++ + + + +
Returns:m_inc
+ + + +
+template <class Incrementable>
+counting_iterator<Incrementable> make_counting_iterator(Incrementable x);
+
+ +++ + + + +
Returns:An instance of counting_iterator<Incrementable> +with current constructed from x.
+ + + +
+
+

Example

+

This example fills an array with numbers and a second array with +pointers into the first array, using counting_iterator for both +tasks. Finally indirect_iterator is used to print out the numbers +into the first array via indirection through the second array.

+
+int N = 7;
+std::vector<int> numbers;
+typedef std::vector<int>::iterator n_iter;
+std::copy(boost::counting_iterator<int>(0),
+         boost::counting_iterator<int>(N),
+         std::back_inserter(numbers));
+
+std::vector<std::vector<int>::iterator> pointers;
+std::copy(boost::make_counting_iterator(numbers.begin()),
+          boost::make_counting_iterator(numbers.end()),
+          std::back_inserter(pointers));
+
+std::cout << "indirectly printing out the numbers from 0 to "
+          << N << std::endl;
+std::copy(boost::make_indirect_iterator(pointers.begin()),
+          boost::make_indirect_iterator(pointers.end()),
+          std::ostream_iterator<int>(std::cout, " "));
+std::cout << std::endl;
+
+

The output is:

+
+indirectly printing out the numbers from 0 to 7
+0 1 2 3 4 5 6
+
+

The source code for this example can be found here.

+
+
+ + + diff --git a/libs/iterator/doc/counting_iterator.pdf b/libs/iterator/doc/counting_iterator.pdf new file mode 100644 index 0000000000000000000000000000000000000000..21b2d9656a4acaca75041b05d5cf5c283d7f675a GIT binary patch literal 72583 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 DRus$8G?MVVV%fEcKXQaT3wsU}4Q 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 numbers; + typedef std::vector::iterator n_iter; + std::copy(boost::counting_iterator(0), + boost::counting_iterator(N), + std::back_inserter(numbers)); + + std::vector::iterator> pointers; + std::copy(boost::make_counting_iterator(numbers.begin()), + boost::make_counting_iterator(numbers.end()), + std::back_inserter(pointers)); + + std::cout << "indirectly printing out the numbers from 0 to " + << N << std::endl; + std::copy(boost::make_indirect_iterator(pointers.begin()), + boost::make_indirect_iterator(pointers.end()), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + +The output is:: + + indirectly printing out the numbers from 0 to 7 + 0 1 2 3 4 5 6 + +The source code for this example can be found `here`__. + +__ ../example/counting_iterator_example.cpp + diff --git a/libs/iterator/doc/counting_iterator_ref.rst b/libs/iterator/doc/counting_iterator_ref.rst new file mode 100644 index 00000000..1c5fd1c4 --- /dev/null +++ b/libs/iterator/doc/counting_iterator_ref.rst @@ -0,0 +1,149 @@ +.. Copyright David Abrahams 2006. 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) + +:: + + template < + class Incrementable + , class CategoryOrTraversal = use_default + , class Difference = use_default + > + class counting_iterator + { + public: + typedef Incrementable value_type; + typedef const Incrementable& reference; + typedef const Incrementable* pointer; + typedef /* see below */ difference_type; + typedef /* see below */ iterator_category; + + counting_iterator(); + counting_iterator(counting_iterator const& rhs); + explicit counting_iterator(Incrementable x); + Incrementable const& base() const; + reference operator*() const; + counting_iterator& operator++(); + counting_iterator& operator--(); + private: + Incrementable m_inc; // exposition + }; + + +If the ``Difference`` argument is ``use_default`` then +``difference_type`` is an unspecified signed integral +type. Otherwise ``difference_type`` is ``Difference``. + +``iterator_category`` is determined according to the following +algorithm: + +.. parsed-literal:: + + if (CategoryOrTraversal is not use_default) + return CategoryOrTraversal + else if (numeric_limits::is_specialized) + return |iterator-category|_\ ( + random_access_traversal_tag, Incrementable, const Incrementable&) + else + return |iterator-category|_\ ( + iterator_traversal::type, + Incrementable, const Incrementable&) + +[*Note:* implementers are encouraged to provide an implementation of + ``operator-`` and a ``difference_type`` that avoids overflows in + the cases where ``std::numeric_limits::is_specialized`` + is true.] + +``counting_iterator`` requirements +.................................. + +The ``Incrementable`` argument shall be Copy Constructible and Assignable. + +If ``iterator_category`` is convertible to ``forward_iterator_tag`` +or ``forward_traversal_tag``, the following must be well-formed:: + + Incrementable i, j; + ++i; // pre-increment + i == j; // operator equal + + +If ``iterator_category`` is convertible to +``bidirectional_iterator_tag`` or ``bidirectional_traversal_tag``, +the following expression must also be well-formed:: + + --i + +If ``iterator_category`` is convertible to +``random_access_iterator_tag`` or ``random_access_traversal_tag``, +the following must must also be valid:: + + counting_iterator::difference_type n; + i += n; + n = i - j; + i < j; + +``counting_iterator`` models +............................ + +Specializations of ``counting_iterator`` model Readable Lvalue +Iterator. In addition, they model the concepts corresponding to the +iterator tags to which their ``iterator_category`` is convertible. +Also, if ``CategoryOrTraversal`` is not ``use_default`` then +``counting_iterator`` models the concept corresponding to the iterator +tag ``CategoryOrTraversal``. Otherwise, if +``numeric_limits::is_specialized``, then +``counting_iterator`` models Random Access Traversal Iterator. +Otherwise, ``counting_iterator`` models the same iterator traversal +concepts modeled by ``Incrementable``. + +``counting_iterator`` is interoperable with +``counting_iterator`` if and only if ``X`` is +interoperable with ``Y``. + + + +``counting_iterator`` operations +................................ + +In addition to the operations required by the concepts modeled by +``counting_iterator``, ``counting_iterator`` provides the following +operations. + + +``counting_iterator();`` + +:Requires: ``Incrementable`` is Default Constructible. +:Effects: Default construct the member ``m_inc``. + + +``counting_iterator(counting_iterator const& rhs);`` + +:Effects: Construct member ``m_inc`` from ``rhs.m_inc``. + + + +``explicit counting_iterator(Incrementable x);`` + +:Effects: Construct member ``m_inc`` from ``x``. + + +``reference operator*() const;`` + +:Returns: ``m_inc`` + + +``counting_iterator& operator++();`` + +:Effects: ``++m_inc`` +:Returns: ``*this`` + + +``counting_iterator& operator--();`` + +:Effects: ``--m_inc`` +:Returns: ``*this`` + + +``Incrementable const& base() const;`` + +:Returns: ``m_inc`` diff --git a/libs/iterator/doc/default.css b/libs/iterator/doc/default.css new file mode 100644 index 00000000..8c1e3425 --- /dev/null +++ b/libs/iterator/doc/default.css @@ -0,0 +1,226 @@ +/* +:Author: David Goodger +:Contact: goodger@users.sourceforge.net +:date: $Date$ +:version: $Revision$ +:copyright: This stylesheet has been placed in the public domain. + +boostinspect:nolicense + +Default cascading style sheet for the HTML output of Docutils. +*/ + +.first { + margin-top: 0 } + +.last { + margin-bottom: 0 } + +a.toc-backref { + text-decoration: none ; + color: black } + +dd { + margin-bottom: 0.5em } + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.attention, div.caution, div.danger, div.error, div.hint, +div.important, div.note, div.tip, div.warning, div.admonition { + margin: 2em ; + border: medium outset ; + padding: 1em } + +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 } + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.sidebar { + margin-left: 1em ; + border: medium outset ; + padding: 0em 1em ; + background-color: #ffffee ; + width: 40% ; + float: right ; + clear: right } + +div.sidebar p.rubric { + font-family: sans-serif ; + font-size: medium } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr { + width: 75% } + +ol.simple, ul.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.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.sidebar-title { + font-family: sans-serif ; + font-weight: bold ; + font-size: larger } + +p.sidebar-subtitle { + font-family: sans-serif ; + font-weight: bold } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.line-block { + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +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 } + +table { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.citation { + border-left: solid thin gray ; + padding-left: 0.5ex } + +table.docinfo { + margin: 2em 4em } + +table.footnote { + border-left: solid thin black ; + padding-left: 0.5ex } + +td, th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +th.docinfo-name, th.field-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap } + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + font-size: 100% } + +tt { + background-color: #eeeeee } + +ul.auto-toc { + list-style-type: none } diff --git a/libs/iterator/doc/distance.rst b/libs/iterator/doc/distance.rst new file mode 100644 index 00000000..d0697a9d --- /dev/null +++ b/libs/iterator/doc/distance.rst @@ -0,0 +1,72 @@ +.. Copyright (C) 2017 Michel Morin. + 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) + +======== +distance +======== + +``boost::iterators::distance`` is an adapted version of ``std::distance`` for +the Boost iterator traversal concepts. + + +Header +------ + +```` + + +Synopsis +-------- + +:: + + template + constexpr typename iterator_difference::type + distance(Iterator first, Iterator last); + + +Description +----------- + +Computes the (signed) distance from ``first`` to ``last``. + + +Requirements +------------ + +``Iterator`` should model Single Pass Iterator. + + +Preconditions +------------- + +If ``Iterator`` models Random Access Traversal Iterator, +``[first, last)`` or ``[last, first)`` should be valid; +otherwise ``[first, last)`` should be valid. + + +Complexity +---------- + +If ``Iterator`` models Random Access Traversal Iterator, it takes constant time; +otherwise it takes linear time. + + +Notes +----- + +- This function is not a customization point and is protected against + being found by argument-dependent lookup (ADL). +- This function is ``constexpr`` only in C++14 or later. + + +-------------------------------------------------------------------------------- + +| Author: Michel Morin +| Copyright |C| 2017 Michel Morin +| Distributed under the `Boost Software License, Version 1.0 + `_. + +.. |C| unicode:: U+00A9 .. COPYRIGHT SIGN diff --git a/libs/iterator/doc/docutils.sty b/libs/iterator/doc/docutils.sty new file mode 100644 index 00000000..a6fce3f0 --- /dev/null +++ b/libs/iterator/doc/docutils.sty @@ -0,0 +1,54 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%% docutils.sty: A style for docutils latex output %%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% o author: Alexander Schmolck (a.schmolck@gmx.net) +%% o created: 2002-07-07 10:50:31+00:40 +%% o last modified: $Date: 2004/01/29 05:55:26 $ +%% o keywords: +%% o license: +%XXX titlesec +%% XXX geometry +\usepackage{graphicx} +\usepackage{latexsym} % extra symbols +\usepackage{url} % !!!: pay attention when using in other commands!!! +\usepackage{verbatim} % normal verbatim has lenght-limit +\usepackage{enumerate} % easy style choice with e.g: ``\begin{enumerate}[Ex i.]`` +\usepackage{hyperref} %href, htarget and hlink XXX: pdfauthor, pdfcreator etc. +\usepackage{xr} %XXX do we need this? +% need this to have ``fboxes`` in ``enviroments``, as well as ``verbatim``s +\usepackage{fancybox} +\usepackage{mdwtab} % better tables and arrays (fixes spacing and adds + % vertical align and multirows (m)) +\usepackage{ltxtable} % long and autoscaling tables (use X for autoscaled + % columns) +\newcommand{\transition}{\vspace{2em}\par\hrule{}\par\vspace{2em}} +\newcommand{\classifier}[1]{(\textit{#1})} +\newenvironment{topic}[1]% +{\begin{Sbox}% + \begin{minipage}{.8\textwidth}% + \protect{\large{\textbf{#1}}}\par\vspace{.5em}}% +{\end{minipage}\end{Sbox}\fbox{\TheSbox}\par\vspace{.5em}} +%XXX shadow box for warnings? +\newenvironment{admonition}[1]% +{\begin{center}% + \begin{Sbox}% + \begin{minipage}{.9\textwidth}% + \protect{\textsc{#1}}\par\vspace{.2em}}% +{\end{minipage}\end{Sbox}\fbox{\TheSbox}\par\vspace{.5em}\end{center}} + +\newenvironment{doctest}% +{\VerbatimEnvironment + \begin{Verbatim}}% +{\end{Verbatim}} +% {% +% \begin{Sbox}% +% \begin{minipage}{.8\textwidth}% +% \protect{\large{\textsc{#1}}\par\vspace{.5em}}}% +% {\end{minipage}\end{Sbox}\fbox{\TheSbox}\par\vspace{.5em}} +%{\end{minipage}\end{Sbox}\fbox{\TheSbox}} + + +%% just a piece of example code +% \newcommand{\vitem}% +% {\SaveVerb[{\item[\UseVerb{\MyTemp}]}]{\MyTemp}} diff --git a/libs/iterator/doc/facade-and-adaptor.html b/libs/iterator/doc/facade-and-adaptor.html new file mode 100644 index 00000000..79d38a30 --- /dev/null +++ b/libs/iterator/doc/facade-and-adaptor.html @@ -0,0 +1,2716 @@ + + + + + + +Iterator Facade and Adaptor + + + + + + + + + + diff --git a/libs/iterator/doc/facade-and-adaptor.pdf b/libs/iterator/doc/facade-and-adaptor.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a77daa477a1f24f3893439ded973ea719d05442b GIT binary patch literal 226024 zcmb@u1z1&0_dcwYl+qy*2Pu&_oZxUk5NVO_7KuYhcL_)-AV^532uMk{5`rLI1|bMi z(kY$aK43iYKHty(`#u-fVedUNd-j?&Yu1{%_dT0MQCyM>!VSZRfOtSQhIjD=1@XbE zZnh{8Sj@oDz|zJPAFOC#igEx!fdb0-U7CcFL=Xge@?;PMb|NBh{C*ARJ1xh{^Zoe!J_PUSHR5|YzSHUqGngfFJpmnGW98cwh@|->&3ORi~6mnW06mnW0^t=2}=xKe> z@A5-or}gULgT-u|tQ|ox2>vfsq3ig&s_?-g*48$TXkDE?{IrVG2c3#>D&+SjeAmdS zz>pt$J5|efE&ou`Y2tTPo>uZh@E`3uZT62=oL+s`!D%hf?=AkWknj3Bl?8TM3+z-D zpwY@G2OB4QBfzFk6@m|zLm8VJh}yUUtwR^)<>%#w^6~P4kZ=e$5(%guxJ%K%9tG&? zLrF`CIggKaWZr~8A`I|))qh)fqo6H z)1d$q0fvb(@D$)5=!%trxuv6xfU$uy>V~0>je{eXk&U&3lcl4%wJEoejTJk(9luNg zt=s>(DKH)cTAA=aG=&er4MRYHl>faccOA@87B_4hEV<2{xKYMVe`x{QEdKWv0G$Dc z^8%{>(HU?)er^O0V08aN3tY?{9d9@|x>=$OjGfILZ0!F-N1)C6e{RMvn}YHK#s!Ch zpu9+KC_fYiG>nIv4*|G^|H7us935>1z+e{_7w+FMDfGzvpIZWh0|vwccwfYimcU^= z+)x;V_up#CKN=L;rTowG!(ni4C@&Bde#y@dBoa1>xi7 zNAN>HP@q2$NWhK|P$V}3@Z$fQJ^f#;`1_RNH(V|HrW5b`-PQ6VxnU5%#lsOm7w`kJ zL*RVeNCXTHg7ZOvES?kZ{~tXq;9I3^RBiCV;(%+laWr=}Kus!#|N?J@bXtKjy}0z(npNElk9Kyc$hz=1g|42TnO{@)u|Csqm!tiNa#iuT_Bvpa?S z>~{26=LG`qFChV!#RmhHc)vCJjS+v953P^?UA`aQ2?~sEI24cu0<1}3JiJg~AplI; z5Ws5Yx8(cL>juUKw*Nty=+(@>C@e6#5fCIW4}bu%6o!Ci2bd19F#nw%_}QY<2=V8J{Ku$q z0u=o37XQP20MH9CJb@?-1>!Ov3;E99kud264**TfpqpZ-N$X{*d-wlKiBzlYj zz6Ajc1z<*r_S`T4P55u5J`FO!r2TI)|2whphZ{#vDquW3z_3Naf$<9rWC$OU8-n=F z#l=r$e|L+2HuV4O+fQJxf6vk(yZ}VN2TY5AxjPUs(KArA_vDB0{g&eY$h%@>L-BW52Z^27~u&bCkclEa~~jb z0r0jY90|;Vzn=pOxF5;9fNwud2JknqqP>lg3JQ$`f&u&-1Xcwi3?S?;XzrxC9}hZ( z)6tLn10;w}gy4fEtc`4p0eBAtEND*!Ft>Mb6f-lh2f!(57sa@b~FQE z(GyS=Kr9U$P$!K5-&9mnQx@S6lT(K90c`-DB#v@0vNuQ1DS(OcNzH!{?(f0xhZw+G z+1$hg1wg52{1pwig1G@)*%)O4hywx;OdtgOOyL7^B|&_UKcv6_$P@(3Cw`XU=L3Na zK*0L_R|-D}Yy<)ugTN>dga`U70|LMvU~3TA1_ZVRK>)D)=PeMxeSqzOG(dzO;s6Q( zfgOP~-~m6<{?r3MBB2fl0oWFLT8jPyV8N3k3|O82Nc+7b8e!xC0z3l53rw2P$G_fp zk`9zYA9>I#mhb=de!S*5>4_g!A>v?!2CNbMZ~$XAu)T>gH#Gw;kuabSfX+kbaRIZ+ z)9ysSV*&l8o27x*Gv-Dj)~1#y5D#EkK%7zs@NRst=J&b))a~?c(NpZ43$RKqDDXCf z9|$XaKvV>Vm!zeEDe&?J5CJebv`Jq9i-0A;(qIFy5!e`v0$YP^z_ws}FffBUF)T@Q z;Bl}MApei{{>R`ai?TL#G=qSU{D94#UI2j?!3T(TdIbZ-g#NeyP=00cLp{SXq?{o}Z=o@*#G+f};?LLaP{Tql z%E}I@-D;&QF>bT9G;LBfUZORAP$I5;HHuh5TGeHK#6iAtf2P*^^MI$XX(=S0Ht8y}9Fp7`H*T2!O~e`6Tx=y}D4VYtY0Q0Le^#FdXGUJ1x$w00 z>={vl`wJKEE?m0o2)cEjpD{|b2?s0kjG9Bajl|6}6d0t%)NuMDu_qV}#1%L=p_sb3 z)SNe;-8f5r;T+O?0ry-|gKaqV**y_PTjZCA&EfZ-+&M!@Y?95>+t=DGza7X|Y!^4;gtpF!s5_m!|3s=1uKnpchQTF6^=%Tira4k$iZ^ zF3OvdSX8u)IUIM8kj=1{%;K+SMHs;fK_&cYw(7vSm|jh zQ;a_z)9d*5SUnXgKQYWmx_3X&lo6{p7M2&3-A~V7YQ8HAtc7QIGNen6ShV3Cr z@5eZLxVP9|(rq}Qk)AswxDE+PZ!d`IATRXU}PSJBMnC*Vf755boS?>^#KbV#MN(_`bY!=yp=izT z<3@A^6CtzHryk+jVi~8n;)JNct;MUID-~})H{BhbiFzw3CM6m5 zva}~;dk0@!R%b+_V^X7LGc)k(=Lz<#qD(!-bcr%T$E^fok&yKWqHVH*Q7_j~a;^+U zV$4MDqo~T2yh{VcN-Q0^Y5sgf53nt0G^(B3%Y#)x1mZRf@J*3hH#OpV-}Yv(WLlIK z#5MD1Z^%B(Z_rILLult}NSC^))V%F!?vI&E$)#@W?H(@dxtEjlN&c?&Y)F@D|4u|O zHPhgE_7QK6r}Q~e-}E$A1}|A(Y0L?`gJYc{s1tF?ypEpD#wDn~ua>@pkyY4`_+mxD zUbPwGD*-RllZX=6{*1mph@zVUQA@R1?$siUTRhV8FV`6eyK9~g%#*U^MwOPCxazyc zu|LaU=Z(?kkxZL!x*Tm4j^c1lIdd z7L{wBUDO_%6z=O4i@hA@{1|W54ik}rm>+k* zGNyX2KG>W@ zJMa5|&Iy}-%_i}FiiB6O?@47g5bCP(5ke8#1$l5;X$!ljR$AV3#CHcaB#Z zq388q#uxe;Jcm17rgtB#9Kv$$obDIa(CD7leVmHA7t=aU7Aw%hpQ_sKU~?_&Xf#>0 zyVa?2DH=7&=zeop!qaSV9&cZvfc}P6PSNmgtkiIr*tYJM6#}!}Lw41hR(FcAQp+_B z9hn?dijt2*Z+BxaH?{SNaqO_EHzR5z<{56=@HYr|1WII#e!MtaLnLe~5PD5i2;3Xn zx`X@H&GqRU+RtGz(znCe-EAHB^AeRiLFP|FF=q;Bd!yHCCP|CxG)9xF7v}HDb$78F zDb2jYSeV{ne%L~*KPI2ZJZ3PjYC-w6D(cqiYA$!Ezk(4aT)(AtNLn8*ASge)?D||zaCDc3;f)$-@pNW6mzH$9|d^>heX~pQqQmV(N8JVyF&$MfSOCbSV=NW9P zb0GG*3lzQq&DHM-ufBDfqF);1D-A#v9pAJzrODHivPo6~cOIaKz3Rb*(XP+=5Z43}!G?Y-s3 zu1rQo6cEcOCA5sl!au7DPQBk6evEyjHLlK&icOyWm;Nzefe%AqVIgX73DSA zEh=%9!$h*%6VbP(J^1}zu!5uv2ZXtvr&P2vZ>z6empW7)NQ2jHaLY80@4PXJm*TB* z$6sIGd}R^))P)v^IL{l@KHjj%y)A#~?G!~p-k!ypP=pL0j&gg)qj;-UAAKvk3ktK$ zxo&Z9R1n0IhS9v z-`swdYGxukggHp+sm^D;cZv6uT3T5PRUgggik(fc!3y9d9if97lecra*&y-f-9F$C ziSz1nb6;og$(i_8z^D1tMY`Zoy|O^u!rr38MED`|ElDLUFYbBOdk%v~%a>SgfE(ep zjX|%#{It_TZ#v!WkkpB=z;Dvt6tMoJS%LlDW9fVHRf}v<5qGsJ$7Fp5BP|YaGTZ*9&YGp&4xKg zI-JB1NXjy3te((DLzJPiM7bvvN~d+;VwjcNW5&zwtQ5E1R7)JT;i6@wbN;FXYD@pJ z;_f*`se{MQQ&Q@QFArn3Vq|*cn$HzFw|tzp*Y!-}Opi&ejw^b&E^BR=q>|xNp>sez z5;>|HNL%??)a+YW|3qwnaqQKFCrVyfVU?-iJ9Jz9wGTB+28FxTa~9Qk$2-PM*6v~T zF*!x9L%io3l~Zb#W7pufD>8}*w~5+#i)`m&WS!q&X5x@)0A?3NQVZ;8+4=C565Bh-W5 zPAVSvE&Q0Jb#4(7TKGDnM4aO78wNq7zCN6DHojEFp6P{4w}tz>X4mbVYjbD%*WBoD zLsA4*#!4|$C|w`w2xz(BiFH4 zYAri1Vk~iVP`?0Iw<++zh~CsEeIumEtYLfWTdlWgx-D&n7=I}q?sF+RH}A5Vo*+Yg zr{TP9@TYUt`IjPcA-G!CB#HEHV&mI1wAD}XlIvd=rx?2B(EdqV9Z#p~HfMyF-?Q!4 zUn}eOrCdu~yrBJvX%-c{tc?5$7Wq)m`Lajq8@K|_I;pw_w=R|`tG+9!hvf|MIu33e z_Nzz_P8nHNS2W04)YOJqYhWPz!HPaqZOAgT%ZzGD0Xd;mu;W|jZA*84m5_8ag4uqFnZ zm;f)De=XMmNx-&f+Lk5C#PR#7{mCjAz-NCh>H)wL3~-;U3_xHrH(N85H9!UULoTrV zcK~2oGc-K&^B#a;2;5@{a1DXw_|Me8BNzzaZZQzR4**O24axvSKoh|Jgl6yo^~!_5 z3LxYkfDt56QW*rikN)`};B7Tn6(Dwj02(tclmu+} z3mE~MfWW3ei$P#>044cDHE6;E*b)S``h}H%?a=55*a3})fSo{KXAsy01a<|1-9TV> zK;wUq?2ib^i6Nk^3_wT#5a+LG#_wLk0iqB3hb|8=H30MsjkfUeq4Af$|Dj9#F%@}2 z!UWz!f{=h7`FIf^J^(WYAPOD;YdOJ7PD`V&kpQZUzCt3<7!DGh0wA@&YWs8Dyl6%k z@MaE;#+)31*BHPn*%Qgo*FQ?5kNkkaoRk5iMjz2sA2X=+yQ_w zIDqh+5D@QWQ!z%Bpfp#C_J9T2xdZQzt`Ao0$5} zeV??4*5S+6(sPtJ=FFKow**+2qa;5&jP;b-eC|2gsY@LlyEbsI>S#fCM&PkU@>-mT z%tM*}_BM{hwCO`i#4=y>HT!V~x;9RnAK5_3H$cpa0X zfijS)NniG+Vu%LyD)p6>sl_Gy;^Kg_LsLV?x7_igoX)%wgA&`DX=bl|z8_R-;gJi~vW zcC;dYSZEiHi8X(?LdbT`)P;JGB74~w+u7-$M-_9mzO#*AFfq6&ni9*zoS+Ox9`E|vJ)&aM$1(Ei#8Q_)_2E3kQ}g)iI3Q;t zU;q1c_ihBHQw$Q|ZiynljypU0GCn^;!nJlz`&u=|k+xz}!Z*!hy8TPoZa#wDAdMm> za?A7kbkqAT8~S;>3Yx^NMsrhN&g{{VV5|?iUmNzN^M06u;WqLV#5e4HS@g2EoS(p9 zH;JU|lS8?{i|h4x5&5f$;y!{sM`>BOmBIBv46W%KiCFgq+w1X^BqsS7bIp##E(f}S zy~rlg9lgmK<41*=gJ=B$I9lJ)6Yet{idb5vjL8v8m}wob`o~NQH?=$}vfMm(`Ks^n z4S$LSVdAy(2yakh!V*K^D$Xt@NlC9TaoWP_C6eK=mNg>rS%E_zT)i1|+WNW6j(WgN z1;Y$i2&a4weFAS+9sA&F&;z$e&)7^!Rjuz~k`&YcML1IH*Su4~{QPWSeeSd3$5lH4 zuE+L_xa1V%TgMFXG0O#kas>PPTcWh@k4-FaClvh}Zr_o4{f>=IW^KUv;_7PfebZ)@ zXfuWIX-jQV-qFoYXTyiwtc+qZQmT3>FL-H2)lg)UOKD4e9@iCLNx1BohjFCfyka)# zJ|6kTGuE+Xo{6YwRo@$zMVCA%B=RHX~>r4{2!mr+)EHDzZ z91I~)_DW#~9~Gw-@V1 zzPKtzZLeF_LJdAyTReL;tgcB{@GORU>1+Tq_pJ+aW59xtHuFpFSa*9>QNo+WCR>d9 zW`dh^N7UN_uhs~NtxDovxC_n=5Jb~xJi;MgI$Kkb;5$sprQcvN^0g@6xI}@94p699E*J2ndGi>{^P_ zATC&KDJ$l(t+N|5n2#BUmRGbQs=mD!r5)94BVhK&Cb`^9ATGs%@&2M9Yraf%v%C^r z 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 literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/facade-and-adaptor.rst b/libs/iterator/doc/facade-and-adaptor.rst new file mode 100644 index 00000000..6308de4c --- /dev/null +++ b/libs/iterator/doc/facade-and-adaptor.rst @@ -0,0 +1,438 @@ +.. 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) + ++++++++++++++++++++++++++++++ + Iterator Facade and Adaptor ++++++++++++++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@styleadvisor.com +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, `Zephyr Associates, Inc.`_ +:date: $Date$ + +:Number: This is a revised version of N1530_\ =03-0113, which was + accepted for Technical Report 1 by the C++ standard + committee's library working group. + +.. Version 1.9 of this ReStructuredText document corresponds to + n1530_, the paper accepted by the LWG. + +.. _n1530: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1530.html + +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Zephyr Associates, Inc.`: http://www.styleadvisor.com + +:abstract: We propose a set of class templates that help programmers + build standard-conforming iterators, both from scratch and + by adapting other iterators. + +.. contents:: Table of Contents + +============ + Motivation +============ + +Iterators play an important role in modern C++ programming. The +iterator is the central abstraction of the algorithms of the Standard +Library, allowing algorithms to be re-used in in a wide variety of +contexts. The C++ Standard Library contains a wide variety of useful +iterators. Every one of the standard containers comes with constant +and mutable iterators [#mutable]_, and also reverse versions of those +same iterators which traverse the container in the opposite direction. +The Standard also supplies ``istream_iterator`` and +``ostream_iterator`` for reading from and writing to streams, +``insert_iterator``, ``front_insert_iterator`` and +``back_insert_iterator`` for inserting elements into containers, and +``raw_storage_iterator`` for initializing raw memory [7]. + +Despite the many iterators supplied by the Standard Library, obvious +and useful iterators are missing, and creating new iterator types is +still a common task for C++ programmers. The literature documents +several of these, for example line_iterator [3] and Constant_iterator +[9]. The iterator abstraction is so powerful that we expect +programmers will always need to invent new iterator types. + +Although it is easy to create iterators that *almost* conform to the +standard, the iterator requirements contain subtleties which can make +creating an iterator which *actually* conforms quite difficult. +Further, the iterator interface is rich, containing many operators +that are technically redundant and tedious to implement. To automate +the repetitive work of constructing iterators, we propose +``iterator_facade``, an iterator base class template which provides +the rich interface of standard iterators and delegates its +implementation to member functions of the derived class. In addition +to reducing the amount of code necessary to create an iterator, the +``iterator_facade`` also provides compile-time error detection. +Iterator implementation mistakes that often go unnoticed are turned +into compile-time errors because the derived class implementation must +match the expectations of the ``iterator_facade``. + +A common pattern of iterator construction is the adaptation of one +iterator to form a new one. The functionality of an iterator is +composed of four orthogonal aspects: traversal, indirection, equality +comparison and distance measurement. Adapting an old iterator to +create a new one often saves work because one can reuse one aspect of +functionality while redefining the other. For example, the Standard +provides ``reverse_iterator``, which adapts any Bidirectional Iterator +by inverting its direction of traversal. As with plain iterators, +iterator adaptors defined outside the Standard have become commonplace +in the literature: + +* Checked iter[13] adds bounds-checking to an existing iterator. + +* The iterators of the View Template Library[14], which adapts + containers, are themselves adaptors over the underlying iterators. + +* Smart iterators [5] adapt an iterator's dereferencing behavior by + applying a function object to the object being referenced and + returning the result. + +* Custom iterators [4], in which a variety of adaptor types are enumerated. + +* Compound iterators [1], which access a slice out of a container of containers. + +* Several iterator adaptors from the MTL [12]. The MTL contains a + strided iterator, where each call to ``operator++()`` moves the + iterator ahead by some constant factor, and a scaled iterator, which + multiplies the dereferenced value by some constant. + +.. [#concept] We use the term concept to mean a set of requirements + that a type must satisfy to be used with a particular template + parameter. + +.. [#mutable] The term mutable iterator refers to iterators over objects that + can be changed by assigning to the dereferenced iterator, while + constant iterator refers to iterators over objects that cannot be + modified. + +To fulfill the need for constructing adaptors, we propose the +``iterator_adaptor`` class template. Instantiations of +``iterator_adaptor`` serve as a base classes for new iterators, +providing the default behavior of forwarding all operations to the +underlying iterator. The user can selectively replace these features +in the derived iterator class. This proposal also includes a number +of more specialized adaptors, such as the ``transform_iterator`` that +applies some user-specified function during the dereference of the +iterator. + +======================== + Impact on the Standard +======================== + +This proposal is purely an addition to the C++ standard library. +However, note that this proposal relies on the proposal for New +Iterator Concepts. + +======== + Design +======== + +Iterator Concepts +================= + +This proposal is formulated in terms of the new ``iterator concepts`` +as proposed in n1550_, since user-defined and especially adapted +iterators suffer from the well known categorization problems that are +inherent to the current iterator categories. + +.. _n1550: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1550.htm + +This proposal does not strictly depend on proposal n1550_, as there +is a direct mapping between new and old categories. This proposal +could be reformulated using this mapping if n1550_ was not accepted. + +Interoperability +================ + +The question of iterator interoperability is poorly addressed in the +current standard. There are currently two defect reports that are +concerned with interoperability issues. + +Issue 179_ concerns the fact that mutable container iterator types +are only required to be convertible to the corresponding constant +iterator types, but objects of these types are not required to +interoperate in comparison or subtraction expressions. This situation +is tedious in practice and out of line with the way built in types +work. This proposal implements the proposed resolution to issue +179_, as most standard library implementations do nowadays. In other +words, if an iterator type A has an implicit or user defined +conversion to an iterator type B, the iterator types are interoperable +and the usual set of operators are available. + +Issue 280_ concerns the current lack of interoperability between +reverse iterator types. The proposed new reverse_iterator template +fixes the issues raised in 280. It provides the desired +interoperability without introducing unwanted overloads. + +.. _179: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#179 +.. _280: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#280 + + +Iterator Facade +=============== + +.. include:: iterator_facade_body.rst + +Iterator Adaptor +================ + +.. include:: iterator_adaptor_body.rst + +Specialized Adaptors +==================== + +This proposal also contains several examples of specialized adaptors +which were easily implemented using ``iterator_adaptor``: + +* ``indirect_iterator``, which iterates over iterators, pointers, + or smart pointers and applies an extra level of dereferencing. + +* A new ``reverse_iterator``, which inverts the direction of a Base + iterator's motion, while allowing adapted constant and mutable + iterators to interact in the expected ways (unlike those in most + implementations of C++98). + +* ``transform_iterator``, which applies a user-defined function object + to the underlying values when dereferenced. + +* ``filter_iterator``, which provides a view of an iterator range in + which some elements of the underlying range are skipped. + +.. _counting: + +* ``counting_iterator``, which adapts any incrementable type + (e.g. integers, iterators) so that incrementing/decrementing the + adapted iterator and dereferencing it produces successive values of + the Base type. + +* ``function_output_iterator``, which makes it easier to create custom + output iterators. + +Based on examples in the Boost library, users have generated many new +adaptors, among them a permutation adaptor which applies some +permutation to a random access iterator, and a strided adaptor, which +adapts a random access iterator by multiplying its unit of motion by a +constant factor. In addition, the Boost Graph Library (BGL) uses +iterator adaptors to adapt other graph libraries, such as LEDA [10] +and Stanford GraphBase [8], to the BGL interface (which requires C++ +Standard compliant iterators). + +=============== + Proposed Text +=============== + + +Header ```` synopsis [lib.iterator.helper.synopsis] +======================================================================= + + +:: + + struct use_default; + + struct iterator_core_access { /* implementation detail */ }; + + template < + class Derived + , class Value + , class CategoryOrTraversal + , class Reference = Value& + , class Difference = ptrdiff_t + > + class iterator_facade; + + template < + class Derived + , class Base + , class Value = use_default + , class CategoryOrTraversal = use_default + , class Reference = use_default + , class Difference = use_default + > + class iterator_adaptor; + + template < + class Iterator + , class Value = use_default + , class CategoryOrTraversal = use_default + , class Reference = use_default + , class Difference = use_default + > + class indirect_iterator; + + template + struct pointee; + + template + struct indirect_reference; + + template + class reverse_iterator; + + template < + class UnaryFunction + , class Iterator + , class Reference = use_default + , class Value = use_default + > + class transform_iterator; + + template + class filter_iterator; + + template < + class Incrementable + , class CategoryOrTraversal = use_default + , class Difference = use_default + > + class counting_iterator; + + template + class function_output_iterator; + + + +Iterator facade [lib.iterator.facade] +===================================== + +.. include:: iterator_facade_abstract.rst + +Class template ``iterator_facade`` +---------------------------------- + +.. include:: iterator_facade_ref.rst + +Iterator adaptor [lib.iterator.adaptor] +======================================= + +.. include:: iterator_adaptor_abstract.rst + +Class template ``iterator_adaptor`` +----------------------------------- + +.. include:: iterator_adaptor_ref.rst + + +Specialized adaptors [lib.iterator.special.adaptors] +==================================================== + + +The ``enable_if_convertible::type`` expression used in +this section is for exposition purposes. The converting constructors +for specialized adaptors should be only be in an overload set provided +that an object of type ``X`` is implicitly convertible to an object of +type ``Y``. +The signatures involving ``enable_if_convertible`` should behave +*as-if* ``enable_if_convertible`` were defined to be:: + + template enable_if_convertible_impl + {}; + + template <> enable_if_convertible_impl + { struct type; }; + + template + struct enable_if_convertible + : enable_if_convertible_impl::value> + {}; + +If an expression other than the default argument is used to supply +the value of a function parameter whose type is written in terms +of ``enable_if_convertible``, the program is ill-formed, no +diagnostic required. + +[*Note:* The ``enable_if_convertible`` approach uses SFINAE to +take the constructor out of the overload set when the types are not +implicitly convertible. +] + + +Indirect iterator +----------------- + +.. include:: indirect_iterator_abstract.rst + +Class template ``pointee`` +.................................... + +.. include:: pointee_ref.rst + +Class template ``indirect_reference`` +..................................... + +.. include:: indirect_reference_ref.rst + +Class template ``indirect_iterator`` +.................................... + +.. include:: indirect_iterator_ref.rst + +Reverse iterator +---------------- + +.. include:: reverse_iterator_abstract.rst + +Class template ``reverse_iterator`` +................................... + +.. include:: reverse_iterator_ref.rst + + +Transform iterator +------------------ + +.. include:: transform_iterator_abstract.rst + +Class template ``transform_iterator`` +..................................... + +.. include:: transform_iterator_ref.rst + + +Filter iterator +--------------- + +.. include:: filter_iterator_abstract.rst + + +Class template ``filter_iterator`` +.................................. + +.. include:: filter_iterator_ref.rst + + +Counting iterator +----------------- + +.. include:: counting_iterator_abstract.rst + +Class template ``counting_iterator`` +.................................... + +.. include:: counting_iterator_ref.rst + + +Function output iterator +------------------------ + +.. include:: func_output_iter_abstract.rst + +Class template ``function_output_iterator`` +........................................... + +.. include:: func_output_iter_ref.rst + + + + +.. LocalWords: Abrahams Siek Witt istream ostream iter MTL strided interoperate + LocalWords: CRTP metafunctions inlining lvalue JGS incrementable BGL LEDA cv + LocalWords: GraphBase struct ptrdiff UnaryFunction const int typename bool pp + LocalWords: lhs rhs SFINAE markup iff tmp OtherDerived OtherIterator DWA foo + LocalWords: dereferenceable subobject AdaptableUnaryFunction impl pre ifdef'd + LocalWords: OtherIncrementable Coplien diff --git a/libs/iterator/doc/facade_iterator_category.rst b/libs/iterator/doc/facade_iterator_category.rst new file mode 100644 index 00000000..6b60d851 --- /dev/null +++ b/libs/iterator/doc/facade_iterator_category.rst @@ -0,0 +1,53 @@ +.. |iterator-category| replace:: *iterator-category* +.. _iterator-category: + +.. parsed-literal:: + + *iterator-category*\ (C,R,V) := + if (C is convertible to std::input_iterator_tag + || C is convertible to std::output_iterator_tag + ) + return C + + else if (C is not convertible to incrementable_traversal_tag) + *the program is ill-formed* + + else return a type X satisfying the following two constraints: + + 1. X is convertible to X1, and not to any more-derived + type, where X1 is defined by: + + if (R is a reference type + && C is convertible to forward_traversal_tag) + { + if (C is convertible to random_access_traversal_tag) + X1 = random_access_iterator_tag + else if (C is convertible to bidirectional_traversal_tag) + X1 = bidirectional_iterator_tag + else + X1 = forward_iterator_tag + } + else + { + if (C is convertible to single_pass_traversal_tag + && R is convertible to V) + X1 = input_iterator_tag + else + X1 = C + } + + 2. |category-to-traversal|_\ (X) is convertible to the most + derived traversal tag type to which X is also + convertible, and not to any more-derived traversal tag + type. + +.. |category-to-traversal| replace:: *category-to-traversal* +.. _`category-to-traversal`: new-iter-concepts.html#category-to-traversal + +[Note: the intention is to allow ``iterator_category`` to be one of +the five original category tags when convertibility to one of the +traversal tags would add no information] + +.. Copyright David Abrahams 2004. Use, modification and distribution is +.. subject to 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/libs/iterator/doc/filter_iterator.html b/libs/iterator/doc/filter_iterator.html new file mode 100644 index 00000000..bd574f00 --- /dev/null +++ b/libs/iterator/doc/filter_iterator.html @@ -0,0 +1,413 @@ + + + + + + +Filter Iterator + + + + + + + + + + + diff --git a/libs/iterator/doc/filter_iterator.pdf b/libs/iterator/doc/filter_iterator.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1d8a804fdc30cb43fc63898603fc0f33cb134b9f GIT binary patch literal 69532 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 literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/filter_iterator.rst b/libs/iterator/doc/filter_iterator.rst new file mode 100644 index 00000000..cfa8642c --- /dev/null +++ b/libs/iterator/doc/filter_iterator.rst @@ -0,0 +1,33 @@ +.. 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) + ++++++++++++++++++ + Filter Iterator ++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: + + .. include:: filter_iterator_abstract.rst + +.. contents:: Table of Contents + +``filter_iterator`` synopsis +............................ + +.. include:: filter_iterator_ref.rst +.. include:: make_filter_iterator.rst + +.. include:: filter_iterator_eg.rst diff --git a/libs/iterator/doc/filter_iterator_abstract.rst b/libs/iterator/doc/filter_iterator_abstract.rst new file mode 100644 index 00000000..9524efab --- /dev/null +++ b/libs/iterator/doc/filter_iterator_abstract.rst @@ -0,0 +1,15 @@ +.. Copyright David Abrahams 2006. 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 filter iterator adaptor creates a view of an iterator range in +which some elements of the range are skipped. A predicate function +object controls which elements are skipped. When the predicate is +applied to an element, if it returns ``true`` then the element is +retained and if it returns ``false`` then the element is skipped +over. When skipping over elements, it is necessary for the filter +adaptor to know when to stop so as to avoid going past the end of the +underlying range. A filter iterator is therefore constructed with pair +of iterators indicating the range of elements in the unfiltered +sequence to be traversed. + diff --git a/libs/iterator/doc/filter_iterator_eg.rst b/libs/iterator/doc/filter_iterator_eg.rst new file mode 100644 index 00000000..dc2770e1 --- /dev/null +++ b/libs/iterator/doc/filter_iterator_eg.rst @@ -0,0 +1,72 @@ +.. Copyright David Abrahams 2006. 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) + +Example +....... + +This example uses ``filter_iterator`` and then +``make_filter_iterator`` to output only the positive integers from an +array of integers. Then ``make_filter_iterator`` is is used to output +the integers greater than ``-2``. + +:: + + struct is_positive_number { + bool operator()(int x) { return 0 < x; } + }; + + int main() + { + int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 }; + const int N = sizeof(numbers_)/sizeof(int); + + typedef int* base_iterator; + base_iterator numbers(numbers_); + + // Example using filter_iterator + typedef boost::filter_iterator + FilterIter; + + is_positive_number predicate; + FilterIter filter_iter_first(predicate, numbers, numbers + N); + FilterIter filter_iter_last(predicate, numbers + N, numbers + N); + + std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + // Example using make_filter_iterator() + std::copy(boost::make_filter_iterator(numbers, numbers + N), + boost::make_filter_iterator(numbers + N, numbers + N), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + // Another example using make_filter_iterator() + std::copy( + boost::make_filter_iterator( + std::bind2nd(std::greater(), -2) + , numbers, numbers + N) + + , boost::make_filter_iterator( + std::bind2nd(std::greater(), -2) + , numbers + N, numbers + N) + + , std::ostream_iterator(std::cout, " ") + ); + + std::cout << std::endl; + + return boost::exit_success; + } + + +The output is:: + + 4 5 8 + 4 5 8 + 0 -1 4 5 8 + + +The source code for this example can be found `here`__. + +__ ../example/filter_iterator_example.cpp diff --git a/libs/iterator/doc/filter_iterator_ref.rst b/libs/iterator/doc/filter_iterator_ref.rst new file mode 100644 index 00000000..1759788c --- /dev/null +++ b/libs/iterator/doc/filter_iterator_ref.rst @@ -0,0 +1,177 @@ +.. Copyright David Abrahams, Jeremy Siek, and Thomas Witt +.. 2004. Use, modification and distribution is subject to 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) + +:: + + template + class filter_iterator + { + public: + typedef iterator_traits::value_type value_type; + typedef iterator_traits::reference reference; + typedef iterator_traits::pointer pointer; + typedef iterator_traits::difference_type difference_type; + typedef /* see below */ iterator_category; + + filter_iterator(); + filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); + filter_iterator(Iterator x, Iterator end = Iterator()); + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + ); + Predicate predicate() const; + Iterator end() const; + Iterator const& base() const; + reference operator*() const; + filter_iterator& operator++(); + private: + Predicate m_pred; // exposition only + Iterator m_iter; // exposition only + Iterator m_end; // exposition only + }; + + +If ``Iterator`` models Readable Lvalue Iterator and Bidirectional Traversal +Iterator then ``iterator_category`` is convertible to +``std::bidirectional_iterator_tag``. +Otherwise, if ``Iterator`` models Readable Lvalue Iterator and Forward Traversal +Iterator then ``iterator_category`` is convertible to +``std::forward_iterator_tag``. +Otherwise ``iterator_category`` is +convertible to ``std::input_iterator_tag``. + + +``filter_iterator`` requirements +................................ + +The ``Iterator`` argument shall meet the requirements of Readable +Iterator and Single Pass Iterator or it shall meet the requirements of +Input Iterator. + +The ``Predicate`` argument must be Assignable, Copy Constructible, and +the expression ``p(x)`` must be valid where ``p`` is an object of type +``Predicate``, ``x`` is an object of type +``iterator_traits::value_type``, and where the type of +``p(x)`` must be convertible to ``bool``. + + +``filter_iterator`` models +.......................... + +The concepts that ``filter_iterator`` models are dependent on which +concepts the ``Iterator`` argument models, as specified in the +following tables. + ++---------------------------------+------------------------------------------+ +|If ``Iterator`` models |then ``filter_iterator`` models | ++=================================+==========================================+ +|Single Pass Iterator |Single Pass Iterator | ++---------------------------------+------------------------------------------+ +|Forward Traversal Iterator |Forward Traversal Iterator | ++---------------------------------+------------------------------------------+ +|Bidirectional Traversal Iterator |Bidirectional Traversal Iterator | ++---------------------------------+------------------------------------------+ + ++--------------------------------+----------------------------------------------+ +| If ``Iterator`` models | then ``filter_iterator`` models | ++================================+==============================================+ +| Readable Iterator | Readable Iterator | ++--------------------------------+----------------------------------------------+ +| Writable Iterator | Writable Iterator | ++--------------------------------+----------------------------------------------+ +| Lvalue Iterator | Lvalue Iterator | ++--------------------------------+----------------------------------------------+ + ++-------------------------------------------------------+---------------------------------+ +|If ``Iterator`` models | then ``filter_iterator`` models | ++=======================================================+=================================+ +|Readable Iterator, Single Pass Iterator | Input Iterator | ++-------------------------------------------------------+---------------------------------+ +|Readable Lvalue Iterator, Forward Traversal Iterator | Forward Iterator | ++-------------------------------------------------------+---------------------------------+ +|Writable Lvalue Iterator, Forward Traversal Iterator | Mutable Forward Iterator | ++-------------------------------------------------------+---------------------------------+ +|Writable Lvalue Iterator, Bidirectional Iterator | Mutable Bidirectional Iterator | ++-------------------------------------------------------+---------------------------------+ + + +``filter_iterator`` is interoperable with ``filter_iterator`` +if and only if ``X`` is interoperable with ``Y``. + + +``filter_iterator`` operations +.............................. + +In addition to those operations required by the concepts that +``filter_iterator`` models, ``filter_iterator`` provides the following +operations. + + +``filter_iterator();`` + +:Requires: ``Predicate`` and ``Iterator`` must be Default Constructible. +:Effects: Constructs a ``filter_iterator`` whose``m_pred``, ``m_iter``, and ``m_end`` + members are a default constructed. + + +``filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());`` + +:Effects: Constructs a ``filter_iterator`` where ``m_iter`` is either + the first position in the range ``[x,end)`` such that ``f(*m_iter) == true`` + or else``m_iter == end``. The member ``m_pred`` is constructed from + ``f`` and ``m_end`` from ``end``. + + + +``filter_iterator(Iterator x, Iterator end = Iterator());`` + +:Requires: ``Predicate`` must be Default Constructible and + ``Predicate`` is a class type (not a function pointer). +:Effects: Constructs a ``filter_iterator`` where ``m_iter`` is either + the first position in the range ``[x,end)`` such that ``m_pred(*m_iter) == true`` + or else``m_iter == end``. The member ``m_pred`` is default constructed. + + +:: + + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + );`` + +:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. +:Effects: Constructs a filter iterator whose members are copied from ``t``. + + +``Predicate predicate() const;`` + +:Returns: ``m_pred`` + + +``Iterator end() const;`` + +:Returns: ``m_end`` + + +``Iterator const& base() const;`` + +:Returns: ``m_iterator`` + + + +``reference operator*() const;`` + +:Returns: ``*m_iter`` + + +``filter_iterator& operator++();`` + +:Effects: Increments ``m_iter`` and then continues to + increment ``m_iter`` until either ``m_iter == m_end`` + or ``m_pred(*m_iter) == true``. +:Returns: ``*this`` diff --git a/libs/iterator/doc/func_output_iter_abstract.rst b/libs/iterator/doc/func_output_iter_abstract.rst new file mode 100644 index 00000000..d4a700f5 --- /dev/null +++ b/libs/iterator/doc/func_output_iter_abstract.rst @@ -0,0 +1,12 @@ +.. Copyright David Abrahams 2006. 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 function output iterator adaptor makes it easier to create custom +output iterators. The adaptor takes a unary function and creates a +model of Output Iterator. Each item assigned to the output iterator is +passed as an argument to the unary function. The motivation for this +iterator is that creating a conforming output iterator is non-trivial, +particularly because the proper implementation usually requires a +proxy object. + diff --git a/libs/iterator/doc/func_output_iter_ref.rst b/libs/iterator/doc/func_output_iter_ref.rst new file mode 100644 index 00000000..e00eab75 --- /dev/null +++ b/libs/iterator/doc/func_output_iter_ref.rst @@ -0,0 +1,73 @@ +.. Copyright David Abrahams 2006. 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) + +Header +...... + +:: + + #include + +:: + + template + class function_output_iterator { + public: + typedef std::output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + explicit function_output_iterator(); + + explicit function_output_iterator(const UnaryFunction& f); + + /* see below */ operator*(); + function_output_iterator& operator++(); + function_output_iterator& operator++(int); + private: + UnaryFunction m_f; // exposition only + }; + + + +``function_output_iterator`` requirements +......................................... + +``UnaryFunction`` must be Assignable and Copy Constructible. + + + +``function_output_iterator`` models +................................... + +``function_output_iterator`` is a model of the Writable and +Incrementable Iterator concepts. + + + +``function_output_iterator`` operations +....................................... + +``explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());`` + +:Effects: Constructs an instance of ``function_output_iterator`` + with ``m_f`` constructed from ``f``. + + +``operator*();`` + +:Returns: An object ``r`` of unspecified type such that ``r = t`` + is equivalent to ``m_f(t)`` for all ``t``. + + +``function_output_iterator& operator++();`` + +:Returns: ``*this`` + + +``function_output_iterator& operator++(int);`` + +:Returns: ``*this`` diff --git a/libs/iterator/doc/function_input_iterator.html b/libs/iterator/doc/function_input_iterator.html new file mode 100644 index 00000000..e097a467 --- /dev/null +++ b/libs/iterator/doc/function_input_iterator.html @@ -0,0 +1,142 @@ + + + + + + + + + + + +
+ + +++ + + + + + +
Author:Dean Michael Berris
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)
+
+

Function Input Iterator

+

The Function Input Iterator allows for creating iterators that encapsulate +a nullary function object and a state object which tracks the number of times +the iterator has been incremented. A Function Input Iterator models the +InputIterator concept and is useful for creating bounded input iterators.

+

Like the Generator Iterator, the Function Input Iterator takes a function +that models the Generator concept (which is basically a nullary or 0-arity +function object). Each increment of the function Function Input Iterator +invokes the generator function and stores the value in the iterator. When +the iterator is dereferenced the stored value is returned.

+

The Function Input Iterator encapsulates a state object which models the +Incrementable Concept and the EqualityComparable Concept. These concepts are +described below as:

+
+

Incrementable Concept

+

A type models the Incrementable Concept when it supports the pre- and post- +increment operators. For a given object i with type I, the following +constructs should be valid:

+ +++++ + + + + + + + + + + + + +
Construct Description Return Type
i++Post-increment i.I
++iPre-increment i.I&
+

NOTE: An Incrementable type should also be DefaultConstructible.

+
+
+

Synopsis

+
+namespace {
+    template <class Function, class State>
+    class function_input_iterator;
+
+    template <class Function, class State>
+    typename function_input_iterator<Function, State>
+    make_function_input_iterator(Function & f);
+
+    struct infinite;
+}
+
+
+
+

Function Input Iterator Class

+

The class Function Input Iterator class takes two template parameters +Function and State. These two template parameters tell the +Function Input Iterator the type of the function to encapsulate and +the type of the internal state value to hold.

+

The State parameter is important in cases where you want to +control the type of the counter which determines whether two iterators +are at the same state. This allows for creating a pair of iterators which +bound the range of the invocations of the encapsulated functions.

+
+
+

Examples

+

The following example shows how we use the function input iterator class +in cases where we want to create bounded (lazy) generated ranges.

+
+struct generator {
+    typedef int result_type;
+    generator() { srand(time(0)); }
+    result_type operator() () const {
+        return rand();
+    }
+};
+
+int main(int argc, char * argv[]) {
+    generator f;
+    copy(
+            make_function_input_iterator(f, 0),
+            make_function_input_iterator(f, 10),
+            ostream_iterator<int>(cout, " ")
+        );
+    return 0;
+}
+
+

Here we can see that we've bounded the number of invocations using an int +that counts from 0 to 10. Say we want to create an endless stream +of random numbers and encapsulate that in a pair of integers, we can do +it with the boost::infinite helper class.

+
+copy(
+        make_function_input_iterator(f,infinite()),
+        make_function_input_iterator(f,infinite()),
+        ostream_iterator<int>(count, " ")
+    );
+
+

Above, instead of creating a huge vector we rely on the STL copy algorithm +to traverse the function input iterator and call the function object f +as it increments the iterator. The special property of boost::infinite +is that equating two instances always yield false -- and that incrementing +an instance of boost::infinite doesn't do anything. This is an efficient +way of stating that the iterator range provided by two iterators with an +encapsulated infinite state will definitely be infinite.

+
+
+
+ + + diff --git a/libs/iterator/doc/function_input_iterator.rst b/libs/iterator/doc/function_input_iterator.rst new file mode 100644 index 00000000..a16b249c --- /dev/null +++ b/libs/iterator/doc/function_input_iterator.rst @@ -0,0 +1,132 @@ +:Author: + `Dean Michael Berris `_ + +: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) + +:Copyright: + Copyright 2012 Google, Inc. + +Function Input Iterator +======================= + +The Function Input Iterator allows for creating iterators that encapsulate +a nullary function object and a state object which tracks the number of times +the iterator has been incremented. A Function Input Iterator models the +`InputIterator`_ concept and is useful for creating bounded input iterators. + +.. _InputIterator: http://www.sgi.com/tech/stl/InputIterator.html + +The Function Input Iterator takes a function that models the Generator_ concept +(which is basically a nullary or 0-arity function object). The first dereference +of the iterator at a given position invokes the generator function and stores +and returns the result; subsequent dereferences at the same position simply +return the same stored result. Incrementing the iterator places it at a new +position, hence a subsequent dereference will generate a new value via another +invokation of the generator function. This ensures the generator function is +invoked precisely when the iterator is requested to return a (new) value. + +.. _Generator: http://www.sgi.com/tech/stl/Generator.html + +The Function Input Iterator encapsulates a state object which models the +`Incrementable Concept`_ and the EqualityComparable_ Concept. These concepts are +described below as: + +.. _EqualityComparable: http://www.sgi.com/tech/stl/EqualityComparable.html + +Incrementable Concept +--------------------- + +A type models the Incrementable Concept when it supports the pre- and post- +increment operators. For a given object ``i`` with type ``I``, the following +constructs should be valid: + +========= ================= =========== +Construct Description Return Type +----------------------------------------- +i++ Post-increment i. I +++i Pre-increment i. I& +========= ================= =========== + +NOTE: An Incrementable type should also be DefaultConstructible_. + +.. _DefaultConstructible: http://www.sgi.com/tech/stl/DefaultConstructible.html + +Synopsis +-------- + +:: + + namespace { + template + class function_input_iterator; + + template + typename function_input_iterator + make_function_input_iterator(Function & f, State s); + + struct infinite; + } + +Function Input Iterator Class +----------------------------- + +The class Function Input Iterator class takes two template parameters +``Function`` and ``State``. These two template parameters tell the +Function Input Iterator the type of the function to encapsulate and +the type of the internal state value to hold. + +The ``State`` parameter is important in cases where you want to +control the type of the counter which determines whether two iterators +are at the same state. This allows for creating a pair of iterators which +bound the range of the invocations of the encapsulated functions. + +Examples +-------- + +The following example shows how we use the function input iterator class +in cases where we want to create bounded (lazy) generated ranges. + +:: + + struct generator { + typedef int result_type; + generator() { srand(time(0)); } + result_type operator() () const { + return rand(); + } + }; + + int main(int argc, char * argv[]) { + generator f; + copy( + make_function_input_iterator(f, 0), + make_function_input_iterator(f, 10), + ostream_iterator(cout, " ") + ); + return 0; + } + +Here we can see that we've bounded the number of invocations using an ``int`` +that counts from ``0`` to ``10``. Say we want to create an endless stream +of random numbers and encapsulate that in a pair of integers, we can do +it with the ``boost::infinite`` helper class. + +:: + + copy( + make_function_input_iterator(f,infinite()), + make_function_input_iterator(f,infinite()), + ostream_iterator(cout, " ") + ); + +Above, instead of creating a huge vector we rely on the STL copy algorithm +to traverse the function input iterator and call the function object f +as it increments the iterator. The special property of ``boost::infinite`` +is that equating two instances always yield false -- and that incrementing +an instance of ``boost::infinite`` doesn't do anything. This is an efficient +way of stating that the iterator range provided by two iterators with an +encapsulated infinite state will definitely be infinite. + + diff --git a/libs/iterator/doc/function_output_iterator.html b/libs/iterator/doc/function_output_iterator.html new file mode 100644 index 00000000..1bae71b8 --- /dev/null +++ b/libs/iterator/doc/function_output_iterator.html @@ -0,0 +1,191 @@ + + + + + + +Function Output Iterator + + + + + + + +
+

Function Output Iterator

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2006-09-11
Copyright:Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
+ + + + +++ + + + +
abstract: + + +The function output iterator adaptor makes it easier to create custom +output iterators. The adaptor takes a unary function and creates a +model of Output Iterator. Each item assigned to the output iterator is +passed as an argument to the unary function. The motivation for this +iterator is that creating a conforming output iterator is non-trivial, +particularly because the proper implementation usually requires a +proxy object.
+ + + + + +
+

function_output_iterator requirements

+

UnaryFunction must be Assignable and Copy Constructible.

+
+
+

function_output_iterator models

+

function_output_iterator is a model of the Writable and +Incrementable Iterator concepts.

+
+
+

function_output_iterator operations

+

explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());

+ +++ + + + +
Effects:Constructs an instance of function_output_iterator +with m_f constructed from f.
+

operator*();

+ +++ + + + +
Returns:An object r of unspecified type such that r = t +is equivalent to m_f(t) for all t.
+

function_output_iterator& operator++();

+ +++ + + + +
Returns:*this
+

function_output_iterator& operator++(int);

+ +++ + + + +
Returns:*this
+ + + +
+
+

Example

+
+struct string_appender
+{
+    string_appender(std::string& s)
+        : m_str(&s)
+    {}
+
+    void operator()(const std::string& x) const
+    {
+        *m_str += x;
+    }
+
+    std::string* m_str;
+};
+
+int main(int, char*[])
+{
+  std::vector<std::string> x;
+  x.push_back("hello");
+  x.push_back(" ");
+  x.push_back("world");
+  x.push_back("!");
+
+  std::string s = "";
+  std::copy(x.begin(), x.end(),
+            boost::make_function_output_iterator(string_appender(s)));
+
+  std::cout << s << std::endl;
+
+  return 0;
+}
+
+
+
+ + + diff --git a/libs/iterator/doc/function_output_iterator.pdf b/libs/iterator/doc/function_output_iterator.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cef2274c8785dcb935ad339b2da106d77024be0d GIT binary patch literal 57133 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 OAVB@*O<`FP%>M&YdnG~u literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/function_output_iterator.rst b/libs/iterator/doc/function_output_iterator.rst new file mode 100644 index 00000000..8018af5a --- /dev/null +++ b/libs/iterator/doc/function_output_iterator.rst @@ -0,0 +1,28 @@ +.. 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) + +++++++++++++++++++++++++++ + Function Output Iterator +++++++++++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: + + .. include:: func_output_iter_abstract.rst + +.. contents:: Table of Contents + +.. include:: func_output_iter_ref.rst +.. include:: function_output_iterator_eg.rst \ No newline at end of file diff --git a/libs/iterator/doc/function_output_iterator_eg.rst b/libs/iterator/doc/function_output_iterator_eg.rst new file mode 100644 index 00000000..ab09f2dd --- /dev/null +++ b/libs/iterator/doc/function_output_iterator_eg.rst @@ -0,0 +1,39 @@ +.. Copyright David Abrahams 2006. 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) + +Example +....... + +:: + + struct string_appender + { + string_appender(std::string& s) + : m_str(&s) + {} + + void operator()(const std::string& x) const + { + *m_str += x; + } + + std::string* m_str; + }; + + int main(int, char*[]) + { + std::vector x; + x.push_back("hello"); + x.push_back(" "); + x.push_back("world"); + x.push_back("!"); + + std::string s = ""; + std::copy(x.begin(), x.end(), + boost::make_function_output_iterator(string_appender(s))); + + std::cout << s << std::endl; + + return 0; + } diff --git a/libs/iterator/doc/generate.py b/libs/iterator/doc/generate.py new file mode 100644 index 00000000..f5d0de80 --- /dev/null +++ b/libs/iterator/doc/generate.py @@ -0,0 +1,32 @@ +#!/usr/bin/python +# Copyright David Abrahams 2004. Use, modification and distribution is +# subject to 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) + +# +# Generate html, TeX, and PDF versions of all the source files +# +import os +import sys + +from syscmd import syscmd +from sources import sources + +if 0: + for s in sources: + syscmd('boosthtml %s' % s) +else: + extensions = ('html', 'pdf') + + if len(sys.argv) > 1: + extensions = sys.argv[1:] + + all = [ '%s.%s' % (os.path.splitext(s)[0],ext) + for ext in extensions + for s in sources + ] + + print 'make %s' % ' '.join(all) + syscmd('make %s' % ' '.join(all)) + + diff --git a/libs/iterator/doc/generator_iterator.htm b/libs/iterator/doc/generator_iterator.htm new file mode 100644 index 00000000..b0e376eb --- /dev/null +++ b/libs/iterator/doc/generator_iterator.htm @@ -0,0 +1,163 @@ + + + + + + + + Generator Iterator Adaptor Documentation + + + + boost.png (6897 bytes) + +

Generator Iterator Adaptor

+ +

Defined in header boost/generator_iterator.hpp

+ +

The generator iterator adaptor makes it easier to create custom input + iterators from 0-ary functions and function objects. The adaptor takes a + Generator and + creates a model of Input Iterator. Each + increment retrieves an item from the generator and makes it available to be + retrieved by dereferencing. The motivation for this iterator is that some + concepts can be more naturally expressed as a generator, while most STL + algorithms expect an iterator. An example is the Random Number library.

+ +

Synopsis

+ +
+
+namespace boost {
+  template <class Generator>
+  class generator_iterator_policies;
+
+  template <class Generator>
+  class generator_iterator_generator;
+
+  template <class Generator>
+  typename generator_iterator_generator<Generator>::type
+  make_generator_iterator(Generator & gen);
+}
+
+
+
+ +

The Generator Iterator Generator Class

+ +

The class generator_iterator_generator is a helper class whose purpose + is to construct a generator iterator type. The template parameter for this + class is the Generator function object type that is being wrapped. The + generator iterator adaptor only holds a reference (or pointer) to the + function object, therefore the function object must outlive the generator + iterator adaptor constructed from it.

+
+template <class Generator>
+class generator_iterator_generator
+{
+public:
+  typedef unspecified type; // the resulting generator iterator type 
+}
+
+ +

Template Parameters

+ + + + + + + + + + + + + +
ParameterDescription
GeneratorThe generator (0-ary function object) type being wrapped. The + return type of the function must be defined as + Generator::result_type. The function object must be a model of + Generator.
+ +

Concept Model

+ +

The generator iterator class is a model of Input Iterator.

+ +

Members

+ +

The generator iterator implements the member functions and operators + required of the Input Iterator + concept.

+
+ +

The + Generator Iterator Object Generator

+ +

The make_generator_iterator() function provides a convenient + way to create generator iterator objects. The function saves the user the + trouble of explicitly writing out the iterator types.

+ +
+
+template <class Generator>
+typename generator_iterator_generator<Generator>::type
+make_generator_iterator(Generator & gen);
+
+
+
+ +

Example

+ +

The following program shows how generator_iterator + transforms a generator into an input iterator.

+ +
+
+#include <iostream>
+#include <boost/generator_iterator.hpp>
+
+class my_generator
+{
+public:
+  typedef int result_type;
+  my_generator() : state(0) { }
+  int operator()() { return ++state; }
+private:
+  int state;
+};
+
+int main()
+{
+  my_generator gen;
+  boost::generator_iterator_generator<my_generator>::type it = boost::make_generator_iterator(gen);
+  for(int i = 0; i < 10; ++i, ++it)
+    std::cout << *it << std::endl;
+}
+
+
+
+ +

Valid HTML 4.01 Transitional

+ +

Revised + 05 December, 2006

+ +

Copyright © 2001 Jens Maurer

+ +

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/libs/iterator/doc/index.html b/libs/iterator/doc/index.html new file mode 100644 index 00000000..62274b67 --- /dev/null +++ b/libs/iterator/doc/index.html @@ -0,0 +1,252 @@ + + + + + + +The Boost.Iterator Library Boost + + + + + + + diff --git a/libs/iterator/doc/index.rst b/libs/iterator/doc/index.rst new file mode 100644 index 00000000..8770b829 --- /dev/null +++ b/libs/iterator/doc/index.rst @@ -0,0 +1,355 @@ +.. 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.Iterator Library |(logo)|__ ++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. |(logo)| image:: ../../../boost.png + :alt: Boost + +__ ../../../index.htm + + +------------------------------------- + + +:Authors: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@styleadvisor.com +:organizations: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, `Zephyr Associates, Inc.`_ +:date: $Date$ + +:copyright: Copyright David Abrahams, Jeremy Siek, Thomas Witt 2003. + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Zephyr Associates, Inc.`: http://www.styleadvisor.com + +:Abstract: The Boost Iterator Library contains two parts. The first + is a system of concepts_ which extend the C++ standard + iterator requirements. The second is a framework of + components for building iterators based on these + extended concepts and includes several useful iterator + adaptors. The extended iterator concepts have been + carefully designed so that old-style iterators + can fit in the new concepts and so that new-style + iterators will be compatible with old-style algorithms, + though algorithms may need to be updated if they want to + take full advantage of the new-style iterator + capabilities. Several components of this library have + been accepted into the C++ standard technical report. + The components of the Boost Iterator Library replace the + older Boost Iterator Adaptor Library. + +.. _concepts: http://www.boost.org/more/generic_programming.html#concept + +.. contents:: **Table of Contents** + + +------------------------------------- + + +===================== + New-Style Iterators +===================== + +The iterator categories defined in C++98 are extremely limiting +because they bind together two orthogonal concepts: traversal and +element access. For example, because a random access iterator is +required to return a reference (and not a proxy) when dereferenced, +it is impossible to capture the capabilities of +``vector::iterator`` using the C++98 categories. This is the +infamous "``vector`` is not a container, and its iterators +aren't random access iterators", debacle about which Herb Sutter +wrote two papers for the standards comittee (n1185_ and n1211_), +and a `Guru of the Week`__. New-style iterators go well beyond +patching up ``vector``, though: there are lots of other +iterators already in use which can't be adequately represented by +the existing concepts. For details about the new iterator +concepts, see our + +.. _n1185: http://www.gotw.ca/publications/N1185.pdf +.. _n1211: http://www.gotw.ca/publications/N1211.pdf +__ http://www.gotw.ca/gotw/050.htm + + + `Standard Proposal For New-Style Iterators`__ (PDF__) + +__ new-iter-concepts.html +__ new-iter-concepts.pdf + +============================= + Iterator Facade and Adaptor +============================= + +Writing standard-conforming iterators is tricky, but the need comes +up often. In order to ease the implementation of new iterators, +the Boost.Iterator library provides the |facade| class template, +which implements many useful defaults and compile-time checks +designed to help the iterator author ensure that his iterator is +correct. + +It is also common to define a new iterator that is similar to some +underlying iterator or iterator-like type, but that modifies some +aspect of the underlying type's behavior. For that purpose, the +library supplies the |adaptor| class template, which is specially +designed to take advantage of as much of the underlying type's +behavior as possible. + +The documentation for these two classes can be found at the following +web pages: + +* |facade|_ (PDF__) + +* |adaptor|_ (PDF__) + + +.. |facade| replace:: ``iterator_facade`` +.. _facade: iterator_facade.html +__ iterator_facade.pdf + +.. |adaptor| replace:: ``iterator_adaptor`` +.. _adaptor: iterator_adaptor.html +__ iterator_adaptor.pdf + +Both |facade| and |adaptor| as well as many of the `specialized +adaptors`_ mentioned below have been proposed for standardization; +see our + + `Standard Proposal For Iterator Facade and Adaptor`__ (PDF__) + +for more details. + +__ facade-and-adaptor.html +__ facade-and-adaptor.pdf + +====================== + Specialized Adaptors +====================== + +The iterator library supplies a useful suite of standard-conforming +iterator templates based on the Boost `iterator facade and adaptor`_. + +* |counting|_ (PDF__): an iterator over a sequence of consecutive values. + Implements a "lazy sequence" + +* |filter|_ (PDF__): an iterator over the subset of elements of some + sequence which satisfy a given predicate + +* |function_input|_ (PDF__): an input iterator wrapping a generator (nullary + function object); each time the iterator is dereferenced, the function object + is called to get the value to return. + +* |function_output|_ (PDF__): an output iterator wrapping a unary function + object; each time an element is written into the dereferenced + iterator, it is passed as a parameter to the function object. + +* |generator|_: an input iterator wrapping a generator (nullary + function object); each time the iterator is dereferenced, the function object + is called to get the value to return. This is an outdated analogue of |function_input|_. + +* |indirect|_ (PDF__): an iterator over the objects *pointed-to* by the + elements of some sequence. + +* |permutation|_ (PDF__): an iterator over the elements of some random-access + sequence, rearranged according to some sequence of integer indices. + +* |reverse|_ (PDF__): an iterator which traverses the elements of some + bidirectional sequence in reverse. Corrects many of the + shortcomings of C++98's ``std::reverse_iterator``. + +* |shared|_: an iterator over elements of a container whose + lifetime is maintained by a |shared_ptr|_ stored in the iterator. + +* |transform|_ (PDF__): an iterator over elements which are the result of + applying some functional transformation to the elements of an + underlying sequence. This component also replaces the old + ``projection_iterator_adaptor``. + +* |zip|_ (PDF__): an iterator over tuples of the elements at corresponding + positions of heterogeneous underlying iterators. + +.. |counting| replace:: ``counting_iterator`` +.. _counting: counting_iterator.html +__ counting_iterator.pdf + +.. |filter| replace:: ``filter_iterator`` +.. _filter: filter_iterator.html +__ filter_iterator.pdf + +.. |function_input| replace:: ``function_input_iterator`` +.. _function_input: function_input_iterator.html +__ function_input_iterator.pdf + +.. |function_output| replace:: ``function_output_iterator`` +.. _function_output: function_output_iterator.html +__ function_output_iterator.pdf + +.. |generator| replace:: ``generator_iterator`` +.. _generator: generator_iterator.htm + +.. |indirect| replace:: ``indirect_iterator`` +.. _indirect: indirect_iterator.html +__ indirect_iterator.pdf + +.. |permutation| replace:: ``permutation_iterator`` +.. _permutation: permutation_iterator.html +__ permutation_iterator.pdf + +.. |reverse| replace:: ``reverse_iterator`` +.. _reverse: reverse_iterator.html +__ reverse_iterator.pdf + +.. |shared| replace:: ``shared_container_iterator`` +.. _shared: ../../utility/shared_container_iterator.html + +.. |transform| replace:: ``transform_iterator`` +.. _transform: transform_iterator.html +__ transform_iterator.pdf + +.. |zip| replace:: ``zip_iterator`` +.. _zip: zip_iterator.html +__ zip_iterator.pdf + +.. |shared_ptr| replace:: ``shared_ptr`` +.. _shared_ptr: ../../smart_ptr/shared_ptr.htm + +==================== + Iterator Utilities +==================== + +Operations +---------- + +The standard library does not handle new-style iterators properly, +because it knows nothing about the iterator traversal concepts. +The Boost.Iterator library provides implementations that fully understand +the new concepts for the two basic operations: + +- |advance|_ +- |distance|_ + +.. |advance| replace:: ``advance`` +.. _advance: advance.html + +.. |distance| replace:: ``distance`` +.. _distance: distance.html + +Traits +------ + +* |pointee|_ (PDF__): Provides the capability to deduce the referent types + of pointers, smart pointers and iterators in generic code. Used + in |indirect|. + +* |iterator_traits|_ (PDF__): Provides MPL_\ -compatible metafunctions which + retrieve an iterator's traits. Also corrects for the deficiencies + of broken implementations of ``std::iterator_traits``. + +.. * |interoperable|_ (PDF__): Provides an MPL_\ -compatible metafunction for + testing iterator interoperability + +.. |pointee| replace:: ``pointee.hpp`` +.. _pointee: pointee.html +__ pointee.pdf + +.. |iterator_traits| replace:: ``iterator_traits.hpp`` +.. _iterator_traits: iterator_traits.html +__ iterator_traits.pdf + +.. |interoperable| replace:: ``interoperable.hpp`` +.. _interoperable: interoperable.html +.. comment! __ interoperable.pdf + +.. _MPL: ../../mpl/doc/index.html + +Testing and Concept Checking +---------------------------- + +* |iterator_concepts|_ (PDF__): Concept checking classes for the new iterator concepts. + +* |iterator_archetypes|_ (PDF__): Concept archetype classes for the new iterators concepts. + +.. |iterator_concepts| replace:: ``iterator_concepts.hpp`` +.. _iterator_concepts: iterator_concepts.html +__ iterator_concepts.pdf + +.. |iterator_archetypes| replace:: ``iterator_archetypes.hpp`` +.. _iterator_archetypes: iterator_archetypes.html +__ iterator_archetypes.pdf + +======================================================= + Upgrading from the old Boost Iterator Adaptor Library +======================================================= + +.. _Upgrading: + +If you have been using the old Boost Iterator Adaptor library to +implement iterators, you probably wrote a ``Policies`` class which +captures the core operations of your iterator. In the new library +design, you'll move those same core operations into the body of the +iterator class itself. If you were writing a family of iterators, +you probably wrote a `type generator`_ to build the +``iterator_adaptor`` specialization you needed; in the new library +design you don't need a type generator (though may want to keep it +around as a compatibility aid for older code) because, due to the +use of the Curiously Recurring Template Pattern (CRTP) [Cop95]_, +you can now define the iterator class yourself and acquire +functionality through inheritance from ``iterator_facade`` or +``iterator_adaptor``. As a result, you also get much finer control +over how your iterator works: you can add additional constructors, +or even override the iterator functionality provided by the +library. + +.. _`type generator`: http://www.boost.org/more/generic_programming.html#type_generator + +If you're looking for the old ``projection_iterator`` component, +its functionality has been merged into ``transform_iterator``: as +long as the function object's ``result_type`` (or the ``Reference`` +template argument, if explicitly specified) is a true reference +type, ``transform_iterator`` will behave like +``projection_iterator`` used to. + +========= + History +========= + +In 2000 Dave Abrahams was writing an iterator for a container of +pointers, which would access the pointed-to elements when +dereferenced. Naturally, being a library writer, he decided to +generalize the idea and the Boost Iterator Adaptor library was born. +Dave was inspired by some writings of Andrei Alexandrescu and chose a +policy based design (though he probably didn't capture Andrei's idea +very well - there was only one policy class for all the iterator's +orthogonal properties). Soon Jeremy Siek realized he would need the +library and they worked together to produce a "Boostified" version, +which was reviewed and accepted into the library. They wrote a paper +and made several important revisions of the code. + +Eventually, several shortcomings of the older library began to make +the need for a rewrite apparent. Dave and Jeremy started working +at the Santa Cruz C++ committee meeting in 2002, and had quickly +generated a working prototype. At the urging of Mat Marcus, they +decided to use the GenVoca/CRTP pattern approach, and moved the +policies into the iterator class itself. Thomas Witt expressed +interest and became the voice of strict compile-time checking for +the project, adding uses of the SFINAE technique to eliminate false +converting constructors and operators from the overload set. He +also recognized the need for a separate ``iterator_facade``, and +factored it out of ``iterator_adaptor``. Finally, after a +near-complete rewrite of the prototype, they came up with the +library you see today. + +.. [Cop95] [Coplien, 1995] Coplien, J., Curiously Recurring Template + Patterns, C++ Report, February 1995, pp. 24-27. + +.. + LocalWords: Abrahams Siek Witt const bool Sutter's WG int UL LI href Lvalue + LocalWords: ReadableIterator WritableIterator SwappableIterator cv pre iter + LocalWords: ConstantLvalueIterator MutableLvalueIterator CopyConstructible TR + LocalWords: ForwardTraversalIterator BidirectionalTraversalIterator lvalue + LocalWords: RandomAccessTraversalIterator dereferenceable Incrementable tmp + LocalWords: incrementable xxx min prev inplace png oldeqnew AccessTag struct + LocalWords: TraversalTag typename lvalues DWA Hmm JGS diff --git a/libs/iterator/doc/indirect_iterator.html b/libs/iterator/doc/indirect_iterator.html new file mode 100644 index 00000000..61d9c95f --- /dev/null +++ b/libs/iterator/doc/indirect_iterator.html @@ -0,0 +1,345 @@ + + + + + + +Indirect Iterator + + + + + + + +
+

Indirect Iterator

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2006-09-11
Copyright:Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
+ + + + +++ + + + +
abstract: + + +indirect_iterator adapts an iterator by applying an +extra dereference inside of operator*(). For example, this +iterator adaptor makes it possible to view a container of pointers +(e.g. list<foo*>) as if it were a container of the pointed-to type +(e.g. list<foo>). indirect_iterator depends on two +auxiliary traits, pointee and indirect_reference, to +provide support for underlying iterators whose value_type is +not an iterator.
+ +
+

indirect_iterator synopsis

+ + + +
+template <
+    class Iterator
+  , class Value = use_default
+  , class CategoryOrTraversal = use_default
+  , class Reference = use_default
+  , class Difference = use_default
+>
+class indirect_iterator
+{
+ public:
+    typedef /* see below */ value_type;
+    typedef /* see below */ reference;
+    typedef /* see below */ pointer;
+    typedef /* see below */ difference_type;
+    typedef /* see below */ iterator_category;
+
+    indirect_iterator();
+    indirect_iterator(Iterator x);
+
+    template <
+        class Iterator2, class Value2, class Category2
+      , class Reference2, class Difference2
+    >
+    indirect_iterator(
+        indirect_iterator<
+             Iterator2, Value2, Category2, Reference2, Difference2
+        > const& y
+      , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition
+    );
+
+    Iterator const& base() const;
+    reference operator*() const;
+    indirect_iterator& operator++();
+    indirect_iterator& operator--();
+private:
+   Iterator m_iterator; // exposition
+};
+
+

The member types of indirect_iterator are defined according to +the following pseudo-code, where V is +iterator_traits<Iterator>::value_type

+
+if (Value is use_default) then
+    typedef remove_const<pointee<V>::type>::type value_type;
+else
+    typedef remove_const<Value>::type value_type;
+
+if (Reference is use_default) then
+    if (Value is use_default) then
+        typedef indirect_reference<V>::type reference;
+    else
+        typedef Value& reference;
+else
+    typedef Reference reference;
+
+if (Value is use_default) then
+    typedef pointee<V>::type* pointer;
+else
+    typedef Value* pointer;
+
+if (Difference is use_default)
+    typedef iterator_traits<Iterator>::difference_type difference_type;
+else
+    typedef Difference difference_type;
+
+if (CategoryOrTraversal is use_default)
+    typedef iterator-category (
+        iterator_traversal<Iterator>::type,``reference``,``value_type``
+    ) iterator_category;
+else
+    typedef iterator-category (
+        CategoryOrTraversal,``reference``,``value_type``
+    ) iterator_category;
+
+
+
+

indirect_iterator requirements

+

The expression *v, where v is an object of +iterator_traits<Iterator>::value_type, shall be valid +expression and convertible to reference. Iterator shall +model the traversal concept indicated by iterator_category. +Value, Reference, and Difference shall be chosen so +that value_type, reference, and difference_type meet +the requirements indicated by iterator_category.

+

[Note: there are further requirements on the +iterator_traits<Iterator>::value_type if the Value +parameter is not use_default, as implied by the algorithm for +deducing the default for the value_type member.]

+
+
+

indirect_iterator models

+

In addition to the concepts indicated by iterator_category +and by iterator_traversal<indirect_iterator>::type, a +specialization of indirect_iterator models the following +concepts, Where v is an object of +iterator_traits<Iterator>::value_type:

+
+
    +
  • Readable Iterator if reference(*v) is convertible to +value_type.
  • +
  • Writable Iterator if reference(*v) = t is a valid +expression (where t is an object of type +indirect_iterator::value_type)
  • +
  • Lvalue Iterator if reference is a reference type.
  • +
+
+

indirect_iterator<X,V1,C1,R1,D1> is interoperable with +indirect_iterator<Y,V2,C2,R2,D2> if and only if X is +interoperable with Y.

+
+
+

indirect_iterator operations

+

In addition to the operations required by the concepts described +above, specializations of indirect_iterator provide the +following operations.

+

indirect_iterator();

+ +++ + + + + + +
Requires:Iterator must be Default Constructible.
Effects:Constructs an instance of indirect_iterator with +a default-constructed m_iterator.
+

indirect_iterator(Iterator x);

+ +++ + + + +
Effects:Constructs an instance of indirect_iterator with +m_iterator copy constructed from x.
+
+template <
+    class Iterator2, class Value2, unsigned Access, class Traversal
+  , class Reference2, class Difference2
+>
+indirect_iterator(
+    indirect_iterator<
+         Iterator2, Value2, Access, Traversal, Reference2, Difference2
+    > const& y
+  , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition
+);
+
+ +++ + + + + + +
Requires:Iterator2 is implicitly convertible to Iterator.
Effects:Constructs an instance of indirect_iterator whose +m_iterator subobject is constructed from y.base().
+

Iterator const& base() const;

+ +++ + + + +
Returns:m_iterator
+

reference operator*() const;

+ +++ + + + +
Returns:**m_iterator
+

indirect_iterator& operator++();

+ +++ + + + + + +
Effects:++m_iterator
Returns:*this
+

indirect_iterator& operator--();

+ +++ + + + + + +
Effects:--m_iterator
Returns:*this
+ + + +
+
+

Example

+

This example prints an array of characters, using +indirect_iterator to access the array of characters through an +array of pointers. Next indirect_iterator is used with the +transform algorithm to copy the characters (incremented by one) to +another array. A constant indirect iterator is used for the source and +a mutable indirect iterator is used for the destination. The last part +of the example prints the original array of characters, but this time +using the make_indirect_iterator helper function.

+
+char characters[] = "abcdefg";
+const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
+char* pointers_to_chars[N];                        // at the end.
+for (int i = 0; i < N; ++i)
+  pointers_to_chars[i] = &characters[i];
+
+// Example of using indirect_iterator
+
+boost::indirect_iterator<char**, char>
+  indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
+
+std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
+std::cout << std::endl;
+
+
+// Example of making mutable and constant indirect iterators
+
+char mutable_characters[N];
+char* pointers_to_mutable_chars[N];
+for (int j = 0; j < N; ++j)
+  pointers_to_mutable_chars[j] = &mutable_characters[j];
+
+boost::indirect_iterator<char* const*> mutable_indirect_first(pointers_to_mutable_chars),
+  mutable_indirect_last(pointers_to_mutable_chars + N);
+boost::indirect_iterator<char* const*, char const> const_indirect_first(pointers_to_chars),
+  const_indirect_last(pointers_to_chars + N);
+
+std::transform(const_indirect_first, const_indirect_last,
+               mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
+
+std::copy(mutable_indirect_first, mutable_indirect_last,
+          std::ostream_iterator<char>(std::cout, ","));
+std::cout << std::endl;
+
+
+// Example of using make_indirect_iterator()
+
+std::copy(boost::make_indirect_iterator(pointers_to_chars),
+          boost::make_indirect_iterator(pointers_to_chars + N),
+          std::ostream_iterator<char>(std::cout, ","));
+std::cout << std::endl;
+
+

The output is:

+
+a,b,c,d,e,f,g,
+b,c,d,e,f,g,h,
+a,b,c,d,e,f,g,
+
+

The source code for this example can be found here.

+
+
+ + + diff --git a/libs/iterator/doc/indirect_iterator.pdf b/libs/iterator/doc/indirect_iterator.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3cdcbd9e7baf329d669f9183b559274aa2880bf8 GIT binary patch literal 75031 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

rDonfw1RF{^yzHB=g+#ZQhz8O07666fV&T zm{*KPrjQA99`21TzjCsDKaTc~-PXLuq2*&H!LMFU^e!@-Wkv^gAAAoDDwjXzGjURD z#i{zvcX?>+l0ma3k~-3WvjeF*Qr&Dv7@9lZ|9s>ltr9yMV_(b3%dQ+OR)6$nAfv^9 zaNcOS{+`jDm74VS`-b3%*#f$hHY%KlAyzK-&RMp7OjKS^JV0-(x;UgUCXaUo-3-2) z#(W%Yle4wBd%P}IAG);1nb!QG2+S-t7Q6~tDnqZX91<1Ijf@`EwOeQG=sx{!!JT$Q z?XA>^uVtBb02!ZuI=U%UdT4AoKkOzm;=01{B_tlFVLMlY`?~-l{hF_}T+1oW{S2>Z zh^#d&ku4=bk)zvKlkXFrQI)kgxiUSo&Q@V{)wB)?4BQu-p(!5E7T8j@|Zblkw&@QICMIzVeo#2#;M z{UeE`t2*v<(2@(svxOH_I{emGbpky+e^~@^X+#y$*K*y4!Hz!i>zzd zCziA{lU%w*VAvH_-OdfAQaU+U8?qil?G-1SV~Vk0;4nHW zdq~M1i7{n!@L8@*2M$GwAvU6aZM#d70~76OaQBvEI3X#uP;chu63<(z)fzKAWMnd( zS5_z9!-rz$dT5E?!j?`)i`G9GbKtYQUx#{j&taERupGbhCOn5N51D;hR8QqohF(S6 z$$~y6@Ga99Z_RKn5OBa3%iwQ_hU(`vS|~B7O7@cLT`#)MB%PeBiGL__?ipsjK(jaN z7NE<=AKyZ$jTG9O3TN`MAve=U7p=jci;&z`Ink=%OU6U@Xw34gI*FWt?Vv)k{5Kgb zJV?dA3>>%FMUUC~?|DcOwf4L9D@C4YoVJUs$b9~wL(6%|qdLvHI9W{iiErvYMmYG+ zC;BubYBfj`EAgwf)KrE~d$O82r>fZCQnX5fn7us}*|pM#mKD2C2)YgBP?Y?}W9|Al z+dIa$PQ`gYlVilC`t!Iz$~swaJ`yw|_y-_A&^jFfqZasoUuE(Zlb%j_DT$Qd${(qc zJ(ZW8GLcC`_hM3^)eyB_bH?}J&BNobg1K>cNFS&8xnN#n!*OLk1$oD1CK-oWlqWpS z7xkXg2W?wctjUfmp}UI>dujxC>y=COwIYxSpvBPI?v zc(dL-a(CZM|1d3tA~O&w1BW-^P7qeDOtw!)%@bt7AqiTPsj71CJ{XVLE)Jf@;~C6{ z!KpKArj^HNPja&}^tTJC&a@FOLM9jzU)AKFD#sd-idHkeS!R;{j+&z0=Ok85GBA@s z($aenOeIT&|Lg@F?QzvfT;Z|Pg!6EXm1e%4vj+cc?n%ck8!%(o?IAvT009$ zkXY<*&tu0UM!q;NmuuZ6gVD-n#&g_LY73XS4c^S@W0C z@IN!F|C7u2tvBtTF5kbK)&I%mTSi(_O;YjJ<@;Y))o)Cje{<#i=V+(@#HtP$yiEYF z?cYqwY=BAI?j~^0%Gd<3L*M>%xOH#_VxRuBi?acCaUlB5+5oV0yW5!=176-hWP!Qu zGr$7-TQ0zY{oL5W7H|Q#0W9NAuD~xRGY8`vD>)EPc+<9vF$gf%{#oz8vFQUj3;-p6z<~d+KEF!;%=Ie;xR3&K!UDKo08hXHgafd7!#IIZH1->BlAAX`bR%G* zzi|OTdf4`k(w5T)?hiw}13zfZhnf z@7v!k;nyVm>CFIR|IM2Lh(Un@F&RH!{@tAc@UFQD-uNGb87hrcwEHS@u_z?%T;I0O zP*l~_XhpQA+n>yDZ{togY52_J@&YuT%DK9oi7u{_m6OZQi!LXtB`HtKmtR<@eI?24 z3L;QleI+X>E@&T7h{p#-gmMUq%E!l}HTE{PQei5{GcUlgIhDdq1e0*XSHt&eYcs;x zr`VvpG%1*xQ>7r$RY;ExQ1RIsr$<7>Z>L?+_rrEJ$jHZ6spp zgWfrgu)5R_hg({K4EV&qek4e|it1zspTN=xg(Au_h9<*_3qmop+}gdPv#jKV;NEz@ zmP^{Yvh2LGI*%HQpm-@0MFJPg20x)$gDC6sem8Uu-b0u4hNQ!{|sf z$GP)9PhHY%2t-}C^?DOclc8X6_+aBz)%DH?&7XMdtX+m{8dkJ}@G!KXa2V&NKI#7c z={&rrUlFNYd}yGJ&0mmKk>Ni3z9J^J5|W?Sf}2lqLzET5-o3V>g<|*&jV`2)H$;S? zHJX{O!j+XHCvaZ|v0m@2Hn<)L7{K5%A)W2*y9zJK8qKzCOtH%@@y;;o@7Jz@q68@9 z;WAMM;SXsV@8}~>SNG+6?B9Xxpyg||Fq;97ezz$0>`(U>Kb=kY8}V7N9LNs zj&DK$=_Ba+bt3`(l}OTjQnxp1lJa*PU&jwu6uZHrSGaCiB-a$ob{Js~FvALcV!bKGyVk)-GEc8x=`$n>pz_;=Rsb~g!~1@Pn^(fcF_(I%6%MBuO=@oda`ze- zNsH?yYg_}a)%P=$r;TbhH}p$@?tX!BJ%AEi%+lExm2&3=VWXbxwNo-i<57Iic|#wY ziwhjNa*j7&QPV*7wV^V`t}-U76Cz0qxYsY#9f3(X!B57s6`i^}%^dWqufC)EtLx>J z@2)dH_V8yjjrJ6ia`}T2UNS`Y`_E6JHlV&nZZ&bkxu@|Bo>uF<8y|b(W}Lza5&C+Z zxK7A;-qsXJ&|1rleC^nbKv&Lhkj5)VKQHY+58ubn6IDIYj|-ykTCZZe=taHgO{Yt- zDI~n7BGDvW5Sn12N77ALx)7W|bnRt)ksof1stw&5zLPscd|3j=%<)b21e*c5uj&#n zf1eub{eDWLy_5kez4VsWj()j5a-(b;d@)8HY7Q^s5j*LlD()Ucy zKW6JhoxZyGG;1+b0nbqA>z;mi!SVj!6hTo8|2tw*#|8!HM+!rO4s}zU)yz&W#^WYB zu(VE`CTRjuUfWxIi5f7U5yFT+@egigEWJ*Ylva7rUf;-579EAon$Ekkh8RafO7G4l zB$`m+vnx~8_dujHHG7!_vPGk3C!(H@~KP&_I_}p}5@a3z-Q>;{+*C#zb9hE4{>i2xQH&&1{@U63-jkT8|A+|an z@h;LCV(tTei33!g!bVK*k8dD^*HR$Xc^2XJP7zreCnxd67N9?@@-VPip4XzgSO;p7RD_=$7Q{NZZ`tgvX zr`~;yTdL%U=~8mN@`D&^#Q`d7X)BJMo5Fe>O7HFl;H zUNe)Z8~M;RT1w6=`K85>%Q+h~MB6lmE3Ipu;KC8)NXy{KNI!0_j2u~U)@<0CQebJd zApZc@-rSydRY->DsrlBIG9wMd#9<*Gmfqns%GDPPVs>fl?mf)?wzjc_oB1GQhnVzg z@4AGY6@ySo4>5ZyfAd z_6Nyv716u=NTnf#3Xq5>XwKUe#9S_`l->me; zW*$`)?OF=c7Co}BkHbxb%mbbv_Q-w}e(Zi6=iuJ)Jp#sj#;NxAioK-1v_~9K`=Gh- ztODJBk5TGL36GO5X4zMrxF-VfDqtSkzCL1n8j@4@%I4ZnC!LxGt6v>!&K@O>+MC~6#vEYMQTIv_6;MX%YOW69{9 z0Gs37Wk%@_lI8cQiXq#RMKmk1R}n%>O|5TN)63LSYC5B;)EsJmB#XQ)Mdx|9b+?(L zw}Dk1K8D&&=xzP9B2#~)T}~)-*%kBo#c74{xK+j5HOsbbiYQSz1ryAq*CP^Q6d0D; z{F%537jFClXQJJ9z||vl)Yvd;a8=N{)6@rt%;*qRB@RTKH^TiFXzKK=0i=O5_t#H2 zp-$x7*$Im#d_7(*FXmjvKMs0k^uS+ETXKV5w7WZg#gte_t)O-KQ5)iAwO;5UrdRMT z1QwUSQsmBvH}|Hhe0RBx*X>b?(-y*!NJzSj=Zm}~An-$c29i)Joj%dhJ?zt~W_lxn z5A)aQBq~@&3tr`&@OZw$|L8AYL)hWK z{KuLi$Fz8=#v#ZSnr^zBxSfJ{a4;nT%AQqTY=y`Cd+>t5Hq+IQFGEf}QM> zfZBr#&#!F!Oxzo53w?N)7|>(yMVquwkG82MO#H42cnPkC5}rRrs***0nIzP zI3KFV7Ov%ml9&%2vA;k6MF*P3tI@V5Llxp&+xpRpmt?|J{JZ~GdRgos6!*^ZS@F$q zIc*qQzH)ALfApD+D{DcxwSl-?S<>iLI%R)DuG^YublpPql;mk#L0d4!FrVwL!E#yp zqVE+Fy^}etF4Z+@T-L@NyM3ZK?{1nk`O2{D4l}ptoFdEQr&TG5L!$66f)9|-WcWwp z_>9=mHyk8cXGXqU4WtM6jlM9*k)1VRPW?PH@StG6WsLA`0s)cg@lHdc%G(#{^4@3l zIXxko@rIkh3^(+=e42%M}yh7F^xKdZe?kNjt!Cw(s;&Vc*)a z{dj?Bf8x0m+Q$8Urh7BVpcQf`yeDm86w1roOA3Gu$MM z3!+elLt5z6rN!Q4YgCl%vqf2Tm~d^;05XpG%Q(xWClX5S+jgB2!hxBEhMpszHOqAs zo7Vi9Je3F^Yz-fIYCe!w@?rmGbS?Xh>>J);qJ)g<(c*ryHSLb$2X@_WKHGRm8YT8* z!*ZWY!e*}0C!iq~feu<_e6iEk1m_#OGMXU;0UO-RSWKR6564oyCO+zv56CFpJI3(r zv^}f@2dR6>M(;6AY^hvDk&k@l921T$mcD2UYZu81*nJDBWk$cxZheQ#>R7!GW6@=1 zW0i5E>(lVtA==t0kPe z+NUD4MW`8{^zjwCd+kE9;RPSH#lgkcqhnsRLH8|FfPvh?cCe9kENCUG?v_3T2CK(6Pp}wu4oxDp*(3FSBd{2 zWbVB8z@;`4ySl@9l#xo6u^BwL;mXiXQ~R)Ge$ZJ0cg^W2XX;CO95=dyusx)m?iso( zfjx@sGPbIle7j{KuSG96q5*zCU6!{II4PN#>vgix*ZSi#8TMxyA0|#`o>xW*ac!LB zFGMSAoXgU++E_}|a*^%fZ{H!|8bR05Q#)w3nU+!K^;#oy|4bz3Y0|Cr=*wF1`Q3Iu z0gCIb3e%cXYzkXiZHecf%MXq}Rt9~5RTzt%O`2N;c)ss2n=|IyP{(J@un3V`XF;f$ zb$-TUUD~+kFUmi)ur8~4wqc~*jkUv}PD*Tv;7wxeaMG4eYJ2W{gWmYY0)gDEjhInaO zI!RWJlN_I+Z+K|e11tW7a8>`}i!;xWd8piLO&v}WCw zCza^H9y>_6NgdAG)2)XlWD$-u1>@xW*!EWUQRZEUd`^Xqj;0*ah;s;9LPPnSt(tl} zjJj)_nhL#;TA~5#S=)EzO+re0WoSnm8qc zW=a9CJ(a=8t{RH|`JBG&N62+&S&!)>PPJl!Pf2l#hSX)AkPECBj&AQ6N3Sf#kuNvh z4_01_>{IGJqbTe^c|NaSb&kTDu|UB#7*~xEQk=&nY)*vG!B@#UBW)^}XFh)UaorPz znA&k5%2POnIw*vnh$5STlTyb@;=&(=gtBQp>U}$nO{k75>i!ZzqCm6WYV|jnJE1CT zoS|;{&Ox{hEp*5M_T+88@3>~)^p9c9dpSvq)ZL3?s{Yc=tfzL`SiHv2r5p-PZD844 z;%NF@wF6ULXfWlllY#~j1@jlkKF+XD)Wx67n2nXFcp5dMmdbUw(5uScu;CH6LH6bH z`xhwe%LbDB1=1Fj9ML-XqZ}rFAG^R5q?5p+=fv2fG!0XV>xK+Ld~#%;n>dyphkA z``{pj$Ij(hLfYS=-OKc}QIpy-Gh zan3Sl!QQ!}L#Xgc_&$vf@m0B56(h4BJ!#g+&cuAyl)!N%vm>S2`qE6Yodd|;v2O?c zEA!|YadiM#D!5-rk;B^hgTxq*TcqNhwH1^mcX?wmcXRcOR?9$1=g7G#9FOZVP)m&qU5nt02p4XbMMkFc9MO; zhvXB$Gn1nH>t&ofkF5#7hR&$Wmem@RAF2%MfYnB0cC839U*je9OG0Pfk-FJOtzY%8 zVO5Qt)WBxbd3z7u-vw(a7_C)7jCbmS(U>?F-1i-NpR+-t=It?;w=ePQ%yGfo?5cI# z129cUk&EI_{A3OnZdcOSkNGKXVOeL9C1(UR(zS~fTq8Wk(e4iW1L+!t1*cvw&>q<8 zMbi%9gUCi(__CMEvJYs?W`Ylkwe~x@0Ye<^2(1#iiQq$xuoJ6T7O0crCF&SU65F_e zga>4=)p?#xKeU_EGNa^(8V9FpcQMO+8QjDUv-^x+-4ca=%iuu_GH2>|Ha&=|Daw|) z?;FbVwXNE;hdTKaJ^Z%pMFjb7A?z5=?>36);F@llk9^Z!B>w_ZMt4aF|3;^JD0cd) z7LQ*ngw|S}*1d15rQOGroUMCDwhdYoB#LTYrfj5L>!<%P636@gcq3EGWLVU~ar7cu9Zryo8M!vP6z`M1rtm2bx#If7j(w zu))uJ@w$0*Vw>I0JN}a~m=mNa&^wP(S%LHbEa79HfYh&BGla=6+LCqop0m-P z%enTF-RMwmKL0zUuwttAb|AyZ65=DT;~J}z-L0J1c3~ZAf{<_)+swUu?Tj|O$!`*? zmG_qsni@4c!amj9at|e8TaNR1h%&8O@uiU77}?VE*>kZrJ%ds(FC|GD77crrz{M5= z=|oKm_*=>Pt}b4SyM(;MJY#!hE-##@Fv-)XBPrHVk@EqZ1x8aN*pLLYI%j!=(%LSG z`H@zn+RkH%Sk&cC$bp>0Itl@c1P>SsQn7&r$Ji|2_iRQ$;20ijb2OPA%3%I&&4f~| zl7=dJGNv03tU;)c6I@rVaZ_GcJ9sB0zNp4;ExBf=DxYY?$I|C^X_duzU4e2ztGdYe%rwW`Ui( z=p@>Rm4__L0S}FMyopqBIOBS=OIx#ED$@mR3wJ& z$JlK?PKl;|4L!-Egbo27n4q=^?BdrhSupZ`KDEX*LCo*tdsRit>Q^M%qgkE!dOH)7 zuQQb`aNRKc>>Uidf;@?di!f4N`o`6jCkQJTqfSaj!QAtFJ5A8EfX`WL1Vj0-C37rC z%4>yt*SY?R6LUBk>23|dJK_6BobE(Z_2~V2H|)8Pg82RflWjvy6acjq)4zQ`+VvN0 za~#c-&`$_f%pLW`T%f;4gu>g|g~VlYIV~X+LW3kZFqR=9Xf8&Qbe)i#xUCBDKAx$? zu9{cL-+2gxWs({>s;b?{MFrj-z{A-U79lds3-3b{%_ei@$&^qmf^-Qk=8U4U_fIfIoQa3I{E$ZiEb5%^^)5j7N zwbj3KQ#N&{OSV6H@MX|#)Z^_dk)*<|2JhvttlV$(xRt+#)I$u>^4sd# zK*R0lBm;}2&#gH@WNQJ_bHnA%EST0_r>3{B2Y=9?l<4w14ovqW2vnEuNNI zYe9a)uP*|*jeQc@y^>*b(y;RLBvdY0(&{lL3!JchiSPO}@tX+GfuK&w;`VrFROy}~=TS%M7$*f0#Mu}Rm|VpOQ_M5XGBWG}48 zkuq7&ZsOgDv)hy^v~(G6o^_?290r%vgse@7lL$ii9||`;H0BRSC6M|_S{EOZt=Dz6 z%+We)wwt_U(@!EPMhdDi<~uXpZ*))|+o5|T!(G!o&uXMO9UOS+bpYo>;{rb&p>(!g z7_E4?$LSd(PeIjaAz{Y+cB)(HM(wRycy~ZohUy!1ht|yEELg37l)H3*GSi~ulzwYDLgN*We z7&LSVDU?R@`x_(%205B2N-G`g-8OwQGXK=3p<{;EW@u1=sw~H5tnEpHwEi#WRj5!% zjGvtwBOn!TXn>?8_TkxPU#nQ%<3jrfIs98UZ_w8197cO zC-W5FLbwq^m#@nYI>?eCiCbcj8ImQaLywYtc?qCa)I#JW(JOu>VO^F7huPS{Dbb8i zo35!j3?%rp;eg!-5l@HmYL9Zz3*lS?WeETc+e74#K|b>v@V!3!+KodGR{8HZW3Ee4 z{yncV;*l!%d^xxp3J;N0G|urp-H`Q>z>U!!GB?D%`}|g_Sj$HBpi)LIRcO3#F2Sj$nw1Ge5}Yohn5a2~^w8llDoZ5qC=Mc1j+c|6S*|t6 zdu0%bK*PE5=-{GM^NMXBN2jBo-j$ueqOQ_J1X zna0xBo$#B}LV$uT1B+Gm8E_o4`7)Iz{Vi@g?_PQ7sJre`?2K6-auhX{8HS=_QWt+j^HxMOCVF2w}Kg!5r1RsYV zTSc1mNU2D?G^cUxDJ;rmkPav$Fno1*UD7+EXK7`E#n8(M%nbPmMY9kVXVO)k<{&H5 zG>}-X##hlcytxe0q)kp4>`)g>BFZqB0EF({7R*R9@LB;&@|EA2%Z1upZKrt@rz5E_ z8#(2z({n{vrjQRvrA<^>$S7(m1+XSyV@=fltM2h1e zl9%>uk_#ni80G5H_JkPPvkxfNjvDfP{jGdNbL_`asBy~$z`gKupA%4;s>uGT--Kp_ zU}R1v+8`$sb2>|ILG7q;)+-tz^0C{p2cZ1;;F=Vsjy~1^oO^Ys?Nuvo8?TkvI&vPz zlf%13%1^^3LQ0>f`^runJ4@(&iIc^xsf&OeQj@?BTe`rXW-C9XujudChgu9~AD}_x z0WO@}B_}|(@ZKYd0x$IPr22mG*Gft0*`}R^k9IMr3P<*uSMVq#Oj@Oi23hBZycCPJ z3>BQ`XB-5nhwi3pj#$lHCvQ$059&|2<-bhvch}ocRKznX^q1I!krG!p?GS!gS%y$W zu|4d#Br_8r-rhsbUGoL7dJROs=uJZ7iakdQCoa!z23$qJOzeUTO)->pcV2xf6@&)M zE&?(Y?hWZjj-0VXhfotLI+3!=qocl8Zq0W+jYkLIxYXPyo7hm=zFJex8Vp7bFXAzD zTQ}M0EIG*&G8Q=RA7xO+?N82N8(N*P!Qv&981uBQ=pXty<(#**#4qwz8Otu=;u_&J z+0(si3n>g5rg)1>{7CjhuuhjmP6pFfmd8A_M++sY;#W}g{)>6r!@3ebZ#G zST#yOhJ^;qN?zENaIADgzcd=)2(HS)d!Zup6{?*2)Wk!qb02K`V)!!W7f#=AV#RB^ zT;MR8Gh?!wzT=2ztAS5+8KFz2w{C}V8hy+iDrPo9PiMw~?(c*tyM4yLM%}5it(YZA zo91OND152Z>LqKWdg+FduvMPC>x}6Gp2U-sX_A!OzNJ1!>n^)-grH-Z!`8T?ACr+q z)p%)>SajMhRq}P&qWi9eKW6^mbIOt+92o!}d~Lm51V(Ewxe<6iYwFO9`N9+))>reb zjU{`y(`2^aOU7K;X)cwxx-ffRh_Yn~#8;2jXXxk1l#9UoPSLVo}gu*?aUH z%7Qzy{9b%7-n>CdrLNVVTi#n5`w=QFsV>%cpqf9$Ne#yMO-MQ57RO(bav)dCg7e7c@h|{y`e_h$TqxAO!^XWsaP*~BANNW{TWf|+ zq$#*e^i+=(vl+OIl;PIq9v}suKAfU($gcm4D$XZ8CQmTVxc7DAETnS2vUAcjtY;sJ zxV0UIWBJ~QuMROZuNTw{AJ0aErmyb5$WkP5ZAYpn*N)|vFY0GE$`bgaj&h?qm`Owe z!VaA0C>$oc$6#&kM8^0zwYyxS9z~}BufXbNy&Qyk3HpP)sw&aEPL+-{o`MCm;+U>t zI70h1@q?{)KuCa`4lbG?!$)<> zG2S>S+GI0){!zYNfPSh0B^>H)rE!m&otYSvJ0|>5ouLX+Uny$_gg0&O954wyZF8A{ zqHgu*eU9+j>TJHa`dmQg)~yrQjz#_QguWN8#u?!$Nb`99huyOucQMG;8SkS>!6gjf8t#i6!FSS5mH)M;g&rZZxvd0nW?Y~$HRZCwt?sY6@L z*KUu52p~dmxWN~46Mwbg?A5%LXpf;fcxONs4)=fsVN)_@mmQk{k}BjQyzJ=$IDxOR)DuX`qyJ zNk-W-z-h7{5{=#O}12n$v3+&$W`i?rVnCVxj*s)d}d& z%U|Rf{xNNeNr>U3;MRX=NzIsAbb82NTc9beqFG#L8d#Ae6FyUGY0GL22bjx2#_Dyf zF2^*>dEDW(lR2?MR z)#qK=RriSIKeR5jJsWp?T-D}zC>4+*SdtmlnTWapK#ws~6qlSbQj+ZI7WFFae%mf) zgCWdR@y!;8mBJGp%Af~tYm;uHW`&N!)q5apXCK9%#YVXdDbYw;Tr>2gf7A#ZZfp7# zpAlk5AG~qp;{C^o{7m{y7@YQGdbs#^bXThJU9wiFsrR>K#wBo+Wxpm2~ zn-{Cdwg3F!i7xUJcyy?;?|>__nc4LY@M`KFm{a=(B95V zSFDCT>RmseG4P(&6{sQ77;V?c)2g%`;hA}AC0|t~!t37?D>e$?*zrA3qKp#6cV}hm z3MB)=RL;i9FKmBWrTTF-MTK9EvE7q}7wcEC2-vOIrxZUq=<1I|;dU0C&!7_(R@TRN zwg%$mERA#>Ck+r^jv%*9`rCbR8MS-W0;pyVN|ep8(swV<<}BbJ%`P7k5B#KST>Q-v z);}E_5`DBmn3M|9d^qWgF2crz$wZ$e4NK29K5~s{FBs=smSH1BF7+XBxcp)`TwOK1 zyL4*l@8bme%ztr?r)`X{5pbQ?t$io)OU+j{@i)y$3bKMY)rN}tAaBaQIJ-u;OPSWz zw3NIq#*)vFDVz)w1}>DiF>AFPaw#GJ*wZ*ZymE%RG@OA59^>K}R7XxDq@7<&uEkgBTjHeLEZl|KqBFRZ$CDnz3q1aKTB=G%)PTp4&FEVVhXvUZsY88!b9U(qh z@aQmGL`vG6q#qP@USO$9tF?%s8U@mnGGNvc&xPQI4Nv4W=Mq0#HZy97i9DJ0qQFz; z+Vx6C8l}l>1c<*fbL>LOIG*+2GF zRUEvpY^S}2E)^^!lxxpPgx73MXM{`T0`kqL%-lcy1Y@IP+Kl03f&#k>n@aj77b=}( zIf>6Y*#)MoO%FYnRHFzv6O>UvaGS%_rgD?=<`;+VS-Q6F&*MHGZ<&;-0dTtjYWre3*%NXYbbLPr zs*F*h-<#2<1>ag*Z6)ZOt^ARvtw?nmyeEu;V*M*Ymo7+<9DeEUC%K6qXFST7{ps_8 z&_@7TkBDTb$TDrvkR5@lm{%omo7lI*B4L>jhF^L)7M4dMlD5$_)rx7ng8WpY9#+{5 z(frW$TH`|&kYQ@1Q>_W;U9@yNnmDU5KYz=V;uD}<=o^)3X9plP%S`$#PRh{_7Hw8| z+>9ro5#VIARnohcOq_(Scgcrk<_c00CD8i^gF4>D8^OX9okPN}G8M%RI>*ngD)5o( z-X;YVo3Wf^tjQfkiD<4#!rgH4o-4+%XC7lzc~^Vej#AmoN@Xk%S>@qX)* zSi4A&FQP287bxYI1P3bojG}w`OxpSk1s+)769glRj>z#tdHV!pXi%2^FPPTfl0N=I z0scpr7Sn&RpE7+B8vkTJ{lW(Rm;Lk$7Wp^(sf;qexWtbyOiNMmKiE&1{vcZZ1yuNB zTmSm*{s)}a*J|i&9jzS<4fHI&Y?%MxiI~2iq_3+@%GIU>%+~0Ju|3l!5;h%B5FC*u_SYiJS z|N0wMWB9ktFnmc(|Nhw+z96bUm;K40F??m={C(j+TVwzBh5qCFsQyJZ{h7t1f*1L&5t+=KW^^?5_&) zkBaf1iLk%w!{5rof8@jdRvP}568n=1`+FJqTNU`T2>ew8{;seU|6i1tBAqhbPde4V z$guxPiT$HL{i8emZ_%;81h{_($Nter{;5a&vm5to$NgK8{*P|l@Bd7bv3~`J{WmZf zJ^S}R4(|Uh87D#Mr^fnB#Wmk9DmXu;Z`;>R@ahXDb8f=##_=_e-lFYhaj|h0vzgr7 zOr%?W?czE-;VL?Y+F&qWz*b^eG=r2kWC2BBs)i6lw7Bf~-80k!g{&Z}Vyp{VOV7v@ z21ricm(DjptE}U0tB(dx7ab53ghIZv1#GYnTuXmjTPM)@4Kf>jse5*Kq-O?1j7H>E z1s+Yd4|dPM(98l(k>05Wc$wcW8FLkI{&%4=KAMb3c5nra?0pr^1fNng)6g)C!2r09 zE9c8toVwfLqyGd_M^M&c;7h zf%5G?ZGPwHQxFnS$vjr&eCW$9FO6&nug`8@mU{_*`lYRto}`voy})JT6!S!+t9raJlIqkh>4*!=*>4@F8sh0^z&}oXc|5- z84sTW9kSorNQU}gjO?wxntVp2jb0UR3VWc87_01jg%;2h7n_uvOwq&LOArRuP>jyc z6}4}Y?}x>oiK+w?=>+3Vc8$+8wfuUPni*bD(X&$BPG6xjD6sf(1x0=&Lmy3j5X&Iq zz#qMkXwk#V3rov4O@K9LAa;PCs4m_=blj&l#{g_EcRt)R{9dc_EW5iVx4qA7K$lhD zi$)-pjiKy5&Qp-&>4&E0pPbv+2pZJh?z06dS2i*8VPiIduc;o=@I}KuNr!3>y^zrI zg&Dgb5KErY@M9#rkiPFJ&Tj%A=f7C{*8jNu&R=WtNh*e#(G>zF9}yB)Qvx%z&pR;E z`_S}}<+tyHd;r;^Bt226Q?z-$zx}qz{W3`%-Rd=&2)5I^_nqG(`9q3&ESe|n-N(!E z8O|Ts`~ys2P4&$udWYtdFIc#Y7hZ4t1_KY6JGdzfunffHQO&=vzq^yb0(r{(!+WKT8ZjtG47 zEd?;~pu5n6V4);J*YFo2h{FC={ZuZh)OG0nIup)NcNoM}V?U8yWWBlL3LFZ?l8O73 zJMo2#bw=Kbr{Vy~BoNN-?19$9TKEHFyV{1CwgI`z1xNHcC|+I@%Y;^j4Ih=KIu?!O z48>dOyZ#oNc8Z#Y=jS{mg<@3ZYEtGHyfm%lFtmEa)f9&WtGrS;^I$Fb!k zSzPz8h3(*Rhf&_{^U9xaAi=I7bb+#uh2Yct<+2i_7=iP)oGE>ses=9C;sEmwF=q2$V-wn-x9+?9@0#`VVjX!!TBh%G= zQ!Va}g0{BhC}gk`JRcD&yuw7Iz}^_+$}ja1Tt4iRdl`xl@6^_Yc8#N}47G8glzmYT zg@j!l3GHHIS7?UW-xzj~hxki|-ww~KL|^~*I~B?;#RCkGi^>_036GTBMz+opN{caV2R7@}7j212 zsPQP;7PRGutm0}X=hig|fx6!cVns-0D13~Aag|1HvN=+B)NNTLZ*@?v)jPft0uy7F zd1W5=8H`L1~!z=6WBhLJX1yWUamXoQ*ERM@}@Z09-I5=W5H6C-IeX?k@vSss@dLlQk z3P0gt{Ys4eV|ax7-wo=1VZ+(@uS7ywZi${(%N#EDQz zg_)%{hR|)sWU1$&@h5d%I-#0#DTX{;jg5yt8yfD)rfwLQbG+k9$6f{hn3b9WWR;m zWcDq^6L;v|NPe_RW3t}ND4=adFZHqH4!wFD?CfdcNK@aKbh43gLdZ>jR-oPkQK%!X zXh9fAv{dWZjejRBGm(YDlLiZm#dh;UHS(H+c<2@>3zx=@Oew)FQ&sl&gQlJBj5KyF zhxrBcKCup-)R%)ST`Q^5R84UOYP$!32F4C(kW>BnG_twCXGLY%t2M>d_ii1qAdkrG=f|#2nOi$qR>yq52YZ0Qb}h2rNp} zeN7%Xa#ATPp7i?;wPr>j4?>&Hv7ZJDLd&-V7(rYTYFwLz-l6FfTxKdz0WJLcCD>O=)#CDH zM(6W6ay{G%BcaYt_$k`{@|Zmg!D?okZOy zsT&zCww6}MX$tT+#zimH{m|cYswJq-7%<}UoMr(590DH4ema;}(qFbUh3*GKUU}T} zm?|dXotZ)N6an^n=;x<$Q6ZpU&Wlpc0vuUI4PJ@A9)52Kf=*0E6~Tr!_jZ&RP4skx zhVbV1_|+fhGZ6=-h-$x81{cs@>xpFC&6TxbZU7G12mzVe= zHg`ZoK`o9qR0Ik=8tkz{7X|MHs$Vmy%WY(1M-6hq5hz@kl{cqrJ<&rOc4+OI2LjE8 zs~KunJ{_x)@7V*di9XtPgIXW1uQFV~Ubj;dk+)4AthIopH6==CN5%KiylmEi6oSB* zougKuh@t^qMlYp z^5qj9U=3SL^Y3x|LdgS16|%P`sjKz;C=a8}E;%c4x^de1o9dg5L+z3%=vd5<{zXmT zt~dh@gxgKQ!w4ZR{R{F&UYcwo`a@ce{RTfe8EGN*EW@SR<_0-_&F;`cxyM#d&-^!f_dcRIo2M(XfHjMh&;X4nO4|GFu*nhl}j~ThnJTK}DW7Qxj zXimi63>{#jRTe6z(wL6N!d_B`)5o$rfP2`>BZ%DINUw7r?_TPP_9Ga)wE{ulI%2gi zk)wqnPJ?uQ$HPo$JMI@0Jb8lUE#zfss>;C5U*G-%Mgc+yTPVC)dV!n}U1BaiOjp>0I4U7iwxE+O)m^A?i+y8(P+Ir3*vXZFdrj2ZII3@ zOK)~+7-kl$&jx4X;7Q$#_3aS3y~OYUr72>on}D~J6zU}1!?*<1CHK09@i~u&btGX+ z4X@g&&Ey41BVm-{PHd$KT9mTrB8a7%5OX%iGP}kY^^+*7S!HZB-Mb8jB_#MI!U8~8 z;SGYV#;FQ9eSz|Qe7{4Rh6cYRo-ygyw-Y!rNYnzfaibZXm1JSQn{47zfF%OOUi58) zC}TV05As`I%DeQcJao~OjheNz!6>S4_vV@o38=+Cy{AM;OUK?5`=y>03Hyco=o9j@ zgSIMky`C9Ye?MkIi`Wy(aU-?G#)8zGWRMFQWw3lYn>dm}#e%aiIOe>@Z|SrU{1WiQ z%V$afS>9e!3CB7dZh+OMw-Jb};mO9`4oT>_t9(n1(%DM}+HI}9+Sdw)?K_9@WwgC^ zPACvqR#D4`HLDta|5=_4ENLg3T}3DR3;p|Rh)5{L2=6pq#K6IklT{gDI)F2nDI`82 zD_Igw0UH>h=Q?=)qzA9HpD>Esa!oKsxzOxjHZGTeX;%NMZ&etk+KINEii7BWg=oGO zu&|`8`$N@nG>Tfu7}5{LG|~Dk*Nr?KkhkKI3Srx3Drm;1iLMRlM^-(x*h(W^L~QQb zgcUWuAJdBF3N;+9RrmZdUbb&VE@CHC7cxytu7t3YtZanGjHAwBFT!vVY6|Jll=kD` zOTj;r&4Wfzb1}3>_8Y`k+?0vJ#5Ub_>1D<8-%doCJZ&zowcRXha*Cf>>vB#f}6qz6}M=S0jIzKd#TM+$^P-xvjj6N_j^5A~E^T#2@jt3jd+-_B}y zC;DgORNx`8KsK(>->aMSqrAk=riqyuwKrpLX`Wa6(kmQ?5p?|cUPncg`Nj69xMWhB zEU*_zP%aDz)PYx~3tZ;TnFhQYHe}ri6}25E5O0*J>M7pB9+zd1>o6hLobHYymkso) zS3JI}mr*1$sVLqXpY{4aHTdb(K0+sJPjzB7V<0Va1=^i??PTYQa`5BHr8YxJO{pEP zr$_AdkOIJ8URdNoJTyFO7*UYpcVsBUJIlCoBdwnq)CtIZIK1hm(h=ZQw|xM}RJA1h zxEwn~D0-WRQ*k_@4{APH+|gpJT6x830^fG68Iz7BK0XTnRiR*b&4nqD(#|ox-7j&Q z{$vvhND6&J1C`>Dqp6ySKX#anhJ-gfU3%ec_Z~fOydWu9}=zLG9@qyR!ZZ7pJXhj7R#lH@5Rzp9RtVLiPsCgM&=_J z)4Y0Nm-Zm2M_yb#GpHw{dMq#Neb2}GnH)$!RLgMmZ@DC#>Fd}>MOLv9>qw905SC|U z{v;*SCw_oVN*y%&p*vC~NSCB}%rEhXPb1W_GKC}LQpwzG@l(q%;6{QFB7_>Dz> z0}9dIpq*s#WDi!xDwg0->_zt}Srm`T3U-RlMlWS6bjgNdCzF0hAs@FinZpPfYfWE~ zZyO9l7bk9#e$IE^(B>d&C@a7`vB-6zrv$!P@&r%$L8>3oKw*&mEWb@Cib!h~f971o z%nn}@wGBG*^ve>x=%}N~Z~SvP4`?~)GFauTAD2*eEP6%z|)VCY4oh9{Fy#Hz#`P3=&eH-Kx0 zk-hBEuId!S{mZ^E5B63WaO-NE2u2Io-;9uYzp`N-F|PPs7g>|h18@sOFb-FZmqWG{ zF{)a~#z0FX6?04r;m?6kaDLemD z@)5r@R5gLcufc;jgRqnm3^(C665GKV7rU$CEMNhn zl{@+fFJ6W%)?F8W>Y8rLV`6}*LnL6`>`ip-*l~CtvWQB^1qb5&>92A4(Yxc{UC*o^lTn`jLz+b*dB8NI=it<*Kyio9_dBvIFAH`lJoQ z<%y&_N)%kC>3ls!-biEQ8fm+^G2PA_T7@UtMt8U6+mUCl2ZKIX96%d$jQbKs&|i@iXL~=^7p);Gj8wg5nxTrCWzQSQe^5JJ0(arO z&66FRjD*y2$dS`jEdQFhcsOOaS=Xw36n0i5u{WtYV!gnUf*%+m9 z%&~Nm@CPV9qiT(vtg%qU{Rt$v?{f^ud_Rcd4i({)1Ri5*gtlUlc_o7PCBq{3w zV&D!Xc&jgsL(ckfxjB!q5v)a6Nu5GUhdJ2wJOd|64@SF~^V97z1{J6gq4Cef<5 z$4uw?-RyhhIlpsj>fMeLszBCvA|u6486N5_q(zp3)l`%pui#(_O`R+=<;BQZ#TAs1 z#dMrodu=hu39meM(Or##j$GAQDgvgu5*Y4Bxt-?q5O<#UvmehKH(QqF&y1Hp5w&1g znG-~w6*@Y$;qmQ?OMz%BexKTZ!3;gJ<>&y}BOB=zTzdtsCT<&11@rkmo?p zs21Vsp@JE<@hO|lcL#Yvc#bYK--hZ!(zA-PW%k`0j?Bf<(*5EAdi#k$}5Uug7kb|Q#o$GfAjQE*y2k0X{Jo$i4RKyq8Rlou3Iu7wmUqwQ0G|f zXH9btc3Kw~zdZw|4|9WDCB6;@OUf?(Z7Fv*Y6 zS>pVT5p*scBVT9@0iCIMoY?OHVU-X;lcbq0_T$UE?2M8imAs@=5~8ofCA%AZ*od!d zZ5!ta!9(qL@k=2H%_odkVmU!~;bWj+Xm_VhV^f9Hi>*Pu*04$S!@}n@i;DSMh?!KW zE18@=L?}AYQdQ-2v5o}StuaH$VBlCHf_A8vQws^8dO3#JU~)VMiEM~f4{1-DW4vdH zY({QYfL_Wz?~-5ZwIpTb*N!2dq4oJoyPWsaL|xqu zhZJEYbg#8u!`DiRG|Bt-5>(IdFq^S$znqA3}_$2V%g_|mlg1oTH#JbUvlFDOx) z&1Wt!n2W<>TbNsYL4+yyVEyTP$gf3sjJu`YITQ<&`<^A0*7 z;lL+8;T)gxXqa3DMQ|LeQ}2m%3ZNg~6`Rlh@rqD~i%aHo1}q-vEj=18+fAs+x%et7 z(nOVTnKbBT?=!^4qBpl;;6~oaYAGtKGn#sAitO@}=UO&wgM!_A1qWZ>tbnN}+tpWX z3(2>*1Lux)pC3cMhl-@<6xkdjH$c1v0b65SMpy#lpeJ;CQEIYXWC46g>}iwm^=k7c zbAwSrLW$8j(lkD=N9WVcy+NCW3+M7T7+kTm*nww(VIx(NJDBh-sf`hFsp(2k&YL?2 zv5Rows&;VqJbl^s>RbL~h#;*q$UFy?aA`g7PhI^+T~q8?0_(~i!S4pBJ{-9ZQodpj zLIAHE@Rqc;wQL9KA)fY{9jM)y4k@MKZ!kVs$#PY?@9GzEx3Oegq+nP;_2TpNE%#Po zBqUc_k~|0M#mF#9hn86Yj*3|ICGAj#-&l3$!Cn?)Q+I}MI1bWDBO_iw(r#OWjKMOl zk0SGkzkW}_^vPY*mVBKJv@SMLFkY@pg!OP-qq>JHF&P~>ntzYCjN53!gdCpdT@cYs zrq0cn*Wx-4m11n$;GntR+> zaR3eseVXw` zmBbG1l_EWz+13|ov{jl8be49iQeN+<5;GYexIaXbwY*v^fb4x~=VYr|!E*xm`F=ud zzWmIzQx-VWyEqG#Ymb`&%~ve<^k{Dm+C+P#eVWWPI>GKw%7gWGL;Psr$8!}i;EKXp z)FGN0Mp3I(GBdD@2Uqs)I8^fjWvv|3dk!&t#-5RI|Lz>WOnXgbpx5&p`v{06vIElAneL@BL zoVq-<6nVz!`aAZ%6H+#=8+$t5C*WDWjo*~WAobBTX!w!RfQ-~$5r{K-+>TkI$)~Tb z5B=&#qwiH`3;%|C2fRC_&UASpB)5>omXEl23C_s#nfsZLuMSWioNia6b*YwaCM41i zGS7@<*>~L2NRIVI{dzW4H}P{Runese@YzyfD2ko~pk)iF0Su~+0*VB>;)#r*Zb4j* zYT-fpUE(}r>PX54hAvXTDHT|=UwVyHHcwt=@sf778zLd^OC?inSCvssXzKbfv%ps@ z?dFp;7d|?-^>dt{R(*F74W+VE>4N)v*)vF{8Tx%V96APF%%-o&DX^D1VL1yAr8z7Q zXqD^8)+-PsTkd$F&5C^Zbz-aL443sL;gKprScGl;CJl8r@|p6A1|g5$jJ4ce+}0v& zt1XavA0YRkqZI+9wN6%3XW#S61_yO%VM*8lJQO?HD$AC<^6MeuUPB{jS8KfAY-BSC8BBU z#Ek7$Q7hD1V##Mu7~bZ}>7JrEj9kbS58}zse9Dd=$o^B~#ga$w!s{J=-F*y?&?D{c9s}S_H&!?n4B61A z7@u|Pk#8(d88$&G$YUO8jakyH{mEyJhgUr`hZEK+3WY%eNZAjZAc)Mh<4o?83fxoo zJTbpe?UEnWKAV}?VLPHvNgWTm^gCb6CoKUm^Mxx)P@GA{-$G-k^>!&B(Qcy8t5y1a zgzhM|)5s&m`EJ~H()OoMQ=tzuxP2Qxu%*9^&9o1f02v+%m;kU$hz?XYM~yqwSKi*h zM2gWn0#dv0g0E)DNBuw>Vvy7r4Q58lN%m1O0B-@J37{OJv2i+3i~#bjUfrNWZAu!R zuhHdkiK~OeZVsAc|Nm%v3*b1Cby--<%#y{-%*@PSv1Bn>%*@P;7RwehqlFeTqs5FC z<3IMEJqu^wd*|MWKPIG}sp{#T>8gpS?9BX<`MK{s1#fz(LgvCST{bCWezx)$ghJ~8 z@jDkmvXP6jrG?eVsuzz+NYhduY#>rSD{R!@`suci$L@Jf?m3L+DcyL61Kln*?2I7Srjv6`Lp_rVr?KU6h1M9+lm(le25 zez2sE{?HlxEY81EP6V@h`fwsZv#Fy^q`4R>c@-yY5HDEf$~)@wlEjJ^)W0T#@QnkW z4=b4nWBEY0bZNy`DJ6kbSO1B|BnPNPkb%$24$bfTn2}8YdrPY6`u06|$Tp3Pr513> z(|zeI%z!i()63T%kSF*}^c|Y2&>E20_?hl4J~-=(HqeT!QIx8=PDN{@iX7i$Vpmi) zWnw|&S%#R9-+%95=;?RK=pAU`)w5eq77L#IULWyl<)owJsZ+TN-a?C74bfpMKLNOYLonkz3DabB5FF0zzwiJ8w;R-ZuCEfjXivU7#xHI@V^n4pSR* z1@zig({<3UUhF{E(a~_6+86xf$(hAf;5|)L+$>2&lIL|MbE(hS@GSkh-5a7U{^`ao z8?0pSz!r8hf&wr@+wksS1rK-K!*nL>8gxQq7ZUH27#S*{%a#|*dNcCjFqDJe2i<54 zhTjt8h(SAZVx0fj?o<4}S$Efj2OD-sUJ)DauHJjH-wIm9cHv|m#>9@}bRj+uCq~|6 zLC|hK*R{V6(wk2k)qQL!x-WC4G;A$4^6Y56B*tS;SUf2Ap@6~2%R4kusd9F1kZCj{>hnBW77V%Y;@ zx2z}tij3lZt2j!t%R_E};0+0WFT{*y_r;+(VTPsva+MdEmfCb9TjP2hxg&8i4$k4? zYA*w7c7JBR@;EVX<>cbK)+g6z&_<>WbNKC3-?4caiAW$Sd3e@wn0oAZ9Xb!uBx?DU zM7JS3Z>%%Rf-(KZGXb*8`E2~g_?CCHcD;Q6Td5!%LW_A6epk8{Mec4cV=U~E-RP?LHvX$+~fr%dlNPp9e}I&EJ<_p5)R z!3I6F$zaN@#E-+pdNVUWlUWOVwPtAD`xl<8Z2C_6!Zs7` zX^5=B!t^4_J{C`C?C0p_S!+i(gN4`Fg>N>j8A|P-i8UV(R7GHxT7lEsYFcxHOh%eE za6B=Sy(coPb?y|#obD#tZj=N!yG!mWNLVwo&b!@85F2y_bLy9fJ&&Nb+a|FnUiXqS zGSg-vMTXk?+@pN@5y^!7>bH_ZTehc!Qd@~rSoY>HQX8gtPc`{vYTIdsDQY9pf-$(& zKOTh#EQ{E!qc!q7mE8e{>PNB_(ACzB1^MLYRHlq5awe^e?{vy`ov<$`QMXc}oh)Zg zBws@iF!-PeZL1E)*MY^gtr~nPX%!m;rIbgCYQqrAnf`M4Wo8IGHg)*}2##S3$NI9k zW{ny3D3c_oZFE+Pq6vx*ZRrxSw+og-==Px4YEz4Kf~JJn_UzWTKR-sxw#n2WZMO&gaxa>R|;>Gsj2tJo^3QOx~GeVpRkMQThfOzOQZ&3CdAND*ln;VqC ztZv>A2&AD;q~6)oJB77W z*oAlE#D-E`3>ixselGpwZeowcF5!GBM8V=`F8k0`jF$1HvM}qF3eGIFGU-2X-`Uz! zW4QdS-<}g63IclK7Y!E36uRfp?|$5feK{DT|+`@y3k)T?E4nxHp0q z9$~G>qjhE0AUbc;@U!nd@beqkn*u3g12{HMi{EL~r;k8ypa41G z4j0E?92o%Z?eC6^pJ^n@Fbu*5jwU|^)c|{dhLEI!(oaW*)IT{g{+^uk>s-HUw}11C z{1=Xl--2AY02YGZ?F3AW0B3~B&uEfAwf&~vXJY!3WrK+cAjNkgWMcZ06@iHvU_o#r z1msZs@!r3v^nZTIf2s7Dm;ldzK3Lg*+y2vkRzO+_AXMd-v*ova|CCq)u!;QPLHS*+ z&IPc%{7J3;GY{k6YIUZcoqwp+|8{}@tX8LEVx?yU?5yHsV*MTv@$!GkEnxy!LVn9F zVPa+fzvPw}0760>7@Qc~{w&!BxLf`z+5Xk=`zZb%0K&-#2u}I!1v4QNC)3Y4WMX6H zWd7Iq4`!C1v+MsU*j9GuRrMrrsbG^tsg%JDr%g{6VW~|T5ltE3o*8g^$6_`xL>pBj z-``L_Nh34Qnh<2pHkiEDKx*6}9-rBoswhoO?AmT5GA@%?BHmN6Db|GPSbNpXAlHvY)lTw zb5Ok=$r}T!96U_y0EE*;kQ4IrlRdC^RyXw!T(yBPZkn(uup9FNqG1Fpr7^_!q0e8D zIB=mC8L|An9mNoS1%(OVBtk+D2NLpwQEB#L5DnFYnk}V}z=(!Vdr|rf0r@-!`A;Af^ngm7$iBy@o2=oSV8$s?i7@(jC<7pTsIRotXb^%1#NQ}MBgfFK zfklV1fXqK47~bfJNdyvCrOYEyX7~qm3ffWlZ9T*Gfl!`dng>8A8dzPNzu8)iAZ%j? zYN&i&1Pjzt>jBx*_<{O1PzdJ8i4@u9G9=3M8f;Nb=?(=GNC~w`m}!XZNn5a`dMVZR zEU{1o7r)B+n*yrj zH;U?Ti2|zGmO5Vm-(%k8MEo`KRjWtD%P};0C13-sKK_&_&_+{){>n5s*kA5l6Yen| zd6BV;o+nOZ;-*4uLn;zjp5%1kfy7Hu#kpd@>~X?_v;0xu^h{S4h*SgD2;PR2r0lg^ zZj-APZFcJE7j!w^MI^~n@|1Mi+w-Ws*E)f!-p3~dI)c^=rTXFByorNg%_`00hpSL& zD6{ly_30p1?b+DAgCo%d%B-n!r{~QWuPBoVK6=*$)sw^cTZAK;EmBbY0JBjuhT9u+J zm6T>eY5(a0f$Jo_?@Fai+A1y2nTgIqI(G7>#m=O1#^F=}6Ib5c>s$X4@L=ov$ABZB zEe28yEO4941D7^kR}f^WPa~1@qNA%4S2ig;KI>bZXIZtH??(U*0DmC@cuXUbtW}i? zu}`6{QWl}`c0d9tVrWiC>mvI;^$BcHW<9ZXq#zp1d`)**4ttuM#s!f$r(mJluV=urwU}TcyzSa=lJ$2oNG_ar0v_NIWW6l z()BXT&=&2qe%3RzE>dmUJ<{c-4bE7(*vWh^8YW%m9+|up@3A<- z2G!YK<=Fq_;l=_bl5fRF=z#pQYU0(a&v&@I&W+YfsH-8j9YKr2O42LczA>-@XY7*Y z?C~~&vXk*De`|aN^=RK?#vf@dLMayZowlYJGo<(%;BqdE%A zvI0jN9aq%Ldb9yt-;s!`mRcC82+wnrnu!a$*S^Ha&w6cjC^#NImW(0taxPftD#dX7 zC%Kt%beYL=Xlf%4Sxd62$)B&ysKjBPt=(O-(lK1yl{7H(y=D89?i$S$yBGBFx^A7~ zwTUN;?5m~b_1_IG)E9U1QkTZ4wI^8ZN-l9LXJJr;sCk!9_0rk%v!tsOH9Mj35Z^Ja zKZe5af}&iI;Vsi*8a0!zR~$F4VW%DJwvu+6WqFFzBvg?x>Jxa-yciZ<5dm+fU5^&O z8os(!`Up-3HKjV&$g|V0Zf`0L;dkK8--kSFPskmQdNYo@ait@|mAlzqcvNI_t~bzF z!Z#EU&RD2Sh4(J@*i)^B!fMKJFQ#|Gcz~*veAE!I^!||Av)VR0kCJfgc2m2{eSIv! zzYr}zcD;~(^it5W082c?Tl3!aZE=6ItfmmM?Hh-h0q&>l1%VUO;JFQbhwv5omW+cr zp|Xg@9|tigvGT+|>f6jKMZ2Ch-A;CW$%7=y?K#fxOOJGv-pi|Rpe*rmiN1A$uTkQT zy>?FyZ$?$GI&`D66dV2cA>P$Wm4Ch#Wa!C+?ysNIk>nb&sa^kQ;sYAjF3b@j@4 zp(#S^mugq14%;d~-TLMaKUEXw0XD4Sj5oBi)XZ6l)Is84~h^B&@|1}R4%~~@0sL=U9);sT+Me5;$|cmZqM>*xuHNk~O5ow~IylJ_jim5GEKpVw%A98nyv!lXRN$ABchV=Nk9-)!cvO;Rb|L{(=GG77mV1BIX7T zgj_$v-u@l6$;AF|#K8I=9&TX?895Q@-#py^@@4*9`#M8#(eMxC!301LfCNrk0I2w1fR8@|jbGR1 zccAgp1<3}0F2DW%`Run>KiA%WJo}^fkM^Iv|2D_|x_-Y8=I?Ohe_)RN+vxlmZUA85 zzmNuCur(x2e#Cudk1KaQzMTEe zjn$3g#~0tbb4Oj@1AbT;a9!MfY*D2_C-5L*VbDpAhFW1tP$)4nD6~=qP$nnd;E#YH zJscpAa8aOEICViyXu)C&T;(~=LI{75M>Oil5Lf2{Q0B*4eX%1ydg#K<8Z71y5qWL? zq>YdmB4D&s8oZKbR3NRQ#CAu=(1_pB4uGe5g|djj{DJJ;Xz}bIbT5seo~?*cYhl3^ z-}DBUiUqW?3C9BQVB!oylfV~|?a`Ry!M_V)Laj#iykZW@Uu{6$lyOA}k!Bc3>YsMW z9TIrMK`R))l;p-0!*NT3%2IL0iNC5@g8Cqu!E9Z?O;_ona)*R{J4(2)Yy8 zOeY)%QTWyh?1TgQ{2pScS)ZkP|CSC|XX2o_ih15W1)ncrOw80QQr``-@pmw7hL15n(yP)z4!M@rH z5P|pw3J|Rzzi|*R8eS<3VyO7^hyZ2XqLu>NJ#swni{4yQ%G!d1<>r<Rz0n2N0t639om2{=ml2x#vV^THsA9)&?Y%}!wDxkVrbsNMc5UWu(j91~eL2oE zuIW4j_>ChpXES(Dr^vx-{hGr;ZtlCSAoW%kwze?6u6BgVPvup?B_zxmiS8g=E=CPa zCRUA4nxTW>%{OHn_ihpW<0PvBR%IXWp?mIxi`2A(l-spMp)*Y@J=H!UXfs-uw_|_o zV}nn2yji%UY9IgDI@<=rQO>94vZjDZw|5b7m1m0eenyWI-S6m7&DQU3f*~8#i`6PM zVtia`?uzGW%elz=bnf-&y+8A!!4hAH#RTqt0i_5*)cg^6qa2w5e`8MNf$hP1c&G7B zi4srh2I+L8Qt{x#+SwP}#bj35dSze*g3*WkJW`8}D?<12mF)e}_{>myeX3pa1d~W- z+cwEVN zn+&Heu;PUrK}fEvGYN-BC72zoEpM*)p-^m=u&#IK+dd4sE#1u_{m+0xzvwu`B&m@S z=g;v*)rLbKVXZQhh@nQz3$YLI-om@&Ss;6Vl}^>fJ1<$5rsn_cSWD1!q+kB_fwIl~igYG&Uu0-Bj=m5S}LE5sTpRWv&VKGY^c6RW$2E zVeg==6MIXXiN>>4r>7c|6VIqs#*aEhbzj@iH=HzM#<^6Dm#b>jHJgxKM8b&a$~eU$=D9`C3`gB?s=fV3$|Wi4Ql+tzeCo zk?mY7be`B)L3Hmphl!P%l)jL$JmrF=Pz19W29GbXrRLY0dPTW=<>~AMQKm2cs48g} zEd?czr9=Zu1y>9XP6gRf7fv0+yIV=`lDzmdK5b5}9J$kds)T<0SZ3%^+0WbPE#)Rt%?@6J+p$HPXEA5D1Q^jd9I9BfPvjIJyN9iD44R|&9}j&4`IqLNEiLg zJ9JFDb)8_oB(u?fp+nzxZx&f#yIg%jCgq@(F6M-LL7bO()iylR_tDK0Y|0`=~>#1C*=C<}{~j+|WMOtAKiyo1nHyvZa45+*V=d*=Y`%mbK)8og~Jh6L<`$j&h!7HOK_iA08kN6Y?)EjUA3GYzk( zr;IaadgWaYSx2a;Ip}QDr5|@rT^%;#x&I>EcBf@}ypxt%F$mVq+Wb;l7nU={@pz4Qr4Gcc zdqIGW3x`Co+}?z9O4V&)U#4N0%I7I_%~(pJPtbQ>26Em#Y_-yC>f6xba$Am$BqA-1XI3(^y}9x2)T`R7kD~ieroYsg@6KFn9>Y$kQ|OG~c!aXU zu}3BLX2$V19L7io|M)hYFdA1fUF(;pDVgd1AuoNd^L={xW}2n8aGL{10hs2O)14I7 z<~+~zud*~56nI2psra^40qY~t-}p+|2xf_PFZe8??2&>vmM;`emX$X_dYxM-`(5xAT%jjf=u7|Br5*n*j)(e68?S4gF=F@MY6XACsdRb}5ZTL;KQULwUSu>mmrz5qUz2Jhs|$M|%W zm#gP+h;HDe76-7epFY(%5XGo%($moL3kJ|^@I3K;-h@L#rFG`(r#8MrSCY^#^v#!y-y-Fe}A5N{44mHe%GSw=X%K+<% z;t(laku!3s%4Ll~01~Ed8KNqV4P)G)Zeoer~w{jNPwZcIMx(_r|DLk#UNNEM#+H1Xxwm*%s-1oET?@2=qBFmR)2J{`6w7dBb~xK}O^M(lta zFcw3EQ8j6{VE#v7O1ewX6KK)ND*It7pbyddc^jhXNQ<`uV8MbwjE_*lz>IrP!yq3{ zkdq+4Hj_vqyS&2Yp;0{}7fK?>Pa{{BP`u>Wk z%#T{V0B9t88}N;R3nz7ZkQ|f-MNzJu)F(#+N~7&N?;^_wP=IjR*H2ctaIXrD-;`sZ zA-02s{6iq1D2qOP>5K5>dd0y$cRZw5BEh3Jf*;0tv`i1+?^oKcU2)cBh)&fy+bPO2 zOfSf6``+^H6hmp-vq8p@ZIX@saJxI}TSW`nxuwlWG@AESIqX|(F4;T>`ir){NeR3_ zl=e5qN3e&Gl$H? z)ljra(I!>6QuManMuxvXJ&Z>I<4fpP^r{=IOOGV(decr-9s3ueV&(~(rD{ZoDvN<5 zI2SsLgcw2yv);lEgCCr_tEMiUHcoGy!fgO<;Yx^8A~qivuixJmOw1xio8ULb}<*ygfDetm$K)jRT%CG}ofVCK} zg)Ob1wN-P+#C^IE{H*u!uGWlN{|% z#*Ct4$GoJn6e!qhDIn8OQOwAKE@Ro6<~Mr~FbvA+MTU@r05hzAAM@a^M1g%rri`)* z?&ehtL+jdURSnQe>wj_K@=Xc$r5P%^u!LL7h66sqD|~}m>`Fhg~yez zMY9~`jV86`Q>KSZAxB?a$0Ap~%gr{LPNj z>qBYgX9!ix9M}bAixXYTwJyDe)jUkBT|Hw+(^glJYUo&_!_sIA#*tig0=TUwN&r5f zt3WtB#+c?k^?b$|kJ~FDFk0=?dlH1=96^lp7O)Wat-Nmks@}@w?YOVjL^jr~?tE(# z;Vht4+%Z0&W0hJkYINE&68?qUXd+Ts!>MQj2x zr{W`;wmGYwLWKEA&8Hmfi@muH;kBSs?|?p0W6XXC>dUE;oHNS$vqS>y-8Ds*eC`3C zit=%DwS>!)ax(9AjIGEe3a;DD*O;TE-0k7>Ha7}WIoSOtb{CBCa!tsUu%T%?F^#u! z$Gf96c=?x$-XU6};C64%E<{I2BI>y{UZNs+Ohdic<-E&KD~DtZ8h`L|{$rhhb|wt{ zy)F6=dfyFvwlirz%c0Y&tDF4*p|^{!w}SF6XR!BglsM-r2`;K3EZXpnH(0E{QPj&A zFAH<8Mzr}}uD5Mi!uiFKAj*1JFCHG@v)s^Of)rI&RbgtU8w_y{!I$r*_;-V=FW3v3 zC)FiO<}PbIV4zONV;wJOyO^?a6|X2uM@>mP;%*H~qS>|d_qujFK3>l591z^HP3e}C9+Wndil4CD)D~rAANTNIxLNj|%Zdcid#x!Qbu<@Rmo3SI z#IY(@S@ZZC3f^aNt|e)3vM@Mwp+nYf&Nxl<|fZ=VoDP>TL5+;1snhi*@ueqgPgRdLCKA**AxEOy09wd~d(}rK-1;tOc0n znVIal$_4F9v+@qNxsx#g4auzL$P>f+OKDid7Pp&D&!7eTyEp!mf_E5BXO<12Eh@sQ zfj(97g!@Yqhe~N5|eNUm;bK6CHNEWs+ZGJ{G0FTbn4)4Du+k-Et&b=T=_3 zAHR*$Y8-Me3Vbm3uYyRi%PGCcp8ocs6j?925qZSIBz8ts-n|s1afy47T|QMXxwc2? zE$1jCQ0)}7J|OzUfL9AcpUsAc%z#e(;hhclVrO*_+ZSJgltP>BEjgT9jT5s<_TmHK zu2mam?yz^tBWI)^uIbw%&UJ|{*Ab@N3W16#Quw>h5Fq~_MK0muGsFT z?zmh7EiB()1qeBQ4u(K>rv|<2b&$N#^AZa*V*Oam!u@*xSgsxBy_aTvAP7TOnwJR@ zCEwiZCXE1A$WS1)V+>0UEeji764gL^jy0=vwp8aem6mY98@f#X%pG=5H?nAA1ihOMg7|vmN?Jn+(Qe7~39YZR} zYDAm5$G;qL+LvP(U$u4vYjaksi1FU~6tie3MbI5zvm(tzbBK+JX8+ld3Vp;+E(JEz zj8&6_U+CpS3AI`ai!vRg!2MoAr8`bY;f8Hua7J+LjNtOR&g?5O-Ck>>K~XPn1Jndh zUTcmDcR^*fo)I$=W^I-y(Br+X{HzwAT=nxqno=vAhD>xXHPAbVx>A>Iw~!<=|25=9 z8NAeLT9#sdxV0_^-&ldMIQ;l#TQ}O9tn}*CBca;jSUn|8*OU#@NKM_-VQN^l?fM1O zindO9XiqklBZyVc&Omh*cOlBP{xWw@5a>PIC&(AnMp1Jw)2Dyy2U**%9+em1-XXAr^L&Z}Q1zF~OqQv%R69;?k#8pre zYqRKq;%FIzm(opo7pl~`sS%iS-U4EI?Q~v>HMM!;b+iUvRvQlb7!O(AekF1tgrn4X zG6L!+Z=)MWS$d2yEAu9DO!14^5!R?D<07nVsp(N^zHblhxAT~$m5(wZ2CU_MLEmj( zsp(!))d`ckM_|J&b~s?q_R~06?V4j`*R7#bB^Hq;WLpF+W6-0+2`;g;?1Ot82M|JS zxDk1Dg$CsI*jZFG;e=@C6k53*JH?{M+$RrRY~}1sm>tNV)5OH1B(Yzj1k70FD0GWd zgnJLaU*&DwMYbB8Z$r(M%o|~4ocJ!mho*7~Iku0hpq_x<=v~eNZl-)5#6W;^6vw|X zU4v%LlD}S26T68)jP6fb)xj-y-OHqi2%2)6_~iao+EWlocPg>vt4~CwD)6~JH$8XD z`_v!UA<=QHA7ksJj@zFOJJN!FSUv>Cr1u}hua{VT>d`x_+!VzwP2oiFB)5^5>PBYOy+7j@ws@CUlsbih%ONc%KySLL(mNOf3 zP8Z-#)NTFk-t(oFQC}!-jbgLZ&g~OpCiK&j0;E_4Z))3*YQsIp=w;G$ZNw(dVz!G* z!O+d7M2`l{cE=k;OY6-^p6g8qRni6xzA@&td@(xDun62jt8f}|uMj?63ei%uHg>L} z7+^RImcEud-%BJ;B5>F_nk!e+4pA%rGr?127Y z8|@oWvQMtI+XZ_8>HutKlkq{OKbdcJie%?K@yRd#)Dp*~r2d(rAugv0#sl zPc2oxAyora@DX4Q7MR)h>bHj-sM$c=T{i96WlfN3JI=KX5&l9=EDpwsB|5!ta=jC# zHkBup=DN}0Jq?3R96?su+Gn_#7{x<0CHaAS-;9(l;6mPmRxl)%T3*EMiZ~cfsh@^A zD%gmoQGr3NAzObDI)Z6{)C9hTq3`KD?NM}q2*<00wtPuf`EIKWkvxNnUBz&QqbI!X zN?!&@M09&!UDT3n4Q)ZW7Fj-}7)XC7@*0YH@CN>>0F`TprA-|E{i94f{3Ans%sYwy zxIG3a;{J!e;-Ap|ziti?GBX2+dVYQwM<+lXcWW58tU0Y?+nq+_x3ex`g46GPs2j$K z5Z3f9>_Yze>P-)EX#O@8H!YX^wQc<0P6amd?k6R8_`L)_VnSMx*>h$+jM?GOzBq`N zLA*{$!xH1r&{)$dNl#lga$1#I-9M@1BMT!FC5MFen2$vf%8`hw(a5lJps4K5>L3>s zmsrZt)yPswyw2?|9XAQ9tD=e*71QsV$toIxK_Zi^?anPB&OJ0?e%<~#59Cneq{EFaE$_wIrp&eLOU68c=Sv% z{W@GSj$MAm&+HQ9Q{htMjsC6cc*Du3UE56_(f;~8%;e7TEzwjDq8szH(YL?s$2sx? zy?WR04ezPwx3 z3C(mJ%n$DzK=nx6N_K423n&X`O9P&Lo$LamnPprmdEYiQH@~ei@qXR8Y5koIvJ1yx zU6s@ui#DADU3WipgRoqEmYY>Rce(cX=<#i7J^hKi+)c>=`J)kv?2-rc>#02sR{^AJ z!%a0Z*b1Jn zIvG?88BUeRqDFrF+~NoalufKlsudlfA+zO)K|QKk<#BfNFg8=dH>@jlw2R7`?;LLy zt{ha2Xv7f#J7x`>boqT^3Ne)CJ^o?L^SfnA?ZqvAgim{YVezmNh2+8`;U_aexM2ve zSvAs?2*T2X&F;bo@6A0?26f*wFm&t!IUdHlyeLly3?xB=2TDvOuR|M#mkd+2Lb2BA z3aGq1ye^o}g<;kPrn>6SVLkmgg6j6dkWuCg+#O9(S$H9g7_KexjVrPJx+}6j9|$x( zfe7x|z_Bx@LX?(-U|Gd1QpPWY@w>KD%_xG?*C5+9w~5^8(yH$11^5Y0sK71o@{u7Mg`_1iw&GRVc});!PB9!|DqTsqZY zD}8i+LSq}Rq&K9a{(Qw+A|#^+Ny^W;K;YF27O-%%-cT>!B@%XX>Q=M4he~#vzCavs z4Rw$;dZI{UTBXyv%WT+4@t@sZnMxudY@*6WYwXgS&~2(t83@_N%=b3l2t!_*wkd;P z;Ff}VC~k41pa<0~b`kX`Nw%q2*x}$cBr%0GM~5lCQuTK9>iMk`99_`{E{{#_82GgjfV(s6jJWh69&l4Cc|C2l_+nEhCCj z69AvZCG*p3M>5ry34^ie6nWC$UaB4^|$$+79``4^0116d;`Lo$s!R+yflhZr7@aoq=D+y_%lCO!nQ z87{((`?nK&8;9QGs%OL!xW>~b5$Z-LWS2&B@O6ShgaX$aValu`bZ750XPRY-WTz_3pS5zFP9Cp1xk0{00WJ&_f9>d?A|fnjsa_iilg=3<)>jL=Rd zRp=@r3J4umLBN1PsE?>x;Xxa+uX)GaA}5O-K0?SjZ~kP7=n$7flmYj>B0e8W5>B>d z8BKAKsUoyIot2&r?g}Sg*5&NpVxYI+$7m4V78g&h|E^u6Jf2tKegWZ8Mk3o*2X#s= z6Nrdm^cPU7DYH*edE4xRd>bZ=L1_-v;&vl=@_bVdxVzrP+D&WOpT^+gmEoKxCF+UV zab2M{awdBaC3l(U+05dOv6D?8C6k@Z?NuIDKkJ?x1fMBr8^ zQwH{05d%bz_ni~SKyK@{FP$-*1Us;0@O4xxc$10>XAIo3pVnkoT?)Gw;SHh8v3wg9 z&r|;R&70$u8N2yxg#g!o`!DW9aAYts9t*bP}7y zbI*?UF|7xz4o4Y*{wG9g&W5cPJiM9 zOBph|oD2WmEJLYqx`L35f(C%zl={bzBfvHJ z8w2%cN#uXcZvupr4Cd~3<|Z}(Yug{{*8h_@mI;t^@`nWWpUiiRfb<|UfK>L+xj6qs zgaRCO|6A?sFUQ{hg%bUBEq@NwpW}6Y&ZhrAAO9SX10Y2I9q{vOKL6|0pZEUlQ~hlD zH);B7aDSg_{|oi*-{;PsS<}C{1^>*P{!POR7$Sg%mxYiW@Izq-NT>f+d^eKjrLuu5~@RzVRR|Mju%LuBctA=wL<|GA&jFXvU<7a zxmmGpC8fodAZ!7VKtltDOOCh4g%!*tN9&qh520EMYOwXP+?Xno}&kJK$$OTRfR+HD0cy z0e?ijl1do^S#TAL_Ex1R*f~m`B>~~Q>jXIERGsO4YNp^_g7s8d_S`JdTw-aumsEA& zT!*6w8tPEgnQVfsl?r;H4Fly`pC+5L;n;gdT z@=;NImrz1mmtP6!8mDU0He6c8ZLogGrSih`t;VM^F7yKHnO!6|JO$yx{8rB7H4I^2 zp@0S_+{<4pLT7iPMy+T)Rz7yPhBGKwC}RAD(3Dj%lCDm=)`)Rq93IuEvwrCeAJ2>5 zE8n85B`^=z`b380h1p-}V1Bj}F1BL26Qk?11?dy9;eZJDLsXB*T;Pw#Z}S#&Gm*@U z8oE{=T`dQVn#SE+D6oiKpA-EVhE87RlR}VNl_#->A2MK%@h;EHVb#$i9F;zTk`cjI zE-MN#=sHyK$AV|XUWOI}O(e&PKMq6%-v&6Gq1Tv2dW!S)-j^Nce4k&5gTy;U6%fl` z9$DRKND!I# z0QvP=oKdVl8(E-u2@wX4P6d5@F&k5WvR4`oN8PT#afl$53Z}q_BeTJwDR@Eb`ybwP zvv(#LGjd3;rzhDJNz>LfRh{*fXzP;jhv!vW&Xv*qXC`g-4nFozdR`2pNGq0d81twz z*|6e+XDws<7#5^ho-3VadF-m+UB+=FRPtU9>&dn<5y3J)nBaxJ3pC<+zf;@H9PjTq z%s+m_o9dP$5Z!VjmRV!OmyOvdor^6#RI15 zU!TJX+vurQ)C}t$0QJ@~DViida-3cx(zHwRc1t~LKnCNmyl*kvvn>3wYq+pyZrk0nHT}|jB2r#>C@@Vy-KLtRC}S8P~n3;6UX5( z&li$`4?;IWA(pr#{?P>N55sMu!DRxt(Cw2`r!+)z(JgGGRO{)krKS9HqoWKjJ|Ffp zR9g*P@e@X)lvX~oqvKMgHd>j}=@@e#Iq&MX-c8PZmeGKJfMlsNFes%%zDc=MeqQ56 zA8$w~2SzuKNr8E{u9T6+Um0o_vt-x>#3E;NL8fqs0)5?j@!uHI@;-CvpY;bo1kkE5;T zsDk7o+XAXtb<|QBHkjBKHFA{pMpk=oU6tp{bUrn`Wsu2YpCOjfk12d26Le3{-bG_f ze&FV$znrG*%Wi*X^9Z;XX-fTArQCA6)F>QT3WTQ`V>`RrEh#PG9)^%#iQ>*);q;xf zW$WOH!GH{Y)J3w>c@s~hf^*IBxaK1j!`c0k`8`sd0w?(`A`WGy-LaihB#h?4cN_R7 z7I`*>2d=O~7ni=F`kN)2;@hso>32{z*gB?VI0dzcDp7BJ2w${|)agph5lQ`uD@EKo z$Y?%0#NM}168OCr5fA0A$vLQFEv+GcWQE@|{#sm9)Wwr2y~=5Q1f@i5t$y3UorbxP+OlHpk# z(Ox=`I|9CDV+q;hpP13uzx>`DXcM0WiHmc*pQXT0kG-qR9;WGOE(U(u_E3oM#B3wiLh^@nXmq#uiSyr&5T~HF_%^~WzVEQ2L z4%_J{+nuPI>s=Jq6>H^}J`rOg{(q%C2{_bU_my3W?4nGT>|^#BA|d;}XG_+MeUEG{ z$R1LbB*`wMkSrw;WhYejEy|uysr-L4C}w=`_kPd+eR|%f&fIhFIp=rox#ymH&$$QB z-p@CzzS4Oz(W_KSbgIX}I+4cX#TZAw*`Wpfrsgh$?ze-=+y!T*ly92KEmYfbhsb>% zX~$lkqFmx#t^1akYI(yzNLlWY4mj*MUvn4Jnnz`5!Gxb}cKSH=&$quW>7iDqZ}!4& z-2HldT>c#w=W=yqAKQEL$0WbB&RH~$y@RTVhL6PzO{Dw9-LRiY_UNn~8?Z?*^={M( z<~2Vh({6bzUqZn5ctT9>;#>ZG#mu^2tjF|%#L)^zsG+w{uukgIbPY-8O$O>uYWhif zf08YVdS~+^qAJ!SsZ!qr;uYs%ele*~=KEY%oDHoCJ51@Yf-u))P(0iwzmPVlK1H9I zPAx1TpXbm4khmRi> z1SwgR^DVJYPUE8NS#l`}c zTv{oD{0qC9a*HSJQfmc;Qv)rvBqAdQ@>aZgT~%%?Sje!vaI};SAT0zI#@Yazy&{&ug6H>*VVU-JO&dko8>dFv*U!p@ zr<7WsD4Pj_(5MI(=~oV&EYbef^&*-t;2{G!{{qIdHkA7nzZdyf^rT6|&~+*eItZgC zbNIECCt%*A;jG-z`-7`yFI>!yKf&QDpV-Ce`EdB9L}W^gIV0?-_%HLx%C747EZP;% zd50j^@zMxz@aJBTavTp)KP+D(Ds)o_C(+%}UsrQL?E)4TZbQ}C8*Jo$5tq1)iKQQA< zTkED9SYTr8$)6$-I5#dQIGD$*Q~?Q+yz*ER(Hvs*!s$?x%SEBR@0F{V&iTYe|Dd9S zlgQ6w%d+#Hic_TZvk3~GYPe{k24yR}bi;x>P5xY+?)r-w+k+pIhw5bWB7+BrTIHH|n zOiVtg>n3wTS4p?>jc@%g_qK~3wd(^@Tz&nv-O$yP#4rA^a@NJ>n*6-6(~fyhF4pdw zf1ah9WogMgbhVyu?i85*_(je)3L2D#;Dp44NxE3eqg+AkQOky4FD{dxkm(x3XSN-S z-l?JU2=`@=r+da?7~W_JSoDS`R__z$w#nYV{Q4_H=TBPyF)r?Nq;mcDeGHh+faG$_ zT&}+$8DG1+K+R}=*3u=~uX(}l80E4eOQN-p2zH#wY*c;On-&y8NAseQvayOHj!8A& zRP4qcZ^x^;Z=YB*8+4k#U?owIVy#HHK+zz7AS8@ZcK=Gvd9o2*D;YU;>ts*W(a|W~ z`9Nq)a=DMf9qj;We|g0&f8T(Qh8*@6M7hn*YC*vV?dyw7FIc$#e4!s)r~2q~lXd#L z@-ia>*5tj$sc(Eml9+|(mi_OG6q+nOjKcPW4Tf{xuw$%x7w<^Eo^@gFs`!51YtK4g z&e*IDf6=wCPZ3!6h#;r#P_l_?Cw#~zoAf3dEkaWz7zm1T8aX0_iu$uw?$5Y3R^&{jVLM- z1_CN*ZN?)1dlVIqw?)jqilPD~t2RdZ6GesYh@t}j*vt_DsKvMZ8$^|sm(x^K2ZE?N zhP#v{1Kvd6q+41^@{PepGH zxIJjQ8R!F26#jKpFarLF;(TyGI2+0O7~pSzQX~iheIhV1kcb$dolsnzG&K4@rR#4n zxjhd8wV@n;1ABPDmISu~dw7nv0(;26NfB@$?Efd^hZ`JVe76ODdt6UPkA||xQ}wlm zvS(A9PzUlYyhPh&8exusPuhs6-Ln;6>aA{T(d84Y{tg`?hE4Gj&$EGCSr%Sn;l4PWv zn?0O(<31f}r`7|yc%u{}-CN1&4c4|fF>y&I=`r!isYwl)v~IEI&l)|uB6b>+S+eK2 z-Yp|t8jtuZy6VxxUqC3ch)u8H#ELf~ur~q%y2R%q_6qs_~!k%~c*`+&b{!y7crq zW$-!beP2|W@(wV;mbA5n7`25ifqQzJnnd^7Y3(6bE08e?IK;wlbosTC6cuYpE-%Ox zta=?IHesMUeb`WN$|!j+@O}eA2ZBZy$Y~{-80p3*8|+gTsu{kt*af>RotSJCo80WV zWEAkoQ>EvtqodHY35(g8`n`lcde=ATFv2t+sldAAG%RlEW*Yqoa<%qlULt3hq4!>RJRgiYxA^8`A+~D0q}$BrD46CpG*K ze}6F3tNXgbl>|M%*}NNt&jRu;nf}ynm>vu^v;QgfbfroBNVV^XOVgslk6#Do)~x)k z)Fn`@-$XoR`ka#$D_%%iW~sG#DW*WFKM53!YjxraInhO%ZGr+f=Ue}64_ zon+6_pCIAXXgwU8V$8r=c_+VDs$-VZc>YE9YQ=Tt#QlS#R?Hu)12094DK0=;Ek6sb z+-bRCHf7y1o{Bc_juIi0IM{r^*XGxd*~o7rZncYZBYHo<3Q*E`^56d=m|2 z*O)|ebQdT5jr~UrVy48IuL;a|RetDh?SZ_3&#o7XI}e;t$z}g2!|`Sf>`=XEX&IC6 zBR2wDr(T*9c@>%3o7HGg`s;U~)ynvd=zC^?-2t6K^i=U9$?@2E_ciy3b9p(k<rDOI(QjWb)r#Ad8rsT*>FbL|Ya9$P;TV)4;lFnG=hB_P!e2|I{wMv* zzF}Q|vh2x)D30uLJ?KHIIT^5c;Dh(eE2YzJ=ODR)Kc!pK50u8yE(SDf34+rZOG)jZ;R!AK}wbd z(Z;GnakiG<(nmrl)ml!G6~&O>Wic^5Hsjo$oOC|yE2S#!gh+=;M@CTZ^s4lp$=>NE zBwgK+495>nG5gTi3orSh1!4Use~ZPvbvZWtQh}#zPO;B1Ex=vx$wBK-dPj|SELu8( zLG8CFJCaLQo+>w8yxR#{=I8-)m*!VecQR*Js^7(tCK&UO3mXH|?i(mY%PG!hw8{eBx1i zxzOn11a>~TJGIMl<1RG|?os|>bWfc5FU`WFSGe3B7(S2Sp=h)OdzH?p`_fBS9eAiv zi?V0al26X7Mrq9lxksfr`%ngE#OTBZp@NBBteX9v(jZx{ zJ2iLu^+;B1((j#ydc-s>f2ibZ6^w3s{ap6X2xpZPp%y?1BDQ`fF> z+A4KL!fwT6?Dnz4aTB#SpK{Y-(~dW%uK`hpA=D9AqtW35*{m=zrLse>>MwpBDAS^H zI^_C&?&17F*p~(WTO-G;(u*jLkf2U|T6c`IRcz9tRO%7GeKqRR;rhHX{=C%)Z@QjL z;QG(uoH>v4K2M)Xe>jFHWcb;8F7Earii5|D-9J>e8S^kVmpy2RZG0|wtvt8VRgILv zjt)T<6!{XUOFN;IFi-bjX%I`9khH4Kog%nudQ_cdxfRtLoF05L!POU2dwg+*=bp-W zBlGKCsIVt}1B<+tN@-FG7zKa+cx>`#u6w@iAfYfT#)fN6F>D!;#}?wgO=?(5hEQhh zo#!|4{u#B*>i1>-2Q}YxMADt$Gk3l%fipY8ncTcpZS37VEqa?egb2-FqHDs@5ihOjZ5wsm~t zpr?J{eX*cKW2Yg>RgS znSbBO^fJx0ASa-fNf5#e|=(X3(cA07)n7s#n>` zh;=M_`tdUIGGfHz3h(JrSq z!!*s#-W7QbmU7{gCqJ@e<6y3*@bSS@R_heSe)d8g=g``Ll9X>j7p)-2H5aa?UpnL@ zE!I@tJ&`dITI_G+cykYB|5d-_pv4ZZl#H6#)autHJ$`#n%ifnymz&?;o+n^Nm(a3A zrjrvZ+UVNr|AKDW?Apb<-ahM?%mK}WzO}@F7T+g9PfF|#MGsr|^h+K|v}iWbqRF%U z-6))WFON4wsdsE&(W_4Dr0n9$F~+#WNVP*KEXeEJ73aypQQH7!Witq@br~|!o6ylOThx~ ziwxeCBFltQDza7_WlAH9P%o!x0zzlOr89l|YY~x1229-v=_QG!+!HctJlwb6k2IG~ zQp<&b%X&YTd)$?eHI`C|lD7~!6Ycp_w)@0MFV?9}?*y98-;c~QKfNGJ z{zBR%wB*1QM(`)t3|r+m3>p(Q~(_PILG`$Zim@P z`YicLULg34f=}wOl+Ss|+hgNwsw}pTYIF@`yixgg{7kN!=Ik}gDd>3zIXaVQS^dzh zYKWfP?yHaT-PU9C6Xr51Q)8+ct-`z_+1*m5@49YUYL405)gKs`$+nfZF>BXBu0^IM z**M3&XD{oUX~}r+F2mMx9(vb2?Kl&)j5{^UD@whWHOnq5RMN5O6%G?|dGYe>AI>+! zIaFR6E9>^PDc =;&#gm}*gf9qV^;PA9cnSluYyq|a{X@}Wlv(sWgwxXgMzZ$%cX zLp;IrqgGefhfkmN%BBqbrJd1}Z?TRt3>|ttuPa(gU%PT=fp6~2&332aSgs?Ivh%$i zpKEVPaaq1J{VsB`HG8FexTbZQYGBCGGw@nmH|Y|T^O(fadD=DQu~vgr60l!S`tPuo z3{>xn?1-0074HvUgp({UNS@>#P3a_2VT` zoM*q0iH11TJ#M>H{Qj6Y#~E_dyNz!vSo-c{8_OmJ`Q_YV0cunk>GD)HE6W7iP-)jR ztHgiO$PvP<2P_DQ>U(Gsd$HRu+5D?;)5d+e|1I1E)W#qPqU?y*mtO zVq0(qnmpGr+WdP>tWhyHOt+$hHmT_9f=`W#HXE`WLkTEeO=ldnxJ@ zM!)q|uQmuNGC$#0yF95(cUhA>Rys7%;l z5KsB0TyDJdEXL6O-6_hw*Snssxlcr0=hyhox7eg-kdbSO8_Rkbo*Bi+PJmNn)Cm4#g zA8wb5dIf^t_Ncq5lWvvCP5xsfI~0cI@8o72W8hhGL9t5n2+b? z^tS7Wg;ug|rtsCddXe$w8tR$0&+Nw3tD=`-vl!vSnItb9C(>>fKq3#_mx)xcx0E;; zY?2C!eUF%r=(Nd#C!A8QG}t`U;*nPP^lKh1wEU~C!gzS#Pu1WRNob z@o{y^E4s^cq#0%0inI=@F{IkJK#qzhnl}2B*#29~s`Ng{xtE%tf6V(p715?L^}re4am6towxf>RWxP_Yt-?V+1lx zWaMMc9_vlv<^%uk#iCC2Ms=xTE9>L9ra$^-vFUfeJQ#D)J9*h$9(!x_b(SG1rLXHM z_Be0H+XW;xB;z6nm3CjIAtzV74ONCia_O-GmB;sKjf{AD){-kjo-zip=gtJY2&uE3 zN*G#?l90S(7WLRv%+t|J?pRDiM?8tN3VVgT!F2mM8nem9tH=7LWv^HpNA#Ic=gkbL z-QM40_&eva-Shmf7r58!W$j+kn4cKqWVu!fv3&U6aM;cL){uou<>~lLOG6pGBjAjBIFy%8Cw}&m3a@~(P#m;2kyvYw!a4xkx9Q~uf``0LY zD#RN`?d28NN|k?xEtcYHeW^p7uy5B-0Ww|`P<`W`#@EO1)kag?+ec?l^-tuTj7nTP zH%N9CYq_`bW7-V^WRVXqn)gA1V~+#JoEF2_r*gGi9rP>bZ|p8BNyhyF{qG#dQ|jIv zMJu^~LE7J|-aB%zqL<`||MVp1DU5gyTOsJjyuJ5{a8hG+Hq=As53m;oi2-wKq)kiF zw!${vVH|spVf{#vG-(B|-}=-Jx-`UnAbUc&068gqE5*^KQm6WrSBAsh>+ig>E$Lr3 zlvO4it@pm%_Oxix@3$U9m-vU}ihcREnq#vZ;9Cn8(YZ&O-7-4{GS7Lp2}bI!6xNEJ z=qnB?aj^br*fb}Ek)L_+Wm&;&VnCGQHh8r3VYb}4@W7AuaoljPO1_ZxRQoD(!fT1E zl`9gRUTV6xTUI5o5z%@XzaS-3(s^R<<@d5*kzH^#{wmOaU0h-&p-yA&2br!vEm|}t zq)4$%pcB4V85$GVrN`*2PWsC)QF3IWfwX5|{bx>6>ySN2l@ZigY}qq~scwDu!f1I4 zmzOo>zZWTw(^z~DuX9UnOr1FSE4m{ryi&7fs7HC`fU_tcLsQT8Q8w%Q&a8 zy-OiCbd>=U_2WsfSuj34wx^wC;F}eR^~%Nzns+8&o=+&x397HeCw*4>7;Mi7f;7YUp8fVvxo(= zl`p*BVtoQql0_s(d)96j=Y|fPNt&UeYNUzL{PO&Q+kMI#ytK)FIacDCqi>mwTHM`# zm#vDPy~0B5b5vB!EQa9n3wfPg`3$TLD=j8)roz3{XHE=yj6}(bo=-aPLtGprnLmMw7t7U^CgtRR;KR#kSm)W=^3E}%>)DXO zsYU(kmWfY$$4+18_Fg$L^+38|iuPOp)zbNMlZO#412``$fzW~ly=Ri?K3`BAE|h_n1dzKdxoj)!~K&M=;b%(E+r580Sb012uK*PAzn^y$>|Aq$8>MK{r3TFFSc@Z>(3u!mG2| zLI&-{K@0;)(XG|4el`q_+HV+~KTQTtz5Sg^wH(WH`l!Cf(465k%a1P!PsGo3G2~a3 z@SqaTOe?-HjBR)|b6v97%b@nu)#6KuWiM7cP|41EcMmaZJo3!Xi8I)9VQ9rO|Ji_< zvAe&$Q%F~_k^4OCDm+g!B9~f^s(62Cprd1Oq@xjJpPNB=Z1FpA-)F?CTgR$;fB86% z+LNQ@Y?BX0tJEYLSPky7oxAs=q(w04H2Fgt*%$@Tb?MYg5@bI5X8U}hvy>*EK0@A0 zgdfUJq0efTcM8a0<;ZJT!u0$7HoxHf{ZWXYv&mXV-VHyqhy3&8kyl?7ltTN*@I!V7I6avFSuI9*R|6RDbN`J{@ptzuBcgb*VZE1j!-H&;w~OMXP7E8z#~%jwX2dtB|JMP>S$Wa2JHxK)9B^W_so3{^Sojrj~9DXWpnFL(3tr@I~ z^>DBTPK^N&aAiOmgx*N@*h=-nj|%*tj?1S)Z|pF)8JDe-7JglG3!ock8_<@875HO- zw(nyBv!>vz>kJeO1o3;|P(++u@fQiiu54$q4xtZT!g7BsTX3MDW!i1Z(t0%BJIO1~b{xY)NX#X=K+wlpQ z*`a}Wy}@j19Kg(`2JObo=1162BFu(@ZTliy>bMItj=+NAu#Jr^eZ$2h{+W#pOacbB ztK#O@*p#z0NNiKNc4c7W18gv`IkC1eu%)THFyQQhTcLp^{Vx;vfwpwwpPBfJy^|3< z30qxkFe0{jqX%GQQ^9s+gi!c+G+a;oavRRYAC+io@HKEgk^F0X8Lz2fzUU@RSOkB|HFu18m9+4?yAoo6>Oyd{$s82;w`&7peum z;vXQcbKq(kzOO$(`~aK${Q=?!+2rRB5I@i+^?!gUT%Vg95Un@3-!_>c`VB7(pnflo z8o*;$#X4f~+mY>hxa$hGQ7#!pTTteH4 zjU#+(BH*x58=UMwN5auy2olg1V)QMugfo`^JNm}_*fIQuICcz=g22IWB;Xhj4ZksU z{y+FQt@&^G2sjFOJrmeg?K1w>BKe2^UFiQO{2e9@C;naV(J(PE3iy1xjgM2?|3?2m z;cu;rTlDXuJa9A&3`GJ)Wf%7Uh3@?mI-&CIGCCRqFpmN@x4Vo^sC>XhQ`}tIp*;V9 zk2fm+Re1k-e7p_XfxpY#`KR#-l@A}O_#fyeRK8urhrpQtF`#%ivH0+Ia69?Cpu=Gp zFbaq$NbASlL(uEk&SU7}OjDYypA2nY9(j!Uv?O>3qT34FS@J zfW^QF07=E#=K>HYbN@RKu+pCfqCx;8;xIr>AutHA6vGg3s0akf2Z8Y6M$(l#1C|HY zJqvRuC)|L#wpe!%@Mm*iVUWJHn>)}E2o8oKphz*;1}P#iFbrhEZ(wZ!lLeu{NHD@g z0A%lC?qTb0Z4UDKg9H4qeM{*L@JS8alZL^mA%Fe@p^!*85@ZAV3j?$V_aDgV4-ATX z7McJC!#NKGFa%C@2w*5+Z6|~Q4=WSGfc287KR_`6UE0|nAP1uUpeUTdAZUli`P&3A z;3$<427}@z=gxM(+iyhu!H^Ilnqes1!wv+v7@%MX0SpcSZrKyUptzUwcH+VTSAr0R zg5!3KJKLd}UtW;NI*egu!ucK0!O&Rel1P7!0@3-q}tJO~eNRf`JpZ1AI)}-fRahz%3EY z2w+wa;R1po<^1TBWsMvzrwC#i;&_r@ZBE*RF8GzxooI7!W2OJ5%ITDE=n)^s3ifHa5 zkr*NwATh*pMgdPv5PnO*0mtnrchG`@;2!oMgaO#ZFrxVZNS?@+pdeyIe4t>!3?b|f zkQEUvfS3v847iLiLRq1JwV3d`0gg4!6WGZc8VNj1NeDv`*%#nyH!&?3Bredovp)>Z zfhB_B!dV3E&_wnMg~7myXvSc0(MSSZF(REri9v{EAO^vOaChR0?ILI3a}dc?45+k4 zgbT+#Dnrm80$0U|5QaPcB7h-*2UiGTD5A9oC@r*GI}Gs{Xri?Y1w64rC_gj=LBt0d z0_<`LXh8!W1u-rPmjkwg4>SZ#BxeAIi=Yv-!{7>j5x~TV>=ha!hKs)LYzIVZi0H#5 zL=m-v;*Kr}aEa|M8VV%z5VeEj($ENS5ir8<3(Q_zOpl-)l9)HZXCTH!;X<_pxM-qv z3z(|A@P@&isS@Dg9v&iq0lpv+Z!jQ&@wc6an>ldc=|+tY@?tLn7qJ0{O;p?28OYGX zZ6c{fm7HvVmwWMEGwxrw;D!Xu9FDeuLM$wi5KBwAHL%*k%~5b07{nSS2DgEmpZqsX a@Nr0YT$mB>E24pCXd%?RymA`y)c*&VzzLH8 literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/indirect_iterator.rst b/libs/iterator/doc/indirect_iterator.rst new file mode 100644 index 00000000..91328e09 --- /dev/null +++ b/libs/iterator/doc/indirect_iterator.rst @@ -0,0 +1,34 @@ +.. 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) + ++++++++++++++++++++ + Indirect Iterator ++++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: + + .. include:: indirect_iterator_abstract.rst + +.. contents:: Table of Contents + +``indirect_iterator`` synopsis +.............................. + +.. include:: indirect_iterator_ref.rst +.. include:: indirect_iterator_eg.rst + +.. _iterator-category: iterator_facade.html#iterator-category +.. |iterator-category| replace:: *iterator-category* diff --git a/libs/iterator/doc/indirect_iterator_abstract.rst b/libs/iterator/doc/indirect_iterator_abstract.rst new file mode 100644 index 00000000..61fe0161 --- /dev/null +++ b/libs/iterator/doc/indirect_iterator_abstract.rst @@ -0,0 +1,15 @@ +.. Copyright David Abrahams 2006. 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) + +``indirect_iterator`` adapts an iterator by applying an +*extra* dereference inside of ``operator*()``. For example, this +iterator adaptor makes it possible to view a container of pointers +(e.g. ``list``) as if it were a container of the pointed-to type +(e.g. ``list``). ``indirect_iterator`` depends on two +auxiliary traits, ``pointee`` and ``indirect_reference``, to +provide support for underlying iterators whose ``value_type`` is +not an iterator. + + + diff --git a/libs/iterator/doc/indirect_iterator_eg.rst b/libs/iterator/doc/indirect_iterator_eg.rst new file mode 100644 index 00000000..1cb00c0d --- /dev/null +++ b/libs/iterator/doc/indirect_iterator_eg.rst @@ -0,0 +1,73 @@ +.. Copyright David Abrahams 2006. 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) + +Example +....... + +This example prints an array of characters, using +``indirect_iterator`` to access the array of characters through an +array of pointers. Next ``indirect_iterator`` is used with the +``transform`` algorithm to copy the characters (incremented by one) to +another array. A constant indirect iterator is used for the source and +a mutable indirect iterator is used for the destination. The last part +of the example prints the original array of characters, but this time +using the ``make_indirect_iterator`` helper function. + + +:: + + char characters[] = "abcdefg"; + const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char + char* pointers_to_chars[N]; // at the end. + for (int i = 0; i < N; ++i) + pointers_to_chars[i] = &characters[i]; + + // Example of using indirect_iterator + + boost::indirect_iterator + indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N); + + std::copy(indirect_first, indirect_last, std::ostream_iterator(std::cout, ",")); + std::cout << std::endl; + + + // Example of making mutable and constant indirect iterators + + char mutable_characters[N]; + char* pointers_to_mutable_chars[N]; + for (int j = 0; j < N; ++j) + pointers_to_mutable_chars[j] = &mutable_characters[j]; + + boost::indirect_iterator mutable_indirect_first(pointers_to_mutable_chars), + mutable_indirect_last(pointers_to_mutable_chars + N); + boost::indirect_iterator const_indirect_first(pointers_to_chars), + const_indirect_last(pointers_to_chars + N); + + std::transform(const_indirect_first, const_indirect_last, + mutable_indirect_first, std::bind1st(std::plus(), 1)); + + std::copy(mutable_indirect_first, mutable_indirect_last, + std::ostream_iterator(std::cout, ",")); + std::cout << std::endl; + + + // Example of using make_indirect_iterator() + + std::copy(boost::make_indirect_iterator(pointers_to_chars), + boost::make_indirect_iterator(pointers_to_chars + N), + std::ostream_iterator(std::cout, ",")); + std::cout << std::endl; + + +The output is:: + + a,b,c,d,e,f,g, + b,c,d,e,f,g,h, + a,b,c,d,e,f,g, + + +The source code for this example can be found `here`__. + +__ ../example/indirect_iterator_example.cpp + diff --git a/libs/iterator/doc/indirect_iterator_ref.rst b/libs/iterator/doc/indirect_iterator_ref.rst new file mode 100644 index 00000000..d1430e15 --- /dev/null +++ b/libs/iterator/doc/indirect_iterator_ref.rst @@ -0,0 +1,181 @@ +.. Copyright David Abrahams 2006. 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) + +:: + + template < + class Iterator + , class Value = use_default + , class CategoryOrTraversal = use_default + , class Reference = use_default + , class Difference = use_default + > + class indirect_iterator + { + public: + typedef /* see below */ value_type; + typedef /* see below */ reference; + typedef /* see below */ pointer; + typedef /* see below */ difference_type; + typedef /* see below */ iterator_category; + + indirect_iterator(); + indirect_iterator(Iterator x); + + template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 // exposition + ); + + Iterator const& base() const; + reference operator*() const; + indirect_iterator& operator++(); + indirect_iterator& operator--(); + private: + Iterator m_iterator; // exposition + }; + + +The member types of ``indirect_iterator`` are defined according to +the following pseudo-code, where ``V`` is +``iterator_traits::value_type`` + +.. parsed-literal:: + + if (Value is use_default) then + typedef remove_const::type>::type value_type; + else + typedef remove_const::type value_type; + + if (Reference is use_default) then + if (Value is use_default) then + typedef indirect_reference::type reference; + else + typedef Value& reference; + else + typedef Reference reference; + + if (Value is use_default) then + typedef pointee::type\* pointer; + else + typedef Value\* pointer; + + if (Difference is use_default) + typedef iterator_traits::difference_type difference_type; + else + typedef Difference difference_type; + + if (CategoryOrTraversal is use_default) + typedef *iterator-category* ( + iterator_traversal::type,``reference``,``value_type`` + ) iterator_category; + else + typedef *iterator-category* ( + CategoryOrTraversal,``reference``,``value_type`` + ) iterator_category; + + +``indirect_iterator`` requirements +.................................. + +The expression ``*v``, where ``v`` is an object of +``iterator_traits::value_type``, shall be valid +expression and convertible to ``reference``. ``Iterator`` shall +model the traversal concept indicated by ``iterator_category``. +``Value``, ``Reference``, and ``Difference`` shall be chosen so +that ``value_type``, ``reference``, and ``difference_type`` meet +the requirements indicated by ``iterator_category``. + +[Note: there are further requirements on the +``iterator_traits::value_type`` if the ``Value`` +parameter is not ``use_default``, as implied by the algorithm for +deducing the default for the ``value_type`` member.] + +``indirect_iterator`` models +............................ + +In addition to the concepts indicated by ``iterator_category`` +and by ``iterator_traversal::type``, a +specialization of ``indirect_iterator`` models the following +concepts, Where ``v`` is an object of +``iterator_traits::value_type``: + + * Readable Iterator if ``reference(*v)`` is convertible to + ``value_type``. + + * Writable Iterator if ``reference(*v) = t`` is a valid + expression (where ``t`` is an object of type + ``indirect_iterator::value_type``) + + * Lvalue Iterator if ``reference`` is a reference type. + +``indirect_iterator`` is interoperable with +``indirect_iterator`` if and only if ``X`` is +interoperable with ``Y``. + + +``indirect_iterator`` operations +................................ + +In addition to the operations required by the concepts described +above, specializations of ``indirect_iterator`` provide the +following operations. + + +``indirect_iterator();`` + +:Requires: ``Iterator`` must be Default Constructible. +:Effects: Constructs an instance of ``indirect_iterator`` with + a default-constructed ``m_iterator``. + + +``indirect_iterator(Iterator x);`` + +:Effects: Constructs an instance of ``indirect_iterator`` with + ``m_iterator`` copy constructed from ``x``. + +:: + + template < + class Iterator2, class Value2, unsigned Access, class Traversal + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Access, Traversal, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 // exposition + ); + +:Requires: ``Iterator2`` is implicitly convertible to ``Iterator``. +:Effects: Constructs an instance of ``indirect_iterator`` whose + ``m_iterator`` subobject is constructed from ``y.base()``. + + +``Iterator const& base() const;`` + +:Returns: ``m_iterator`` + + +``reference operator*() const;`` + +:Returns: ``**m_iterator`` + + +``indirect_iterator& operator++();`` + +:Effects: ``++m_iterator`` +:Returns: ``*this`` + + +``indirect_iterator& operator--();`` + +:Effects: ``--m_iterator`` +:Returns: ``*this`` diff --git a/libs/iterator/doc/indirect_reference_ref.rst b/libs/iterator/doc/indirect_reference_ref.rst new file mode 100644 index 00000000..f222d7e6 --- /dev/null +++ b/libs/iterator/doc/indirect_reference_ref.rst @@ -0,0 +1,29 @@ +.. Copyright David Abrahams 2004. Use, modification and distribution is +.. subject to 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) + +:: + + template + struct indirect_reference + { + typedef /* see below */ type; + }; + +:Requires: For an object ``x`` of type ``Dereferenceable``, ``*x`` + is well-formed. If ``++x`` is ill-formed it shall neither be + ambiguous nor shall it violate access control, and + ``pointee::type&`` shall be well-formed. + Otherwise ``iterator_traits::reference`` shall + be well formed. [Note: These requirements need not apply to + explicit or partial specializations of ``indirect_reference``] + +``type`` is determined according to the following algorithm, where +``x`` is an object of type ``Dereferenceable``:: + + if ( ++x is ill-formed ) + return ``pointee::type&`` + else + std::iterator_traits::reference + + \ No newline at end of file diff --git a/libs/iterator/doc/interoperability-revisited.rst b/libs/iterator/doc/interoperability-revisited.rst new file mode 100644 index 00000000..6fb6acf7 --- /dev/null +++ b/libs/iterator/doc/interoperability-revisited.rst @@ -0,0 +1,238 @@ +++++++++++++++++++++++++++++ + Interoperability Revisited +++++++++++++++++++++++++++++ + +:date: $Date$ +:copyright: Copyright Thomas Witt 2004. + +.. 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) + +Problem +======= + +The current iterator_facade specification makes it unneccessarily tedious to +implement interoperable iterators. + +In the following text a simplified example of the current iterator_facade specification is used to +illustrate the problem. + +In the current specification binary operators are implemented in the following way:: + + template + struct Facade + { + }; + + template + struct is_interoperable : + or_< + is_convertible + , is_convertible + > + {}; + + template< + class Derived1 + , class Derived2 + > + enable_if, bool> operator==( + Derived1 const& lhs + , Derived2 const& rhs + ) + { + return static_cast(lhs).equal_to(static_cast + { + bool equal_to(Mutable const&); + }; + + struct Constant : Facade + { + Constant(); + Constant(Constant const&); + Constant(Mutable const&); + + ... + + bool equal_to(Constant const&); + }; + + Constant c; + Mutable m; + + c == m; // ok, dispatched to Constant::equal_to + m == c; // !! error, dispatched to Mutable::equal_to + + Instead the following "slightly" more complicated implementation is necessary + + struct Mutable : Facade + { + template + enable_if || is_convertible, bool>::type equal_to(T const&); + }; + + struct Constant : Tag + { + Constant(); + Constant(Constant const&); + Constant(Mutable const&); + + template + enable_if || is_convertible, bool>::type equal_to(T const&); + }; + +Beside the fact that the code is significantly more complex to understand and to teach there is +a major design problem lurking here. Note that in both types equal_to is a function template with +an unconstrained argument T. This is necessary so that further types can be made interoperable with +Mutable or Constant. Would Mutable be defined as :: + + struct Mutable : Facade + { + bool equal_to(Mutable const&); + bool equal_to(Constant const&); + }; + +Constant and Mutable would still be interoperable but no further interoperable could be added +without changing Mutable. Even if this would be considered acceptable the current specification forces +a two way dependency between interoperable types. Note in the templated equal_to case this dependency +is implicitly created when specializing equal_to. + +Solution +======== + +The two way dependency can be avoided by enabling type conversion in the binary operator +implementation. Note that this is the usual way interoperability betwween types is achieved +for binary operators and one reason why binary operators are usually implemented as non-members. + +A simple implementation of this strategy would look like this :: + + template< + class T1 + , class T2 + > + struct interoperable_base : + if_< + is_convertible< + T2 + , T1 + > + , T1 + , T2> + {}; + + + template< + class Derived1 + , class Derived2 + > + enable_if, bool> operator==( + Derived1 const& lhs + , Derived2 const& rhs + ) + { + typedef interoperable_base< + Derived1 + , Derived2 + >::type Base; + + return static_cast(lhs).equal_to(static_cast + enable_if, bool> operator==( + Derived1 const& lhs + , Derived2 const& rhs + ) + { + return static_cast(lhs).equal_to(static_cast + enable_if, bool> operator==( + Derived1 const& lhs + , Derived2 const& rhs + ) + { + return static_cast(rhs).equal_to(static_cast + { + Constant(); + Constant(Constant const&); + Constant(Mutable const&); + + ... + + bool equal_to(Constant const&); + bool equal_to(Mutable const&); + }; + + c == m; // ok, dispatched to Constant::equal_to(Mutable const&), no conversion + m == c; // ok, dispatched to Constant::equal_to(Mutable const&), no conversion + +This definition of operator== introduces a possible ambiguity when both types are convertible +to each other. I don't think this is a problem as this behaviour is the same with concrete types. +I.e. :: + + struct A {}; + + bool operator==(A, A); + + struct B { B(A); }; + + bool operator==(B, B); + + A a; + B b(a); + + a == b; // error, ambiguous overload + +Effect +====== + +Iterator implementations using iterator_facade look exactly as if they were +"hand-implemented" (I am working on better wording). + +a) Less burden for the user + +b) The definition (standardese) of specialized adpters might be easier + (This has to be proved yet) diff --git a/libs/iterator/doc/issues.rst b/libs/iterator/doc/issues.rst new file mode 100644 index 00000000..a36f5a9a --- /dev/null +++ b/libs/iterator/doc/issues.rst @@ -0,0 +1,152 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Problem with ``is_writable`` and ``is_swappable`` in N1550_ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. _N1550: http://www.boost-consulting.com/writing/n1550.html +.. _N1530: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1530.html + +:Author: David Abrahams and Jeremy Siek +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu +:Organization: `Boost Consulting`_, Indiana University Bloomington +:date: $Date$ +:Copyright: Copyright David Abrahams, Jeremy Siek 2003. Use, modification and + distribution is subject to 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) + +.. _`Boost Consulting`: http://www.boost-consulting.com + +.. contents:: Table of Contents + +============== + Introduction +============== + +The ``is_writable`` and ``is_swappable`` traits classes in N1550_ +provide a mechanism for determining at compile time if an iterator +type is a model of the new Writable Iterator and Swappable Iterator +concepts, analogous to ``iterator_traits::iterator_category`` +for the old iterator concepts. For backward compatibility, +``is_writable`` and ``is_swappable`` not only work with new +iterators, but they also are intended to work for old +iterators (iterators that meet the requirements for one of the +iterator concepts in the current standard). In the case of old +iterators, the writability and swapability is deduced based on the +``iterator_category`` and also the ``reference`` type. The +specification for this deduction gives false positives for forward +iterators that have non-assignable value types. + +To review, the part of the ``is_writable`` trait definition which +applies to old iterators is:: + + if (cat is convertible to output_iterator_tag) + return true; + else if (cat is convertible to forward_iterator_tag + and iterator_traits::reference is a + mutable reference) + return true; + else + return false; + +Suppose the ``value_type`` of the iterator ``It`` has a private +assignment operator:: + + class B { + public: + ... + private: + B& operator=(const B&); + }; + +and suppose the ``reference`` type of the iterator is ``B&``. In +that case, ``is_writable::value`` will be true when in fact +attempting to write into ``B`` will cause an error. + +The same problem applies to ``is_swappable``. + + +==================== + Proposed Resolution +==================== + +1. Remove the ``is_writable`` and ``is_swappable`` traits, and remove the + requirements in the Writable Iterator and Swappable Iterator concepts + that require their models to support these traits. + +2. Change the ``is_readable`` specification to be: + ``is_readable::type`` is ``true_type`` if the + result type of ``X::operator*`` is convertible to + ``iterator_traits::value_type`` and is ``false_type`` + otherwise. Also, ``is_readable`` is required to satisfy + the requirements for the UnaryTypeTrait concept + (defined in the type traits proposal). + + Remove the requirement for support of the ``is_readable`` trait from + the Readable Iterator concept. + + +3. Remove the ``iterator_tag`` class. + +4. Change the specification of ``traversal_category`` to:: + + traversal-category(Iterator) = + let cat = iterator_traits::iterator_category + if (cat is convertible to incrementable_iterator_tag) + return cat; // Iterator is a new iterator + else if (cat is convertible to random_access_iterator_tag) + return random_access_traversal_tag; + else if (cat is convertible to bidirectional_iterator_tag) + return bidirectional_traversal_tag; + else if (cat is convertible to forward_iterator_tag) + return forward_traversal_tag; + else if (cat is convertible to input_iterator_tag) + return single_pass_iterator_tag; + else if (cat is convertible to output_iterator_tag) + return incrementable_iterator_tag; + else + return null_category_tag; + + +========== + Rationale +========== + +1. There are two reasons for removing ``is_writable`` + and ``is_swappable``. The first is that we do not know of + a way to fix the specification so that it gives the correct + answer for all iterators. Second, there was only a weak + motivation for having ``is_writable`` and ``is_swappable`` + there in the first place. The main motivation was simply + uniformity: we have tags for the old iterator categories + so we should have tags for the new iterator categories. + While having tags and the capability to dispatch based + on the traversal categories is often used, we see + less of a need for dispatching based on writability + and swappability, since typically algorithms + that need these capabilities have no alternative if + they are not provided. + +2. We discovered that the ``is_readable`` trait can be implemented + using only the iterator type itself and its ``value_type``. + Therefore we remove the requirement for ``is_readable`` from the + Readable Iterator concept, and change the definition of + ``is_readable`` so that it works for any iterator type. + +3. The purpose of the ``iterator_tag`` class was to + bundle the traversal and access category tags + into the ``iterator_category`` typedef. + With ``is_writable`` and ``is_swappable`` gone, and + ``is_readable`` no longer in need of special hints, + there is no reason for iterators to provide + information about the access capabilities of an iterator. + Thus there is no need for the ``iterator_tag``. The + traversal tag can be directly used for the + ``iterator_category``. If a new iterator is intended to be backward + compatible with old iterator concepts, a tag type + that is convertible to both one of the new traversal tags + and also to an old iterator tag can be created and use + for the ``iterator_category``. + +4. The changes to the specification of ``traversal_category`` are a + direct result of the removal of ``iterator_tag``. + diff --git a/libs/iterator/doc/iterator_adaptor.html b/libs/iterator/doc/iterator_adaptor.html new file mode 100644 index 00000000..e023d82a --- /dev/null +++ b/libs/iterator/doc/iterator_adaptor.html @@ -0,0 +1,461 @@ + + + + + + +Iterator Adaptor + + + + + + + +

+

Iterator Adaptor

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2006-09-11
Copyright:Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
+ + + + +++ + + + +
abstract:
+ + + + + +

Each specialization of the iterator_adaptor class template is derived from +a specialization of iterator_facade. The core interface functions +expected by iterator_facade are implemented in terms of the +iterator_adaptor's Base template parameter. A class derived +from iterator_adaptor typically redefines some of the core +interface functions to adapt the behavior of the Base type. +Whether the derived class models any of the standard iterator concepts +depends on the operations supported by the Base type and which +core interface functions of iterator_facade are redefined in the +Derived class.

+ +
+

Overview

+ + + + + +

The iterator_adaptor class template adapts some Base1 +type to create a new iterator. Instantiations of iterator_adaptor +are derived from a corresponding instantiation of iterator_facade +and implement the core behaviors in terms of the Base type. In +essence, iterator_adaptor merely forwards all operations to an +instance of the Base type, which it stores as a member.

+ + + + + +
[1](1, 2) The term "Base" here does not refer to a base class and is +not meant to imply the use of derivation. We have followed the lead +of the standard library, which provides a base() function to access +the underlying iterator object of a reverse_iterator adaptor.
+

The user of iterator_adaptor creates a class derived from an +instantiation of iterator_adaptor and then selectively +redefines some of the core member functions described in the +iterator_facade core requirements table. The Base type need +not meet the full requirements for an iterator; it need only +support the operations used by the core interface functions of +iterator_adaptor that have not been redefined in the user's +derived class.

+

Several of the template parameters of iterator_adaptor default +to use_default. This allows the +user to make use of a default parameter even when she wants to +specify a parameter later in the parameter list. Also, the +defaults for the corresponding associated types are somewhat +complicated, so metaprogramming is required to compute them, and +use_default can help to simplify the implementation. Finally, +the identity of the use_default type is not left unspecified +because specification helps to highlight that the Reference +template parameter may not always be identical to the iterator's +reference type, and will keep users from making mistakes based on +that assumption.

+
+
+

Reference

+ + + + + +
+template <
+    class Derived
+  , class Base
+  , class Value               = use_default
+  , class CategoryOrTraversal = use_default
+  , class Reference           = use_default
+  , class Difference = use_default
+>
+class iterator_adaptor
+  : public iterator_facade<Derived, V', C', R', D'> // see details
+{
+    friend class iterator_core_access;
+ public:
+    iterator_adaptor();
+    explicit iterator_adaptor(Base const& iter);
+    typedef Base base_type;
+    Base const& base() const;
+ protected:
+    typedef iterator_adaptor iterator_adaptor_;
+    Base const& base_reference() const;
+    Base& base_reference();
+ private: // Core iterator interface for iterator_facade.
+    typename iterator_adaptor::reference dereference() const;
+
+    template <
+    class OtherDerived, class OtherIterator, class V, class C, class R, class D
+    >
+    bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
+
+    void advance(typename iterator_adaptor::difference_type n);
+    void increment();
+    void decrement();
+
+    template <
+        class OtherDerived, class OtherIterator, class V, class C, class R, class D
+    >
+    typename iterator_adaptor::difference_type distance_to(
+        iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
+
+ private:
+    Base m_iterator; // exposition only
+};
+
+
+

iterator_adaptor requirements

+

static_cast<Derived*>(iterator_adaptor*) shall be well-formed. +The Base argument shall be Assignable and Copy Constructible.

+
+
+

iterator_adaptor base class parameters

+

The V', C', R', and D' parameters of the iterator_facade +used as a base class in the summary of iterator_adaptor +above are defined as follows:

+
+V' = if (Value is use_default)
+          return iterator_traits<Base>::value_type
+      else
+          return Value
+
+C' = if (CategoryOrTraversal is use_default)
+          return iterator_traversal<Base>::type
+      else
+          return CategoryOrTraversal
+
+R' = if (Reference is use_default)
+          if (Value is use_default)
+              return iterator_traits<Base>::reference
+          else
+              return Value&
+      else
+          return Reference
+
+D' = if (Difference is use_default)
+          return iterator_traits<Base>::difference_type
+      else
+          return Difference
+
+ + + +
+
+

iterator_adaptor public operations

+

iterator_adaptor();

+ +++ + + + + + +
Requires:The Base type must be Default Constructible.
Returns:An instance of iterator_adaptor with +m_iterator default constructed.
+

explicit iterator_adaptor(Base const& iter);

+ +++ + + + +
Returns:An instance of iterator_adaptor with +m_iterator copy constructed from iter.
+

Base const& base() const;

+ +++ + + + +
Returns:m_iterator
+
+
+

iterator_adaptor protected member functions

+

Base const& base_reference() const;

+ +++ + + + +
Returns:A const reference to m_iterator.
+

Base& base_reference();

+ +++ + + + +
Returns:A non-const reference to m_iterator.
+
+
+

iterator_adaptor private member functions

+

typename iterator_adaptor::reference dereference() const;

+ +++ + + + +
Returns:*m_iterator
+
+template <
+class OtherDerived, class OtherIterator, class V, class C, class R, class D
+>
+bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
+
+ +++ + + + +
Returns:m_iterator == x.base()
+

void advance(typename iterator_adaptor::difference_type n);

+ +++ + + + +
Effects:m_iterator += n;
+

void increment();

+ +++ + + + +
Effects:++m_iterator;
+

void decrement();

+ +++ + + + +
Effects:--m_iterator;
+
+template <
+    class OtherDerived, class OtherIterator, class V, class C, class R, class D
+>
+typename iterator_adaptor::difference_type distance_to(
+    iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
+
+ +++ + + + +
Returns:y.base() - m_iterator
+
+
+
+

Tutorial Example

+ + + +

In this section we'll further refine the node_iter class +template we developed in the iterator_facade tutorial. If you haven't already +read that material, you should go back now and check it out because +we're going to pick up right where it left off.

+ +

You probably didn't think of it this way, but the node_base* +object that underlies node_iterator is itself an iterator, +just like all other pointers. If we examine that pointer closely +from an iterator perspective, we can see that it has much in common +with the node_iterator we're building. First, they share most +of the same associated types (value_type, reference, +pointer, and difference_type). Second, even some of the +core functionality is the same: operator* and operator== on +the node_iterator return the result of invoking the same +operations on the underlying pointer, via the node_iterator's +dereference and equal member functions). The only real behavioral difference +between node_base* and node_iterator can be observed when +they are incremented: node_iterator follows the +m_next pointer, while node_base* just applies an address offset.

+

It turns out that the pattern of building an iterator on another +iterator-like type (the Base1 type) while modifying +just a few aspects of the underlying type's behavior is an +extremely common one, and it's the pattern addressed by +iterator_adaptor. Using iterator_adaptor is very much like +using iterator_facade, but because iterator_adaptor tries to +mimic as much of the Base type's behavior as possible, we +neither have to supply a Value argument, nor implement any core +behaviors other than increment. The implementation of +node_iter is thus reduced to:

+
+template <class Value>
+class node_iter
+  : public boost::iterator_adaptor<
+        node_iter<Value>                // Derived
+      , Value*                          // Base
+      , boost::use_default              // Value
+      , boost::forward_traversal_tag    // CategoryOrTraversal
+    >
+{
+ private:
+    struct enabler {};  // a private type avoids misuse
+
+ public:
+    node_iter()
+      : node_iter::iterator_adaptor_(0) {}
+
+    explicit node_iter(Value* p)
+      : node_iter::iterator_adaptor_(p) {}
+
+    template <class OtherValue>
+    node_iter(
+        node_iter<OtherValue> const& other
+      , typename boost::enable_if<
+            boost::is_convertible<OtherValue*,Value*>
+          , enabler
+        >::type = enabler()
+    )
+      : node_iter::iterator_adaptor_(other.base()) {}
+
+ private:
+    friend class boost::iterator_core_access;
+    void increment() { this->base_reference() = this->base()->next(); }
+};
+
+

Note the use of node_iter::iterator_adaptor_ here: because +iterator_adaptor defines a nested iterator_adaptor_ type +that refers to itself, that gives us a convenient way to refer to +the complicated base class type of node_iter<Value>. [Note: +this technique is known not to work with Borland C++ 5.6.4 and +Metrowerks CodeWarrior versions prior to 9.0]

+

You can see an example program that exercises this version of the +node iterators here.

+

In the case of node_iter, it's not very compelling to pass +boost::use_default as iterator_adaptor's Value +argument; we could have just passed node_iter's Value +along to iterator_adaptor, and that'd even be shorter! Most +iterator class templates built with iterator_adaptor are +parameterized on another iterator type, rather than on its +value_type. For example, boost::reverse_iterator takes an +iterator type argument and reverses its direction of traversal, +since the original iterator and the reversed one have all the same +associated types, iterator_adaptor's delegation of default +types to its Base saves the implementor of +boost::reverse_iterator from writing:

+
+std::iterator_traits<Iterator>::some-associated-type
+
+

at least four times.

+

We urge you to review the documentation and implementations of +reverse_iterator and the other Boost specialized iterator +adaptors to get an idea of the sorts of things you can do with +iterator_adaptor. In particular, have a look at +transform_iterator, which is perhaps the most straightforward +adaptor, and also counting_iterator, which demonstrates that +iterator_adaptor's Base type needn't be an iterator.

+
+
+ + + diff --git a/libs/iterator/doc/iterator_adaptor.pdf b/libs/iterator/doc/iterator_adaptor.pdf new file mode 100644 index 0000000000000000000000000000000000000000..24582c19e011038f781e81e0f17c6742239aa602 GIT binary patch literal 100117 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 literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/iterator_adaptor.rst b/libs/iterator/doc/iterator_adaptor.rst new file mode 100644 index 00000000..4f8ca017 --- /dev/null +++ b/libs/iterator/doc/iterator_adaptor.rst @@ -0,0 +1,41 @@ +.. 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) + ++++++++++++++++++ + Iterator Adaptor ++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: + +.. include:: iterator_adaptor_abstract.rst + +.. contents:: Table of Contents + +Overview +======== + +.. include:: iterator_adaptor_body.rst + + +Reference +========= + +.. include:: iterator_adaptor_ref.rst + +Tutorial Example +================ + +.. include:: iterator_adaptor_tutorial.rst diff --git a/libs/iterator/doc/iterator_adaptor_abstract.rst b/libs/iterator/doc/iterator_adaptor_abstract.rst new file mode 100644 index 00000000..fa887f21 --- /dev/null +++ b/libs/iterator/doc/iterator_adaptor_abstract.rst @@ -0,0 +1,19 @@ +.. 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) + +.. Version 1.1 of this ReStructuredText document corresponds to + n1530_, the paper accepted by the LWG. + +.. Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. + +Each specialization of the ``iterator_adaptor`` class template is derived from +a specialization of ``iterator_facade``. The core interface functions +expected by ``iterator_facade`` are implemented in terms of the +``iterator_adaptor``\ 's ``Base`` template parameter. A class derived +from ``iterator_adaptor`` typically redefines some of the core +interface functions to adapt the behavior of the ``Base`` type. +Whether the derived class models any of the standard iterator concepts +depends on the operations supported by the ``Base`` type and which +core interface functions of ``iterator_facade`` are redefined in the +``Derived`` class. diff --git a/libs/iterator/doc/iterator_adaptor_body.rst b/libs/iterator/doc/iterator_adaptor_body.rst new file mode 100644 index 00000000..ddd7f7b4 --- /dev/null +++ b/libs/iterator/doc/iterator_adaptor_body.rst @@ -0,0 +1,43 @@ +.. 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) + +.. Version 1.2 of this ReStructuredText document corresponds to + n1530_, the paper accepted by the LWG for TR1. + +.. Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. + +The ``iterator_adaptor`` class template adapts some ``Base`` [#base]_ +type to create a new iterator. Instantiations of ``iterator_adaptor`` +are derived from a corresponding instantiation of ``iterator_facade`` +and implement the core behaviors in terms of the ``Base`` type. In +essence, ``iterator_adaptor`` merely forwards all operations to an +instance of the ``Base`` type, which it stores as a member. + +.. [#base] The term "Base" here does not refer to a base class and is + not meant to imply the use of derivation. We have followed the lead + of the standard library, which provides a base() function to access + the underlying iterator object of a ``reverse_iterator`` adaptor. + +The user of ``iterator_adaptor`` creates a class derived from an +instantiation of ``iterator_adaptor`` and then selectively +redefines some of the core member functions described in the +``iterator_facade`` core requirements table. The ``Base`` type need +not meet the full requirements for an iterator; it need only +support the operations used by the core interface functions of +``iterator_adaptor`` that have not been redefined in the user's +derived class. + +Several of the template parameters of ``iterator_adaptor`` default +to ``use_default``. This allows the +user to make use of a default parameter even when she wants to +specify a parameter later in the parameter list. Also, the +defaults for the corresponding associated types are somewhat +complicated, so metaprogramming is required to compute them, and +``use_default`` can help to simplify the implementation. Finally, +the identity of the ``use_default`` type is not left unspecified +because specification helps to highlight that the ``Reference`` +template parameter may not always be identical to the iterator's +``reference`` type, and will keep users from making mistakes based on +that assumption. + diff --git a/libs/iterator/doc/iterator_adaptor_ref.rst b/libs/iterator/doc/iterator_adaptor_ref.rst new file mode 100644 index 00000000..50c00fcc --- /dev/null +++ b/libs/iterator/doc/iterator_adaptor_ref.rst @@ -0,0 +1,182 @@ +.. 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) + +.. Version 1.4 of this ReStructuredText document corresponds to + n1530_, the paper accepted by the LWG for TR1. + +.. Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. + +.. parsed-literal:: + + template < + class Derived + , class Base + , class Value = use_default + , class CategoryOrTraversal = use_default + , class Reference = use_default + , class Difference = use_default + > + class iterator_adaptor + : public iterator_facade // see details__ + { + friend class iterator_core_access; + public: + iterator_adaptor(); + explicit iterator_adaptor(Base const& iter); + typedef Base base_type; + Base const& base() const; + protected: + typedef iterator_adaptor iterator_adaptor\_; + Base const& base_reference() const; + Base& base_reference(); + private: // Core iterator interface for iterator_facade. + typename iterator_adaptor::reference dereference() const; + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor const& x) const; + + void advance(typename iterator_adaptor::difference_type n); + void increment(); + void decrement(); + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename iterator_adaptor::difference_type distance_to( + iterator_adaptor const& y) const; + + private: + Base m_iterator; // exposition only + }; + +__ base_parameters_ + +.. _requirements: + +``iterator_adaptor`` requirements +--------------------------------- + +``static_cast(iterator_adaptor*)`` shall be well-formed. +The ``Base`` argument shall be Assignable and Copy Constructible. + + +.. _base_parameters: + +``iterator_adaptor`` base class parameters +------------------------------------------ + +The *V'*, *C'*, *R'*, and *D'* parameters of the ``iterator_facade`` +used as a base class in the summary of ``iterator_adaptor`` +above are defined as follows: + +.. parsed-literal:: + + *V'* = if (Value is use_default) + return iterator_traits::value_type + else + return Value + + *C'* = if (CategoryOrTraversal is use_default) + return iterator_traversal::type + else + return CategoryOrTraversal + + *R'* = if (Reference is use_default) + if (Value is use_default) + return iterator_traits::reference + else + return Value& + else + return Reference + + *D'* = if (Difference is use_default) + return iterator_traits::difference_type + else + return Difference + +.. ``iterator_adaptor`` models + --------------------------- + + In order for ``Derived`` to model the iterator concepts corresponding + to ``iterator_traits::iterator_category``, the expressions + involving ``m_iterator`` in the specifications of those private member + functions of ``iterator_adaptor`` that may be called by + ``iterator_facade`` in evaluating any valid + expression involving ``Derived`` in those concepts' requirements. + +.. The above is confusing and needs a rewrite. -JGS +.. That's why it's removed. We're embracing inheritance, remember? + +``iterator_adaptor`` public operations +-------------------------------------- + +``iterator_adaptor();`` + +:Requires: The ``Base`` type must be Default Constructible. +:Returns: An instance of ``iterator_adaptor`` with + ``m_iterator`` default constructed. + + +``explicit iterator_adaptor(Base const& iter);`` + +:Returns: An instance of ``iterator_adaptor`` with + ``m_iterator`` copy constructed from ``iter``. + +``Base const& base() const;`` + +:Returns: ``m_iterator`` + +``iterator_adaptor`` protected member functions +----------------------------------------------- + +``Base const& base_reference() const;`` + +:Returns: A const reference to ``m_iterator``. + + +``Base& base_reference();`` + +:Returns: A non-const reference to ``m_iterator``. + + +``iterator_adaptor`` private member functions +--------------------------------------------- + +``typename iterator_adaptor::reference dereference() const;`` + +:Returns: ``*m_iterator`` + +:: + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor const& x) const; + +:Returns: ``m_iterator == x.base()`` + + +``void advance(typename iterator_adaptor::difference_type n);`` + +:Effects: ``m_iterator += n;`` + +``void increment();`` + +:Effects: ``++m_iterator;`` + +``void decrement();`` + +:Effects: ``--m_iterator;`` + +:: + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename iterator_adaptor::difference_type distance_to( + iterator_adaptor const& y) const; + +:Returns: ``y.base() - m_iterator`` diff --git a/libs/iterator/doc/iterator_adaptor_tutorial.rst b/libs/iterator/doc/iterator_adaptor_tutorial.rst new file mode 100644 index 00000000..41068468 --- /dev/null +++ b/libs/iterator/doc/iterator_adaptor_tutorial.rst @@ -0,0 +1,135 @@ +.. Copyright David Abrahams 2004. Use, modification and distribution is +.. subject to 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) + +In this section we'll further refine the ``node_iter`` class +template we developed in the |fac_tut|_. If you haven't already +read that material, you should go back now and check it out because +we're going to pick up right where it left off. + +.. |fac_tut| replace:: ``iterator_facade`` tutorial +.. _fac_tut: iterator_facade.html#tutorial-example + +.. sidebar:: ``node_base*`` really *is* an iterator + + It's not really a very interesting iterator, since ``node_base`` + is an abstract class: a pointer to a ``node_base`` just points + at some base subobject of an instance of some other class, and + incrementing a ``node_base*`` moves it past this base subobject + to who-knows-where? The most we can do with that incremented + position is to compare another ``node_base*`` to it. In other + words, the original iterator traverses a one-element array. + +You probably didn't think of it this way, but the ``node_base*`` +object that underlies ``node_iterator`` is itself an iterator, +just like all other pointers. If we examine that pointer closely +from an iterator perspective, we can see that it has much in common +with the ``node_iterator`` we're building. First, they share most +of the same associated types (``value_type``, ``reference``, +``pointer``, and ``difference_type``). Second, even some of the +core functionality is the same: ``operator*`` and ``operator==`` on +the ``node_iterator`` return the result of invoking the same +operations on the underlying pointer, via the ``node_iterator``\ 's +|dereference_and_equal|_). The only real behavioral difference +between ``node_base*`` and ``node_iterator`` can be observed when +they are incremented: ``node_iterator`` follows the +``m_next`` pointer, while ``node_base*`` just applies an address offset. + +.. |dereference_and_equal| replace:: ``dereference`` and ``equal`` member functions +.. _dereference_and_equal: iterator_facade.html#implementing-the-core-operations + +It turns out that the pattern of building an iterator on another +iterator-like type (the ``Base`` [#base]_ type) while modifying +just a few aspects of the underlying type's behavior is an +extremely common one, and it's the pattern addressed by +``iterator_adaptor``. Using ``iterator_adaptor`` is very much like +using ``iterator_facade``, but because iterator_adaptor tries to +mimic as much of the ``Base`` type's behavior as possible, we +neither have to supply a ``Value`` argument, nor implement any core +behaviors other than ``increment``. The implementation of +``node_iter`` is thus reduced to:: + + template + class node_iter + : public boost::iterator_adaptor< + node_iter // Derived + , Value* // Base + , boost::use_default // Value + , boost::forward_traversal_tag // CategoryOrTraversal + > + { + private: + struct enabler {}; // a private type avoids misuse + + public: + node_iter() + : node_iter::iterator_adaptor_(0) {} + + explicit node_iter(Value* p) + : node_iter::iterator_adaptor_(p) {} + + template + node_iter( + node_iter const& other + , typename boost::enable_if< + boost::is_convertible + , enabler + >::type = enabler() + ) + : node_iter::iterator_adaptor_(other.base()) {} + + private: + friend class boost::iterator_core_access; + void increment() { this->base_reference() = this->base()->next(); } + }; + +Note the use of ``node_iter::iterator_adaptor_`` here: because +``iterator_adaptor`` defines a nested ``iterator_adaptor_`` type +that refers to itself, that gives us a convenient way to refer to +the complicated base class type of ``node_iter``. [Note: +this technique is known not to work with Borland C++ 5.6.4 and +Metrowerks CodeWarrior versions prior to 9.0] + +You can see an example program that exercises this version of the +node iterators `here`__. + +__ ../example/node_iterator3.cpp + +In the case of ``node_iter``, it's not very compelling to pass +``boost::use_default`` as ``iterator_adaptor``\ 's ``Value`` +argument; we could have just passed ``node_iter``\ 's ``Value`` +along to ``iterator_adaptor``, and that'd even be shorter! Most +iterator class templates built with ``iterator_adaptor`` are +parameterized on another iterator type, rather than on its +``value_type``. For example, ``boost::reverse_iterator`` takes an +iterator type argument and reverses its direction of traversal, +since the original iterator and the reversed one have all the same +associated types, ``iterator_adaptor``\ 's delegation of default +types to its ``Base`` saves the implementor of +``boost::reverse_iterator`` from writing: + +.. parsed-literal:: + + std::iterator_traits::*some-associated-type* + +at least four times. + +We urge you to review the documentation and implementations of +|reverse_iterator|_ and the other Boost `specialized iterator +adaptors`__ to get an idea of the sorts of things you can do with +``iterator_adaptor``. In particular, have a look at +|transform_iterator|_, which is perhaps the most straightforward +adaptor, and also |counting_iterator|_, which demonstrates that +``iterator_adaptor``\ 's ``Base`` type needn't be an iterator. + +.. |reverse_iterator| replace:: ``reverse_iterator`` +.. _reverse_iterator: reverse_iterator.html + +.. |counting_iterator| replace:: ``counting_iterator`` +.. _counting_iterator: counting_iterator.html + +.. |transform_iterator| replace:: ``transform_iterator`` +.. _transform_iterator: transform_iterator.html + +__ index.html#specialized-adaptors + diff --git a/libs/iterator/doc/iterator_archetypes.html b/libs/iterator/doc/iterator_archetypes.html new file mode 100644 index 00000000..cba66fa6 --- /dev/null +++ b/libs/iterator/doc/iterator_archetypes.html @@ -0,0 +1,224 @@ + + + + + + +Iterator Archetype + + + + + + + + + + + diff --git a/libs/iterator/doc/iterator_archetypes.pdf b/libs/iterator/doc/iterator_archetypes.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8cecde3095478dd62d57cdd95534a8cf43fcfdc7 GIT binary patch literal 61213 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 + class iterator_archetype + { + typedef /* see below */ value_type; + typedef /* see below */ reference; + typedef /* see below */ pointer; + typedef /* see below */ difference_type; + typedef /* see below */ iterator_category; + }; + +``Access Category Tags`` +........................ + +The access category types provided correspond to the following +standard iterator access concept combinations: + +:: + + readable_iterator_t := + + Readable Iterator + + writable_iterator_t := + + Writeable Iterator + + readable_writable_iterator_t := + + Readable Iterator & Writeable Iterator & Swappable Iterator + + readable_lvalue_iterator_t := + + Readable Iterator & Lvalue Iterator + + writeable_lvalue_iterator_t := + + Readable Iterator & Writeable Iterator & Swappable Iterator & Lvalue Iterator + +``iterator_archetype`` Requirements +................................... + +The ``AccessCategory`` argument must be one of the predefined access +category tags. The ``TraversalCategory`` must be one of the standard +traversal tags. The ``Value`` type must satisfy the requirements of +the iterator concept specified by ``AccessCategory`` and +``TraversalCategory`` as implied by the nested traits types. + +``iterator_archetype`` Models +............................. + +``iterator_archetype`` models the iterator concepts specified by the +``AccessCategory`` and ``TraversalCategory`` +arguments. ``iterator_archetype`` does not model any other access +concepts or any more derived traversal concepts. + +``Traits`` +.......... + +The nested trait types are defined as follows: + +:: + + if (AccessCategory == readable_iterator_t) + + value_type = Value + reference = Value + pointer = Value* + + else if (AccessCategory == writable_iterator_t) + + value_type = void + reference = void + pointer = void + + else if (AccessCategory == readable_writable_iterator_t) + + value_type = Value + + reference := + + A type X that is convertible to Value for which the following + expression is valid. Given an object x of type X and v of type + Value. + + x = v + + pointer = Value* + + else if (AccessCategory == readable_lvalue_iterator_t) + + value_type = Value + reference = Value const& + pointer = Value const* + + else if (AccessCategory == writable_lvalue_iterator_t) + + value_type = Value + reference = Value& + pointer = Value* + + if ( TraversalCategory is convertible to forward_traversal_tag ) + + difference_type := ptrdiff_t + + else + + difference_type := unspecified type + + + iterator_category := + + A type X satisfying the following two constraints: + + 1. X is convertible to X1, and not to any more-derived + type, where X1 is defined by: + + if (reference is a reference type + && TraversalCategory is convertible to forward_traversal_tag) + { + if (TraversalCategory is convertible to random_access_traversal_tag) + X1 = random_access_iterator_tag + else if (TraversalCategory is convertible to bidirectional_traversal_tag) + X1 = bidirectional_iterator_tag + else + X1 = forward_iterator_tag + } + else + { + if (TraversalCategory is convertible to single_pass_traversal_tag + && reference != void) + X1 = input_iterator_tag + else + X1 = output_iterator_tag + } + + 2. X is convertible to TraversalCategory + + diff --git a/libs/iterator/doc/iterator_concepts.html b/libs/iterator/doc/iterator_concepts.html new file mode 100644 index 00000000..0a488388 --- /dev/null +++ b/libs/iterator/doc/iterator_concepts.html @@ -0,0 +1,127 @@ + + + + + + +Iterator Concepts + + + + + + + +
+

Iterator Concepts

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@styleadvisor.com
Organization:Boost Consulting, Indiana University Open Systems +Lab, Zephyr Associates, Inc.
Date:2006-09-11
Copyright:Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2004.
+ + + + +++ + + + +
abstract:The iterator concept checking classes provide a mechanism for +a template to report better error messages when a user instantiates +the template with a type that does not meet the requirements of +the template.
+

For an introduction to using concept checking classes, see +the documentation for the boost::concept_check library.

+
+

Reference

+ + +
+

iterator_concepts.hpp Synopsis

+
+namespace boost_concepts {
+
+    // Iterator Access Concepts
+
+    template <typename Iterator>
+    class ReadableIteratorConcept;
+
+    template <
+        typename Iterator
+      , typename ValueType = std::iterator_traits<Iterator>::value_type
+    >
+    class WritableIteratorConcept;
+
+    template <typename Iterator>
+    class SwappableIteratorConcept;
+
+    template <typename Iterator>
+    class LvalueIteratorConcept;
+
+    // Iterator Traversal Concepts
+
+    template <typename Iterator>
+    class IncrementableIteratorConcept;
+
+    template <typename Iterator>
+    class SinglePassIteratorConcept;
+
+    template <typename Iterator>
+    class ForwardTraversalConcept;
+
+    template <typename Iterator>
+    class BidirectionalTraversalConcept;
+
+    template <typename Iterator>
+    class RandomAccessTraversalConcept;
+
+    // Interoperability
+
+    template <typename Iterator, typename ConstIterator>
+    class InteroperableIteratorConcept;
+
+}
+
+
+
+
+ + + diff --git a/libs/iterator/doc/iterator_concepts.pdf b/libs/iterator/doc/iterator_concepts.pdf new file mode 100644 index 0000000000000000000000000000000000000000..98e43020541281aae5ddbedb3facecc2042f0c8e GIT binary patch literal 66710 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%0D-1U3J&tbp!g{5^O(|&gEB>+TwX< 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 literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/iterator_concepts.rst b/libs/iterator/doc/iterator_concepts.rst new file mode 100644 index 00000000..77242a4e --- /dev/null +++ b/libs/iterator/doc/iterator_concepts.rst @@ -0,0 +1,130 @@ +.. 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) + +++++++++++++++++++ + Iterator Concepts +++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@styleadvisor.com +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, `Zephyr Associates, Inc.`_ +:date: $Date$ +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2004. + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Zephyr Associates, Inc.`: http://www.styleadvisor.com + +:abstract: The iterator concept checking classes provide a mechanism for + a template to report better error messages when a user instantiates + the template with a type that does not meet the requirements of + the template. + + +For an introduction to using concept checking classes, see +the documentation for the |concepts|_ library. + +.. |concepts| replace:: ``boost::concept_check`` +.. _concepts: ../../concept_check/index.html + + +Reference +========= + +Iterator Access Concepts +........................ + +* |Readable|_ +* |Writable|_ +* |Swappable|_ +* |Lvalue|_ + +.. |Readable| replace:: *Readable Iterator* +.. _Readable: ReadableIterator.html + +.. |Writable| replace:: *Writable Iterator* +.. _Writable: WritableIterator.html + +.. |Swappable| replace:: *Swappable Iterator* +.. _Swappable: SwappableIterator.html + +.. |Lvalue| replace:: *Lvalue Iterator* +.. _Lvalue: LvalueIterator.html + + +Iterator Traversal Concepts +........................... + +* |Incrementable|_ +* |SinglePass|_ +* |Forward|_ +* |Bidir|_ +* |Random|_ + + +.. |Incrementable| replace:: *Incrementable Iterator* +.. _Incrementable: IncrementableIterator.html + +.. |SinglePass| replace:: *Single Pass Iterator* +.. _SinglePass: SinglePassIterator.html + +.. |Forward| replace:: *Forward Traversal* +.. _Forward: ForwardTraversal.html + +.. |Bidir| replace:: *Bidirectional Traversal* +.. _Bidir: BidirectionalTraversal.html + +.. |Random| replace:: *Random Access Traversal* +.. _Random: RandomAccessTraversal.html + + + +``iterator_concepts.hpp`` Synopsis +.................................. + +:: + + namespace boost_concepts { + + // Iterator Access Concepts + + template + class ReadableIteratorConcept; + + template < + typename Iterator + , typename ValueType = std::iterator_traits::value_type + > + class WritableIteratorConcept; + + template + class SwappableIteratorConcept; + + template + class LvalueIteratorConcept; + + // Iterator Traversal Concepts + + template + class IncrementableIteratorConcept; + + template + class SinglePassIteratorConcept; + + template + class ForwardTraversalConcept; + + template + class BidirectionalTraversalConcept; + + template + class RandomAccessTraversalConcept; + + // Interoperability + + template + class InteroperableIteratorConcept; + + } diff --git a/libs/iterator/doc/iterator_facade.html b/libs/iterator/doc/iterator_facade.html new file mode 100644 index 00000000..21e048d9 --- /dev/null +++ b/libs/iterator/doc/iterator_facade.html @@ -0,0 +1,1348 @@ + + + + + + +Iterator Facade + + + + + + + +
+

Iterator Facade

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2006-09-11
Copyright:Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
+ + + + +++ + + + +
abstract: + + +iterator_facade is a base class template that implements the +interface of standard iterators in terms of a few core functions +and associated types, to be supplied by a derived iterator class.
+
+
+

Overview

+ + + + + +

While the iterator interface is rich, there is a core subset of the +interface that is necessary for all the functionality. We have +identified the following core behaviors for iterators:

+
    +
  • dereferencing
  • +
  • incrementing
  • +
  • decrementing
  • +
  • equality comparison
  • +
  • random-access motion
  • +
  • distance measurement
  • +
+

In addition to the behaviors listed above, the core interface elements +include the associated types exposed through iterator traits: +value_type, reference, difference_type, and +iterator_category.

+

Iterator facade uses the Curiously Recurring Template +Pattern (CRTP) [Cop95] so that the user can specify the behavior +of iterator_facade in a derived class. Former designs used +policy objects to specify the behavior, but that approach was +discarded for several reasons:

+
+
    +
  1. the creation and eventual copying of the policy object may create +overhead that can be avoided with the current approach.
  2. +
  3. The policy object approach does not allow for custom constructors +on the created iterator types, an essential feature if +iterator_facade should be used in other library +implementations.
  4. +
  5. Without the use of CRTP, the standard requirement that an +iterator's operator++ returns the iterator type itself +would mean that all iterators built with the library would +have to be specializations of iterator_facade<...>, rather +than something more descriptive like +indirect_iterator<T*>. Cumbersome type generator +metafunctions would be needed to build new parameterized +iterators, and a separate iterator_adaptor layer would be +impossible.
  6. +
+
+
+

Usage

+

The user of iterator_facade derives his iterator class from a +specialization of iterator_facade and passes the derived +iterator class as iterator_facade's first template parameter. +The order of the other template parameters have been carefully +chosen to take advantage of useful defaults. For example, when +defining a constant lvalue iterator, the user can pass a +const-qualified version of the iterator's value_type as +iterator_facade's Value parameter and omit the +Reference parameter which follows.

+

The derived iterator class must define member functions implementing +the iterator's core behaviors. The following table describes +expressions which are required to be valid depending on the category +of the derived iterator type. These member functions are described +briefly below and in more detail in the iterator facade +requirements.

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionEffects
i.dereference()Access the value referred to
i.equal(j)Compare for equality with j
i.increment()Advance by one position
i.decrement()Retreat by one position
i.advance(n)Advance by n positions
i.distance_to(j)Measure the distance to j
+
+ +

In addition to implementing the core interface functions, an iterator +derived from iterator_facade typically defines several +constructors. To model any of the standard iterator concepts, the +iterator must at least have a copy constructor. Also, if the iterator +type X is meant to be automatically interoperate with another +iterator type Y (as with constant and mutable iterators) then +there must be an implicit conversion from X to Y or from Y +to X (but not both), typically implemented as a conversion +constructor. Finally, if the iterator is to model Forward Traversal +Iterator or a more-refined iterator concept, a default constructor is +required.

+
+
+

Iterator Core Access

+

iterator_facade and the operator implementations need to be able +to access the core member functions in the derived class. Making the +core member functions public would expose an implementation detail to +the user. The design used here ensures that implementation details do +not appear in the public interface of the derived iterator type.

+

Preventing direct access to the core member functions has two +advantages. First, there is no possibility for the user to accidently +use a member function of the iterator when a member of the value_type +was intended. This has been an issue with smart pointer +implementations in the past. The second and main advantage is that +library implementers can freely exchange a hand-rolled iterator +implementation for one based on iterator_facade without fear of +breaking code that was accessing the public core member functions +directly.

+

In a naive implementation, keeping the derived class' core member +functions private would require it to grant friendship to +iterator_facade and each of the seven operators. In order to +reduce the burden of limiting access, iterator_core_access is +provided, a class that acts as a gateway to the core member functions +in the derived iterator class. The author of the derived class only +needs to grant friendship to iterator_core_access to make his core +member functions available to the library.

+ + +

iterator_core_access will be typically implemented as an empty +class containing only private static member functions which invoke the +iterator core member functions. There is, however, no need to +standardize the gateway protocol. Note that even if +iterator_core_access used public member functions it would not +open a safety loophole, as every core member function preserves the +invariants of the iterator.

+
+
+

operator[]

+

The indexing operator for a generalized iterator presents special +challenges. A random access iterator's operator[] is only +required to return something convertible to its value_type. +Requiring that it return an lvalue would rule out currently-legal +random-access iterators which hold the referenced value in a data +member (e.g. counting_iterator), because *(p+n) is a reference +into the temporary iterator p+n, which is destroyed when +operator[] returns.

+

Writable iterators built with iterator_facade implement the +semantics required by the preferred resolution to issue 299 and +adopted by proposal n1550: the result of p[n] is an object +convertible to the iterator's value_type, and p[n] = x is +equivalent to *(p + n) = x (Note: This result object may be +implemented as a proxy containing a copy of p+n). This approach +will work properly for any random-access iterator regardless of the +other details of its implementation. A user who knows more about +the implementation of her iterator is free to implement an +operator[] that returns an lvalue in the derived iterator +class; it will hide the one supplied by iterator_facade from +clients of her iterator.

+
+
+

operator->

+

The reference type of a readable iterator (and today's input +iterator) need not in fact be a reference, so long as it is +convertible to the iterator's value_type. When the value_type +is a class, however, it must still be possible to access members +through operator->. Therefore, an iterator whose reference +type is not in fact a reference must return a proxy containing a copy +of the referenced value from its operator->.

+

The return types for iterator_facade's operator-> and +operator[] are not explicitly specified. Instead, those types +are described in terms of a set of requirements, which must be +satisfied by the iterator_facade implementation.

+ + + + + +
[Cop95](1, 2) [Coplien, 1995] Coplien, J., Curiously Recurring Template +Patterns, C++ Report, February 1995, pp. 24-27.
+
+
+
+

Reference

+ + + + + +
+template <
+    class Derived
+  , class Value
+  , class CategoryOrTraversal
+  , class Reference  = Value&
+  , class Difference = ptrdiff_t
+>
+class iterator_facade {
+ public:
+    typedef remove_const<Value>::type value_type;
+    typedef Reference reference;
+    typedef Value* pointer;
+    typedef Difference difference_type;
+    typedef /* see below */ iterator_category;
+
+    reference operator*() const;
+    /* see below */ operator->() const;
+    /* see below */ operator[](difference_type n) const;
+    Derived& operator++();
+    Derived operator++(int);
+    Derived& operator--();
+    Derived operator--(int);
+    Derived& operator+=(difference_type n);
+    Derived& operator-=(difference_type n);
+    Derived operator-(difference_type n) const;
+ protected:
+    typedef iterator_facade iterator_facade_;
+};
+
+// Comparison operators
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type // exposition
+operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+           iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+           iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+// Iterator difference
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+/* see below */
+operator-(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+          iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+// Iterator addition
+template <class Dr, class V, class TC, class R, class D>
+Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&,
+                   typename Derived::difference_type n);
+
+template <class Dr, class V, class TC, class R, class D>
+Derived operator+ (typename Derived::difference_type n,
+                   iterator_facade<Dr,V,TC,R,D> const&);
+
+

The iterator_category member of iterator_facade is

+
+iterator-category(CategoryOrTraversal, value_type, reference)
+
+

where iterator-category is defined as follows:

+
+iterator-category(C,R,V) :=
+   if (C is convertible to std::input_iterator_tag
+       || C is convertible to std::output_iterator_tag
+   )
+       return C
+
+   else if (C is not convertible to incrementable_traversal_tag)
+       the program is ill-formed
+
+   else return a type X satisfying the following two constraints:
+
+      1. X is convertible to X1, and not to any more-derived
+         type, where X1 is defined by:
+
+           if (R is a reference type
+               && C is convertible to forward_traversal_tag)
+           {
+               if (C is convertible to random_access_traversal_tag)
+                   X1 = random_access_iterator_tag
+               else if (C is convertible to bidirectional_traversal_tag)
+                   X1 = bidirectional_iterator_tag
+               else
+                   X1 = forward_iterator_tag
+           }
+           else
+           {
+               if (C is convertible to single_pass_traversal_tag
+                   && R is convertible to V)
+                   X1 = input_iterator_tag
+               else
+                   X1 = C
+           }
+
+      2. category-to-traversal(X) is convertible to the most
+         derived traversal tag type to which X is also
+         convertible, and not to any more-derived traversal tag
+         type.
+
+

[Note: the intention is to allow iterator_category to be one of +the five original category tags when convertibility to one of the +traversal tags would add no information]

+ + + +

The enable_if_interoperable template used above is for exposition +purposes. The member operators should only be in an overload set +provided the derived types Dr1 and Dr2 are interoperable, +meaning that at least one of the types is convertible to the other. The +enable_if_interoperable approach uses SFINAE to take the operators +out of the overload set when the types are not interoperable. +The operators should behave as-if enable_if_interoperable +were defined to be:

+
+template <bool, typename> enable_if_interoperable_impl
+{};
+
+template <typename T> enable_if_interoperable_impl<true,T>
+{ typedef T type; };
+
+template<typename Dr1, typename Dr2, typename T>
+struct enable_if_interoperable
+  : enable_if_interoperable_impl<
+        is_convertible<Dr1,Dr2>::value || is_convertible<Dr2,Dr1>::value
+      , T
+    >
+{};
+
+
+

iterator_facade Requirements

+

The following table describes the typical valid expressions on +iterator_facade's Derived parameter, depending on the +iterator concept(s) it will model. The operations in the first +column must be made accessible to member functions of class +iterator_core_access. In addition, +static_cast<Derived*>(iterator_facade*) shall be well-formed.

+

In the table below, F is iterator_facade<X,V,C,R,D>, a is an +object of type X, b and c are objects of type const X, +n is an object of F::difference_type, y is a constant +object of a single pass iterator type interoperable with X, and z +is a constant object of a random access traversal iterator type +interoperable with X.

+
+

iterator_facade Core Operations

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionReturn TypeAssertion/NoteUsed to implement Iterator +Concept(s)
c.dereference()F::reference Readable Iterator, Writable +Iterator
c.equal(y)convertible to booltrue iff c and y +refer to the same +position.Single Pass Iterator
a.increment()unused Incrementable Iterator
a.decrement()unused Bidirectional Traversal +Iterator
a.advance(n)unused Random Access Traversal +Iterator
c.distance_to(z)convertible to +F::difference_typeequivalent to +distance(c, X(z)).Random Access Traversal +Iterator
+
+
+
+

iterator_facade operations

+

The operations in this section are described in terms of operations on +the core interface of Derived which may be inaccessible +(i.e. private). The implementation should access these operations +through member functions of class iterator_core_access.

+

reference operator*() const;

+ +++ + + + +
Returns:static_cast<Derived const*>(this)->dereference()
+

operator->() const; (see below)

+ +++ + + + +
Returns:

If reference is a reference type, an object +of type pointer equal to:

+
+&static_cast<Derived const*>(this)->dereference()
+
+

Otherwise returns an object of unspecified type such that, +(*static_cast<Derived const*>(this))->m is equivalent to (w = **static_cast<Derived const*>(this), +w.m) for some temporary object w of type value_type.

+
+

unspecified operator[](difference_type n) const;

+ +++ + + + +
Returns:an object convertible to value_type. For constant +objects v of type value_type, and n of type +difference_type, (*this)[n] = v is equivalent to +*(*this + n) = v, and static_cast<value_type +const&>((*this)[n]) is equivalent to +static_cast<value_type const&>(*(*this + n))
+

Derived& operator++();

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->increment();
+return *static_cast<Derived*>(this);
+
+
+

Derived operator++(int);

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+++*this;
+return tmp;
+
+
+

Derived& operator--();

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->decrement();
+return *static_cast<Derived*>(this);
+
+
+

Derived operator--(int);

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+--*this;
+return tmp;
+
+
+

Derived& operator+=(difference_type n);

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->advance(n);
+return *static_cast<Derived*>(this);
+
+
+

Derived& operator-=(difference_type n);

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->advance(-n);
+return *static_cast<Derived*>(this);
+
+
+

Derived operator-(difference_type n) const;

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+return tmp -= n;
+
+
+
+template <class Dr, class V, class TC, class R, class D>
+Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&,
+                   typename Derived::difference_type n);
+
+template <class Dr, class V, class TC, class R, class D>
+Derived operator+ (typename Derived::difference_type n,
+                   iterator_facade<Dr,V,TC,R,D> const&);
+
+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+return tmp += n;
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + +
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

((Dr1 const&)lhs).equal((Dr2 const&)rhs).

+
+
Otherwise,
+

((Dr2 const&)rhs).equal((Dr1 const&)lhs).

+
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + +
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

!((Dr1 const&)lhs).equal((Dr2 const&)rhs).

+
+
Otherwise,
+

!((Dr2 const&)rhs).equal((Dr1 const&)lhs).

+
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+           iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + +
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) < 0.

+
+
Otherwise,
+

((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) > 0.

+
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + +
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) <= 0.

+
+
Otherwise,
+

((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) >= 0.

+
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+           iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + +
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) > 0.

+
+
Otherwise,
+

((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) < 0.

+
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + +
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) >= 0.

+
+
Otherwise,
+

((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) <= 0.

+
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,difference>::type
+operator -(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+           iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + + + +
Return Type:

if is_convertible<Dr2,Dr1>::value

+
+
+
then
+

difference shall be +iterator_traits<Dr1>::difference_type.

+
+
Otherwise
+

difference shall be iterator_traits<Dr2>::difference_type

+
+
+
+
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

-((Dr1 const&)lhs).distance_to((Dr2 const&)rhs).

+
+
Otherwise,
+

((Dr2 const&)rhs).distance_to((Dr1 const&)lhs).

+
+
+
+
+
+
+

Tutorial Example

+ + + +

In this section we'll walk through the implementation of a few +iterators using iterator_facade, based around the simple +example of a linked list of polymorphic objects. This example was +inspired by a posting by Keith Macdonald on the Boost-Users +mailing list.

+
+

The Problem

+

Say we've written a polymorphic linked list node base class:

+
+# include <iostream>
+
+struct node_base
+{
+    node_base() : m_next(0) {}
+
+    // Each node manages all of its tail nodes
+    virtual ~node_base() { delete m_next; }
+
+    // Access the rest of the list
+    node_base* next() const { return m_next; }
+
+    // print to the stream
+    virtual void print(std::ostream& s) const = 0;
+
+    // double the value
+    virtual void double_me() = 0;
+
+    void append(node_base* p)
+    {
+        if (m_next)
+            m_next->append(p);
+        else
+            m_next = p;
+    }
+
+ private:
+    node_base* m_next;
+};
+
+

Lists can hold objects of different types by linking together +specializations of the following template:

+
+template <class T>
+struct node : node_base
+{
+    node(T x)
+      : m_value(x)
+    {}
+
+    void print(std::ostream& s) const { s << this->m_value; }
+    void double_me() { m_value += m_value; }
+
+ private:
+    T m_value;
+};
+
+

And we can print any node using the following streaming operator:

+
+inline std::ostream& operator<<(std::ostream& s, node_base const& n)
+{
+    n.print(s);
+    return s;
+}
+
+

Our first challenge is to build an appropriate iterator over these +lists.

+
+
+

A Basic Iterator Using iterator_facade

+

We will construct a node_iterator class using inheritance from +iterator_facade to implement most of the iterator's operations.

+
+# include "node.hpp"
+# include <boost/iterator/iterator_facade.hpp>
+
+class node_iterator
+  : public boost::iterator_facade<...>
+{
+   ...
+};
+
+
+

Template Arguments for iterator_facade

+

iterator_facade has several template parameters, so we must decide +what types to use for the arguments. The parameters are Derived, +Value, CategoryOrTraversal, Reference, and Difference.

+
+

Derived

+

Because iterator_facade is meant to be used with the CRTP +[Cop95] the first parameter is the iterator class name itself, +node_iterator.

+
+
+

Value

+

The Value parameter determines the node_iterator's +value_type. In this case, we are iterating over node_base +objects, so Value will be node_base.

+
+
+

CategoryOrTraversal

+

Now we have to determine which iterator traversal concept our +node_iterator is going to model. Singly-linked lists only have +forward links, so our iterator can't can't be a bidirectional +traversal iterator. Our iterator should be able to make multiple +passes over the same linked list (unlike, say, an +istream_iterator which consumes the stream it traverses), so it +must be a forward traversal iterator. Therefore, we'll pass +boost::forward_traversal_tag in this position1.

+ + + + + +
[1]iterator_facade also supports old-style category +tags, so we could have passed std::forward_iterator_tag here; +either way, the resulting iterator's iterator_category will +end up being std::forward_iterator_tag.
+
+
+

Reference

+

The Reference argument becomes the type returned by +node_iterator's dereference operation, and will also be the +same as std::iterator_traits<node_iterator>::reference. The +library's default for this parameter is Value&; since +node_base& is a good choice for the iterator's reference +type, we can omit this argument, or pass use_default.

+
+
+

Difference

+

The Difference argument determines how the distance between +two node_iterators will be measured and will also be the +same as std::iterator_traits<node_iterator>::difference_type. +The library's default for Difference is std::ptrdiff_t, an +appropriate type for measuring the distance between any two +addresses in memory, and one that works for almost any iterator, +so we can omit this argument, too.

+

The declaration of node_iterator will therefore look something +like:

+
+# include "node.hpp"
+# include <boost/iterator/iterator_facade.hpp>
+
+class node_iterator
+  : public boost::iterator_facade<
+        node_iterator
+      , node_base
+      , boost::forward_traversal_tag
+    >
+{
+   ...
+};
+
+
+
+
+

Constructors and Data Members

+

Next we need to decide how to represent the iterator's position. +This representation will take the form of data members, so we'll +also need to write constructors to initialize them. The +node_iterator's position is quite naturally represented using +a pointer to a node_base. We'll need a constructor to build an +iterator from a node_base*, and a default constructor to +satisfy the forward traversal iterator requirements2. +Our node_iterator then becomes:

+
+# include "node.hpp"
+# include <boost/iterator/iterator_facade.hpp>
+
+class node_iterator
+  : public boost::iterator_facade<
+        node_iterator
+      , node_base
+      , boost::forward_traversal_tag
+    >
+{
+ public:
+    node_iterator()
+      : m_node(0)
+    {}
+
+    explicit node_iterator(node_base* p)
+      : m_node(p)
+    {}
+
+ private:
+    ...
+    node_base* m_node;
+};
+
+ + + + + +
[2]Technically, the C++ standard places almost no +requirements on a default-constructed iterator, so if we were +really concerned with efficiency, we could've written the +default constructor to leave m_node uninitialized.
+
+
+

Implementing the Core Operations

+

The last step is to implement the core operations required by +the concepts we want our iterator to model. Referring to the +table, we can see that the first three rows are applicable +because node_iterator needs to satisfy the requirements for +readable iterator, single pass iterator, and incrementable +iterator.

+

We therefore need to supply dereference, +equal, and increment members. We don't want these members +to become part of node_iterator's public interface, so we can +make them private and grant friendship to +boost::iterator_core_access, a "back-door" that +iterator_facade uses to get access to the core operations:

+
+# include "node.hpp"
+# include <boost/iterator/iterator_facade.hpp>
+
+class node_iterator
+  : public boost::iterator_facade<
+        node_iterator
+      , node_base
+      , boost::forward_traversal_tag
+    >
+{
+ public:
+    node_iterator()
+      : m_node(0) {}
+
+    explicit node_iterator(node_base* p)
+      : m_node(p) {}
+
+ private:
+    friend class boost::iterator_core_access;
+
+    void increment() { m_node = m_node->next(); }
+
+    bool equal(node_iterator const& other) const
+    {
+        return this->m_node == other.m_node;
+    }
+
+    node_base& dereference() const { return *m_node; }
+
+    node_base* m_node;
+};
+
+

Voilà; a complete and conforming readable, forward-traversal +iterator! For a working example of its use, see this program.

+
+
+
+

A constant node_iterator

+ +

Now, our node_iterator gives clients access to both node's print(std::ostream&) const member function, but also its +mutating double_me() member. If we wanted to build a +constant node_iterator, we'd only have to make three +changes:

+
+class const_node_iterator
+  : public boost::iterator_facade<
+        const_node_iterator
+      , node_base const
+      , boost::forward_traversal_tag
+    >
+{
+ public:
+    const_node_iterator()
+      : m_node(0) {}
+
+    explicit const_node_iterator(node_base* p)
+      : m_node(p) {}
+
+ private:
+    friend class boost::iterator_core_access;
+
+    void increment() { m_node = m_node->next(); }
+
+    bool equal(const_node_iterator const& other) const
+    {
+        return this->m_node == other.m_node;
+    }
+
+    node_base const& dereference() const { return *m_node; }
+
+    node_base const* m_node;
+};
+
+ +

As a matter of fact, node_iterator and const_node_iterator +are so similar that it makes sense to factor the common code out +into a template as follows:

+
+template <class Value>
+class node_iter
+  : public boost::iterator_facade<
+        node_iter<Value>
+      , Value
+      , boost::forward_traversal_tag
+    >
+{
+ public:
+    node_iter()
+      : m_node(0) {}
+
+    explicit node_iter(Value* p)
+      : m_node(p) {}
+
+ private:
+    friend class boost::iterator_core_access;
+
+    bool equal(node_iter<Value> const& other) const
+    {
+        return this->m_node == other.m_node;
+    }
+
+    void increment()
+    { m_node = m_node->next(); }
+
+    Value& dereference() const
+    { return *m_node; }
+
+    Value* m_node;
+};
+typedef node_iter<node_base> node_iterator;
+typedef node_iter<node_base const> node_const_iterator;
+
+
+
+

Interoperability

+

Our const_node_iterator works perfectly well on its own, but +taken together with node_iterator it doesn't quite meet +expectations. For example, we'd like to be able to pass a +node_iterator where a node_const_iterator was expected, +just as you can with std::list<int>'s iterator and +const_iterator. Furthermore, given a node_iterator and a +node_const_iterator into the same list, we should be able to +compare them for equality.

+

This expected ability to use two different iterator types together +is known as interoperability. Achieving interoperability in +our case is as simple as templatizing the equal function and +adding a templatized converting constructor34:

+
+template <class Value>
+class node_iter
+  : public boost::iterator_facade<
+        node_iter<Value>
+      , Value
+      , boost::forward_traversal_tag
+    >
+{
+ public:
+    node_iter()
+      : m_node(0) {}
+
+    explicit node_iter(Value* p)
+      : m_node(p) {}
+
+    template <class OtherValue>
+    node_iter(node_iter<OtherValue> const& other)
+      : m_node(other.m_node) {}
+
+ private:
+    friend class boost::iterator_core_access;
+    template <class> friend class node_iter;
+
+    template <class OtherValue>
+    bool equal(node_iter<OtherValue> const& other) const
+    {
+        return this->m_node == other.m_node;
+    }
+
+    void increment()
+    { m_node = m_node->next(); }
+
+    Value& dereference() const
+    { return *m_node; }
+
+    Value* m_node;
+};
+typedef impl::node_iterator<node_base> node_iterator;
+typedef impl::node_iterator<node_base const> node_const_iterator;
+
+ + + + + +
[3]If you're using an older compiler and it can't handle +this example, see the example code for workarounds.
+ + + + + +
[4]If node_iterator had been a random access +traversal iterator, we'd have had to templatize its +distance_to function as well.
+

You can see an example program which exercises our interoperable +iterators here.

+
+
+

Telling the Truth

+

Now node_iterator and node_const_iterator behave exactly as +you'd expect... almost. We can compare them and we can convert in +one direction: from node_iterator to node_const_iterator. +If we try to convert from node_const_iterator to +node_iterator, we'll get an error when the converting +constructor tries to initialize node_iterator's m_node, a +node* with a node const*. So what's the problem?

+

The problem is that +boost::is_convertible<node_const_iterator,node_iterator>::value +will be true, but it should be false. is_convertible +lies because it can only see as far as the declaration of +node_iter's converting constructor, but can't look inside at +the definition to make sure it will compile. A perfect solution +would make node_iter's converting constructor disappear when +the m_node conversion would fail.

+

In fact, that sort of magic is possible using +boost::enable_if. By rewriting the converting constructor as +follows, we can remove it from the overload set when it's not +appropriate:

+
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/utility/enable_if.hpp>
+
+  ...
+
+private:
+  struct enabler {};
+
+public:
+  template <class OtherValue>
+  node_iter(
+      node_iter<OtherValue> const& other
+    , typename boost::enable_if<
+          boost::is_convertible<OtherValue*,Value*>
+        , enabler
+      >::type = enabler()
+  )
+    : m_node(other.m_node) {}
+
+
+
+

Wrap Up

+

This concludes our iterator_facade tutorial, but before you +stop reading we urge you to take a look at iterator_adaptor. +There's another way to approach writing these iterators which might +even be superior.

+
+
+
+ + + diff --git a/libs/iterator/doc/iterator_facade.pdf b/libs/iterator/doc/iterator_facade.pdf new file mode 100644 index 0000000000000000000000000000000000000000..30d46d2633f11ec123ef3fa2cfc74e263596ff85 GIT binary patch literal 167634 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

-Z-mm`nHnpu>fO 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, rather + than something more descriptive like + ``indirect_iterator``. Cumbersome type generator + metafunctions would be needed to build new parameterized + iterators, and a separate ``iterator_adaptor`` layer would be + impossible. + +Usage +----- + +The user of ``iterator_facade`` derives his iterator class from a +specialization of ``iterator_facade`` and passes the derived +iterator class as ``iterator_facade``\ 's first template parameter. +The order of the other template parameters have been carefully +chosen to take advantage of useful defaults. For example, when +defining a constant lvalue iterator, the user can pass a +const-qualified version of the iterator's ``value_type`` as +``iterator_facade``\ 's ``Value`` parameter and omit the +``Reference`` parameter which follows. + +The derived iterator class must define member functions implementing +the iterator's core behaviors. The following table describes +expressions which are required to be valid depending on the category +of the derived iterator type. These member functions are described +briefly below and in more detail in the iterator facade +requirements. + + +------------------------+-------------------------------+ + |Expression |Effects | + +========================+===============================+ + |``i.dereference()`` |Access the value referred to | + +------------------------+-------------------------------+ + |``i.equal(j)`` |Compare for equality with ``j``| + +------------------------+-------------------------------+ + |``i.increment()`` |Advance by one position | + +------------------------+-------------------------------+ + |``i.decrement()`` |Retreat by one position | + +------------------------+-------------------------------+ + |``i.advance(n)`` |Advance by ``n`` positions | + +------------------------+-------------------------------+ + |``i.distance_to(j)`` |Measure the distance to ``j`` | + +------------------------+-------------------------------+ + +.. Should we add a comment that a zero overhead implementation of iterator_facade + is possible with proper inlining? + +In addition to implementing the core interface functions, an iterator +derived from ``iterator_facade`` typically defines several +constructors. To model any of the standard iterator concepts, the +iterator must at least have a copy constructor. Also, if the iterator +type ``X`` is meant to be automatically interoperate with another +iterator type ``Y`` (as with constant and mutable iterators) then +there must be an implicit conversion from ``X`` to ``Y`` or from ``Y`` +to ``X`` (but not both), typically implemented as a conversion +constructor. Finally, if the iterator is to model Forward Traversal +Iterator or a more-refined iterator concept, a default constructor is +required. + + + +Iterator Core Access +-------------------- + +``iterator_facade`` and the operator implementations need to be able +to access the core member functions in the derived class. Making the +core member functions public would expose an implementation detail to +the user. The design used here ensures that implementation details do +not appear in the public interface of the derived iterator type. + +Preventing direct access to the core member functions has two +advantages. First, there is no possibility for the user to accidently +use a member function of the iterator when a member of the value_type +was intended. This has been an issue with smart pointer +implementations in the past. The second and main advantage is that +library implementers can freely exchange a hand-rolled iterator +implementation for one based on ``iterator_facade`` without fear of +breaking code that was accessing the public core member functions +directly. + +In a naive implementation, keeping the derived class' core member +functions private would require it to grant friendship to +``iterator_facade`` and each of the seven operators. In order to +reduce the burden of limiting access, ``iterator_core_access`` is +provided, a class that acts as a gateway to the core member functions +in the derived iterator class. The author of the derived class only +needs to grant friendship to ``iterator_core_access`` to make his core +member functions available to the library. + +.. This is no long uptodate -thw +.. Yes it is; I made sure of it! -DWA + +``iterator_core_access`` will be typically implemented as an empty +class containing only private static member functions which invoke the +iterator core member functions. There is, however, no need to +standardize the gateway protocol. Note that even if +``iterator_core_access`` used public member functions it would not +open a safety loophole, as every core member function preserves the +invariants of the iterator. + +``operator[]`` +-------------- + +The indexing operator for a generalized iterator presents special +challenges. A random access iterator's ``operator[]`` is only +required to return something convertible to its ``value_type``. +Requiring that it return an lvalue would rule out currently-legal +random-access iterators which hold the referenced value in a data +member (e.g. |counting|_), because ``*(p+n)`` is a reference +into the temporary iterator ``p+n``, which is destroyed when +``operator[]`` returns. + +.. |counting| replace:: ``counting_iterator`` + +Writable iterators built with ``iterator_facade`` implement the +semantics required by the preferred resolution to `issue 299`_ and +adopted by proposal n1550_: the result of ``p[n]`` is an object +convertible to the iterator's ``value_type``, and ``p[n] = x`` is +equivalent to ``*(p + n) = x`` (Note: This result object may be +implemented as a proxy containing a copy of ``p+n``). This approach +will work properly for any random-access iterator regardless of the +other details of its implementation. A user who knows more about +the implementation of her iterator is free to implement an +``operator[]`` that returns an lvalue in the derived iterator +class; it will hide the one supplied by ``iterator_facade`` from +clients of her iterator. + +.. _n1550: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1550.htm + +.. _`issue 299`: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#299 + +.. _`operator arrow`: + + +``operator->`` +-------------- + +The ``reference`` type of a readable iterator (and today's input +iterator) need not in fact be a reference, so long as it is +convertible to the iterator's ``value_type``. When the ``value_type`` +is a class, however, it must still be possible to access members +through ``operator->``. Therefore, an iterator whose ``reference`` +type is not in fact a reference must return a proxy containing a copy +of the referenced value from its ``operator->``. + +The return types for ``iterator_facade``\ 's ``operator->`` and +``operator[]`` are not explicitly specified. Instead, those types +are described in terms of a set of requirements, which must be +satisfied by the ``iterator_facade`` implementation. + +.. [Cop95] [Coplien, 1995] Coplien, J., Curiously Recurring Template + Patterns, C++ Report, February 1995, pp. 24-27. + diff --git a/libs/iterator/doc/iterator_facade_ref.rst b/libs/iterator/doc/iterator_facade_ref.rst new file mode 100644 index 00000000..87c032ac --- /dev/null +++ b/libs/iterator/doc/iterator_facade_ref.rst @@ -0,0 +1,441 @@ +.. 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) + +.. Version 1.3 of this ReStructuredText document corresponds to + n1530_, the paper accepted by the LWG for TR1. + +.. Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. + + +.. parsed-literal:: + + template < + class Derived + , class Value + , class CategoryOrTraversal + , class Reference = Value& + , class Difference = ptrdiff_t + > + class iterator_facade { + public: + typedef remove_const::type value_type; + typedef Reference reference; + typedef Value\* pointer; + typedef Difference difference_type; + typedef /* see below__ \*/ iterator_category; + + reference operator\*() const; + /* see below__ \*/ operator->() const; + /* see below__ \*/ operator[](difference_type n) const; + Derived& operator++(); + Derived operator++(int); + Derived& operator--(); + Derived operator--(int); + Derived& operator+=(difference_type n); + Derived& operator-=(difference_type n); + Derived operator-(difference_type n) const; + protected: + typedef iterator_facade iterator_facade\_; + }; + + // Comparison operators + template + typename enable_if_interoperable::type // exposition + operator ==(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator !=(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator <(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator <=(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator >(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator >=(iterator_facade const& lhs, + iterator_facade const& rhs); + + // Iterator difference + template + /* see below__ \*/ + operator-(iterator_facade const& lhs, + iterator_facade const& rhs); + + // Iterator addition + template + Derived operator+ (iterator_facade const&, + typename Derived::difference_type n); + + template + Derived operator+ (typename Derived::difference_type n, + iterator_facade const&); + +__ `iterator category`_ + +__ `operator arrow`_ + +__ brackets_ + +__ minus_ + +.. _`iterator category`: + +The ``iterator_category`` member of ``iterator_facade`` is + +.. parsed-literal:: + + *iterator-category*\ (CategoryOrTraversal, reference, value_type) + +where *iterator-category* is defined as follows: + +.. include:: facade_iterator_category.rst + +The ``enable_if_interoperable`` template used above is for exposition +purposes. The member operators should only be in an overload set +provided the derived types ``Dr1`` and ``Dr2`` are interoperable, +meaning that at least one of the types is convertible to the other. The +``enable_if_interoperable`` approach uses SFINAE to take the operators +out of the overload set when the types are not interoperable. +The operators should behave *as-if* ``enable_if_interoperable`` +were defined to be:: + + template enable_if_interoperable_impl + {}; + + template enable_if_interoperable_impl + { typedef T type; }; + + template + struct enable_if_interoperable + : enable_if_interoperable_impl< + is_convertible::value || is_convertible::value + , T + > + {}; + + +``iterator_facade`` Requirements +-------------------------------- + +The following table describes the typical valid expressions on +``iterator_facade``\ 's ``Derived`` parameter, depending on the +iterator concept(s) it will model. The operations in the first +column must be made accessible to member functions of class +``iterator_core_access``. In addition, +``static_cast(iterator_facade*)`` shall be well-formed. + +In the table below, ``F`` is ``iterator_facade``, ``a`` is an +object of type ``X``, ``b`` and ``c`` are objects of type ``const X``, +``n`` is an object of ``F::difference_type``, ``y`` is a constant +object of a single pass iterator type interoperable with ``X``, and ``z`` +is a constant object of a random access traversal iterator type +interoperable with ``X``. + +.. _`core operations`: + +.. topic:: ``iterator_facade`` Core Operations + + +--------------------+----------------------+-------------------------+---------------------------+ + |Expression |Return Type |Assertion/Note |Used to implement Iterator | + | | | |Concept(s) | + +====================+======================+=========================+===========================+ + |``c.dereference()`` |``F::reference`` | |Readable Iterator, Writable| + | | | |Iterator | + +--------------------+----------------------+-------------------------+---------------------------+ + |``c.equal(y)`` |convertible to bool |true iff ``c`` and ``y`` |Single Pass Iterator | + | | |refer to the same | | + | | |position. | | + +--------------------+----------------------+-------------------------+---------------------------+ + |``a.increment()`` |unused | |Incrementable Iterator | + +--------------------+----------------------+-------------------------+---------------------------+ + |``a.decrement()`` |unused | |Bidirectional Traversal | + | | | |Iterator | + +--------------------+----------------------+-------------------------+---------------------------+ + |``a.advance(n)`` |unused | |Random Access Traversal | + | | | |Iterator | + +--------------------+----------------------+-------------------------+---------------------------+ + |``c.distance_to(z)``|convertible to |equivalent to |Random Access Traversal | + | |``F::difference_type``|``distance(c, X(z))``. |Iterator | + +--------------------+----------------------+-------------------------+---------------------------+ + + + +``iterator_facade`` operations +------------------------------ + +The operations in this section are described in terms of operations on +the core interface of ``Derived`` which may be inaccessible +(i.e. private). The implementation should access these operations +through member functions of class ``iterator_core_access``. + +``reference operator*() const;`` + +:Returns: ``static_cast(this)->dereference()`` + +``operator->() const;`` (see below__) + +__ `operator arrow`_ + +:Returns: If ``reference`` is a reference type, an object + of type ``pointer`` equal to:: + + &static_cast(this)->dereference() + + Otherwise returns an object of unspecified type such that, + ``(*static_cast(this))->m`` is equivalent to ``(w = **static_cast(this), + w.m)`` for some temporary object ``w`` of type ``value_type``. + +.. _brackets: + +*unspecified* ``operator[](difference_type n) const;`` + +:Returns: an object convertible to ``value_type``. For constant + objects ``v`` of type ``value_type``, and ``n`` of type + ``difference_type``, ``(*this)[n] = v`` is equivalent to + ``*(*this + n) = v``, and ``static_cast((*this)[n])`` is equivalent to + ``static_cast(*(*this + n))`` + + + +``Derived& operator++();`` + +:Effects: + + :: + + static_cast(this)->increment(); + return *static_cast(this); + +``Derived operator++(int);`` + +:Effects: + + :: + + Derived tmp(static_cast(this)); + ++*this; + return tmp; + + +``Derived& operator--();`` + +:Effects: + + :: + + static_cast(this)->decrement(); + return *static_cast(this); + + +``Derived operator--(int);`` + +:Effects: + + :: + + Derived tmp(static_cast(this)); + --*this; + return tmp; + + +``Derived& operator+=(difference_type n);`` + +:Effects: + + :: + + static_cast(this)->advance(n); + return *static_cast(this); + + +``Derived& operator-=(difference_type n);`` + +:Effects: + + :: + + static_cast(this)->advance(-n); + return *static_cast(this); + + +``Derived operator-(difference_type n) const;`` + +:Effects: + + :: + + Derived tmp(static_cast(this)); + return tmp -= n; + +:: + + template + Derived operator+ (iterator_facade const&, + typename Derived::difference_type n); + + template + Derived operator+ (typename Derived::difference_type n, + iterator_facade const&); + +:Effects: + + :: + + Derived tmp(static_cast(this)); + return tmp += n; + + +:: + + template + typename enable_if_interoperable::type + operator ==(iterator_facade const& lhs, + iterator_facade const& rhs); + +:Returns: + if ``is_convertible::value`` + + then + ``((Dr1 const&)lhs).equal((Dr2 const&)rhs)``. + + Otherwise, + ``((Dr2 const&)rhs).equal((Dr1 const&)lhs)``. + +:: + + template + typename enable_if_interoperable::type + operator !=(iterator_facade const& lhs, + iterator_facade const& rhs); + +:Returns: + if ``is_convertible::value`` + + then + ``!((Dr1 const&)lhs).equal((Dr2 const&)rhs)``. + + Otherwise, + ``!((Dr2 const&)rhs).equal((Dr1 const&)lhs)``. + +:: + + template + typename enable_if_interoperable::type + operator <(iterator_facade const& lhs, + iterator_facade const& rhs); + +:Returns: + if ``is_convertible::value`` + + then + ``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) < 0``. + + Otherwise, + ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) > 0``. + +:: + + template + typename enable_if_interoperable::type + operator <=(iterator_facade const& lhs, + iterator_facade const& rhs); + +:Returns: + if ``is_convertible::value`` + + then + ``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) <= 0``. + + Otherwise, + ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) >= 0``. + +:: + + template + typename enable_if_interoperable::type + operator >(iterator_facade const& lhs, + iterator_facade const& rhs); + +:Returns: + if ``is_convertible::value`` + + then + ``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) > 0``. + + Otherwise, + ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) < 0``. + + +:: + + template + typename enable_if_interoperable::type + operator >=(iterator_facade const& lhs, + iterator_facade const& rhs); + +:Returns: + if ``is_convertible::value`` + + then + ``((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) >= 0``. + + Otherwise, + ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) <= 0``. + +.. _minus: + +:: + + template + typename enable_if_interoperable::type + operator -(iterator_facade const& lhs, + iterator_facade const& rhs); + +:Return Type: + if ``is_convertible::value`` + + then + ``difference`` shall be + ``iterator_traits::difference_type``. + + Otherwise + ``difference`` shall be ``iterator_traits::difference_type`` + +:Returns: + if ``is_convertible::value`` + + then + ``-((Dr1 const&)lhs).distance_to((Dr2 const&)rhs)``. + + Otherwise, + ``((Dr2 const&)rhs).distance_to((Dr1 const&)lhs)``. diff --git a/libs/iterator/doc/iterator_facade_tutorial.rst b/libs/iterator/doc/iterator_facade_tutorial.rst new file mode 100644 index 00000000..75564b77 --- /dev/null +++ b/libs/iterator/doc/iterator_facade_tutorial.rst @@ -0,0 +1,523 @@ +.. Copyright David Abrahams 2004. Use, modification and distribution is +.. subject to 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) + +In this section we'll walk through the implementation of a few +iterators using ``iterator_facade``, based around the simple +example of a linked list of polymorphic objects. This example was +inspired by a `posting`__ by Keith Macdonald on the `Boost-Users`_ +mailing list. + +.. _`Boost-Users`: http://www.boost.org/more/mailing_lists.htm#users + +__ http://thread.gmane.org/gmane.comp.lib.boost.user/5100 + +The Problem +----------- + +Say we've written a polymorphic linked list node base class:: + + # include + + struct node_base + { + node_base() : m_next(0) {} + + // Each node manages all of its tail nodes + virtual ~node_base() { delete m_next; } + + // Access the rest of the list + node_base* next() const { return m_next; } + + // print to the stream + virtual void print(std::ostream& s) const = 0; + + // double the value + virtual void double_me() = 0; + + void append(node_base* p) + { + if (m_next) + m_next->append(p); + else + m_next = p; + } + + private: + node_base* m_next; + }; + +Lists can hold objects of different types by linking together +specializations of the following template:: + + template + struct node : node_base + { + node(T x) + : m_value(x) + {} + + void print(std::ostream& s) const { s << this->m_value; } + void double_me() { m_value += m_value; } + + private: + T m_value; + }; + +And we can print any node using the following streaming operator:: + + inline std::ostream& operator<<(std::ostream& s, node_base const& n) + { + n.print(s); + return s; + } + +Our first challenge is to build an appropriate iterator over these +lists. + +A Basic Iterator Using ``iterator_facade`` +------------------------------------------ + +We will construct a ``node_iterator`` class using inheritance from +``iterator_facade`` to implement most of the iterator's operations. + +:: + + # include "node.hpp" + # include + + class node_iterator + : public boost::iterator_facade<...> + { + ... + }; + + + +Template Arguments for ``iterator_facade`` +.......................................... + +``iterator_facade`` has several template parameters, so we must decide +what types to use for the arguments. The parameters are ``Derived``, +``Value``, ``CategoryOrTraversal``, ``Reference``, and ``Difference``. + + +``Derived`` +''''''''''' + +Because ``iterator_facade`` is meant to be used with the CRTP +[Cop95]_ the first parameter is the iterator class name itself, +``node_iterator``. + +``Value`` +''''''''' + +The ``Value`` parameter determines the ``node_iterator``\ 's +``value_type``. In this case, we are iterating over ``node_base`` +objects, so ``Value`` will be ``node_base``. + + +``CategoryOrTraversal`` +''''''''''''''''''''''' + +Now we have to determine which `iterator traversal concept`_ our +``node_iterator`` is going to model. Singly-linked lists only have +forward links, so our iterator can't can't be a `bidirectional +traversal iterator`_. Our iterator should be able to make multiple +passes over the same linked list (unlike, say, an +``istream_iterator`` which consumes the stream it traverses), so it +must be a `forward traversal iterator`_. Therefore, we'll pass +``boost::forward_traversal_tag`` in this position [#category]_. + +.. [#category] ``iterator_facade`` also supports old-style category + tags, so we could have passed ``std::forward_iterator_tag`` here; + either way, the resulting iterator's ``iterator_category`` will + end up being ``std::forward_iterator_tag``. + +``Reference`` +''''''''''''' + +The ``Reference`` argument becomes the type returned by +``node_iterator``\ 's dereference operation, and will also be the +same as ``std::iterator_traits::reference``. The +library's default for this parameter is ``Value&``; since +``node_base&`` is a good choice for the iterator's ``reference`` +type, we can omit this argument, or pass ``use_default``. + +``Difference`` +'''''''''''''' + +The ``Difference`` argument determines how the distance between +two ``node_iterator``\ s will be measured and will also be the +same as ``std::iterator_traits::difference_type``. +The library's default for ``Difference`` is ``std::ptrdiff_t``, an +appropriate type for measuring the distance between any two +addresses in memory, and one that works for almost any iterator, +so we can omit this argument, too. + +The declaration of ``node_iterator`` will therefore look something +like:: + + # include "node.hpp" + # include + + class node_iterator + : public boost::iterator_facade< + node_iterator + , node_base + , boost::forward_traversal_tag + > + { + ... + }; + +Constructors and Data Members +............................. + +Next we need to decide how to represent the iterator's position. +This representation will take the form of data members, so we'll +also need to write constructors to initialize them. The +``node_iterator``\ 's position is quite naturally represented using +a pointer to a ``node_base``. We'll need a constructor to build an +iterator from a ``node_base*``, and a default constructor to +satisfy the `forward traversal iterator`_ requirements [#default]_. +Our ``node_iterator`` then becomes:: + + # include "node.hpp" + # include + + class node_iterator + : public boost::iterator_facade< + node_iterator + , node_base + , boost::forward_traversal_tag + > + { + public: + node_iterator() + : m_node(0) + {} + + explicit node_iterator(node_base* p) + : m_node(p) + {} + + private: + ... + node_base* m_node; + }; + +.. [#default] Technically, the C++ standard places almost no + requirements on a default-constructed iterator, so if we were + really concerned with efficiency, we could've written the + default constructor to leave ``m_node`` uninitialized. + +Implementing the Core Operations +................................ + +The last step is to implement the `core operations`_ required by +the concepts we want our iterator to model. Referring to the +table__, we can see that the first three rows are applicable +because ``node_iterator`` needs to satisfy the requirements for +`readable iterator`_, `single pass iterator`_, and `incrementable +iterator`_. + +__ `core operations`_ + +We therefore need to supply ``dereference``, +``equal``, and ``increment`` members. We don't want these members +to become part of ``node_iterator``\ 's public interface, so we can +make them private and grant friendship to +``boost::iterator_core_access``, a "back-door" that +``iterator_facade`` uses to get access to the core operations:: + + # include "node.hpp" + # include + + class node_iterator + : public boost::iterator_facade< + node_iterator + , node_base + , boost::forward_traversal_tag + > + { + public: + node_iterator() + : m_node(0) {} + + explicit node_iterator(node_base* p) + : m_node(p) {} + + private: + friend class boost::iterator_core_access; + + void increment() { m_node = m_node->next(); } + + bool equal(node_iterator const& other) const + { + return this->m_node == other.m_node; + } + + node_base& dereference() const { return *m_node; } + + node_base* m_node; + }; + +Voilà; a complete and conforming readable, forward-traversal +iterator! For a working example of its use, see `this program`__. + +__ ../example/node_iterator1.cpp + +A constant ``node_iterator`` +---------------------------- + +.. Sidebar:: Constant and Mutable iterators + + The term **mutable iterator** means an iterator through which + the object it references (its "referent") can be modified. A + **constant iterator** is one which doesn't allow modification of + its referent. + + The words *constant* and *mutable* don't refer to the ability to + modify the iterator itself. For example, an ``int const*`` is a + non-\ ``const`` *constant iterator*, which can be incremented + but doesn't allow modification of its referent, and ``int* + const`` is a ``const`` *mutable iterator*, which cannot be + modified but which allows modification of its referent. + + Confusing? We agree, but those are the standard terms. It + probably doesn't help much that a container's constant iterator + is called ``const_iterator``. + +Now, our ``node_iterator`` gives clients access to both ``node``\ +'s ``print(std::ostream&) const`` member function, but also its +mutating ``double_me()`` member. If we wanted to build a +*constant* ``node_iterator``, we'd only have to make three +changes: + +.. parsed-literal:: + + class const_node_iterator + : public boost::iterator_facade< + const_node_iterator + , node_base **const** + , boost::forward_traversal_tag + > + { + public: + const_node_iterator() + : m_node(0) {} + + explicit const_node_iterator(node_base* p) + : m_node(p) {} + + private: + friend class boost::iterator_core_access; + + void increment() { m_node = m_node->next(); } + + bool equal(const_node_iterator const& other) const + { + return this->m_node == other.m_node; + } + + node_base **const**\ & dereference() const { return \*m_node; } + + node_base **const**\ * m_node; + }; + +.. Sidebar:: ``const`` and an iterator's ``value_type`` + + The C++ standard requires an iterator's ``value_type`` *not* be + ``const``\ -qualified, so ``iterator_facade`` strips the + ``const`` from its ``Value`` parameter in order to produce the + iterator's ``value_type``. Making the ``Value`` argument + ``const`` provides a useful hint to ``iterator_facade`` that the + iterator is a *constant iterator*, and the default ``Reference`` + argument will be correct for all lvalue iterators. + +As a matter of fact, ``node_iterator`` and ``const_node_iterator`` +are so similar that it makes sense to factor the common code out +into a template as follows:: + + template + class node_iter + : public boost::iterator_facade< + node_iter + , Value + , boost::forward_traversal_tag + > + { + public: + node_iter() + : m_node(0) {} + + explicit node_iter(Value* p) + : m_node(p) {} + + private: + friend class boost::iterator_core_access; + + bool equal(node_iter const& other) const + { + return this->m_node == other.m_node; + } + + void increment() + { m_node = m_node->next(); } + + Value& dereference() const + { return *m_node; } + + Value* m_node; + }; + typedef node_iter node_iterator; + typedef node_iter node_const_iterator; + + +Interoperability +---------------- + +Our ``const_node_iterator`` works perfectly well on its own, but +taken together with ``node_iterator`` it doesn't quite meet +expectations. For example, we'd like to be able to pass a +``node_iterator`` where a ``node_const_iterator`` was expected, +just as you can with ``std::list``\ 's ``iterator`` and +``const_iterator``. Furthermore, given a ``node_iterator`` and a +``node_const_iterator`` into the same list, we should be able to +compare them for equality. + +This expected ability to use two different iterator types together +is known as |interoperability|_. Achieving interoperability in +our case is as simple as templatizing the ``equal`` function and +adding a templatized converting constructor [#broken]_ [#random]_:: + + template + class node_iter + : public boost::iterator_facade< + node_iter + , Value + , boost::forward_traversal_tag + > + { + public: + node_iter() + : m_node(0) {} + + explicit node_iter(Value* p) + : m_node(p) {} + + template + node_iter(node_iter const& other) + : m_node(other.m_node) {} + + private: + friend class boost::iterator_core_access; + template friend class node_iter; + + template + bool equal(node_iter const& other) const + { + return this->m_node == other.m_node; + } + + void increment() + { m_node = m_node->next(); } + + Value& dereference() const + { return *m_node; } + + Value* m_node; + }; + typedef impl::node_iterator node_iterator; + typedef impl::node_iterator node_const_iterator; + +.. |interoperability| replace:: **interoperability** +.. _interoperability: new-iter-concepts.html#interoperable-iterators-lib-interoperable-iterators + +.. [#broken] If you're using an older compiler and it can't handle + this example, see the `example code`__ for workarounds. + +.. [#random] If ``node_iterator`` had been a `random access + traversal iterator`_, we'd have had to templatize its + ``distance_to`` function as well. + + +__ ../example/node_iterator2.hpp + +You can see an example program which exercises our interoperable +iterators `here`__. + +__ ../example/node_iterator2.cpp + +Telling the Truth +----------------- + +Now ``node_iterator`` and ``node_const_iterator`` behave exactly as +you'd expect... almost. We can compare them and we can convert in +one direction: from ``node_iterator`` to ``node_const_iterator``. +If we try to convert from ``node_const_iterator`` to +``node_iterator``, we'll get an error when the converting +constructor tries to initialize ``node_iterator``\ 's ``m_node``, a +``node*`` with a ``node const*``. So what's the problem? + +The problem is that +``boost::``\ |is_convertible|_\ ``::value`` +will be ``true``, but it should be ``false``. |is_convertible|_ +lies because it can only see as far as the *declaration* of +``node_iter``\ 's converting constructor, but can't look inside at +the *definition* to make sure it will compile. A perfect solution +would make ``node_iter``\ 's converting constructor disappear when +the ``m_node`` conversion would fail. + +.. |is_convertible| replace:: ``is_convertible`` +.. _is_convertible: ../../type_traits/index.html#relationships + +In fact, that sort of magic is possible using +|enable_if|__. By rewriting the converting constructor as +follows, we can remove it from the overload set when it's not +appropriate:: + + #include + #include + + ... + + private: + struct enabler {}; + + public: + template + node_iter( + node_iter const& other + , typename boost::enable_if< + boost::is_convertible + , enabler + >::type = enabler() + ) + : m_node(other.m_node) {} + +.. |enable_if| replace:: ``boost::enable_if`` +__ ../../utility/enable_if.html + + +Wrap Up +------- + +This concludes our ``iterator_facade`` tutorial, but before you +stop reading we urge you to take a look at |iterator_adaptor|__. +There's another way to approach writing these iterators which might +even be superior. + +.. |iterator_adaptor| replace:: ``iterator_adaptor`` +__ iterator_adaptor.html + +.. _`iterator traversal concept`: new-iter-concepts.html#iterator-traversal-concepts-lib-iterator-traversal +.. _`readable iterator`: new-iter-concepts.html#readable-iterators-lib-readable-iterators +.. _`lvalue iterator`: new-iter-concepts.html#lvalue-iterators-lib-lvalue-iterators +.. _`single pass iterator`: new-iter-concepts.html#single-pass-iterators-lib-single-pass-iterators +.. _`incrementable iterator`: new-iter-concepts.html#incrementable-iterators-lib-incrementable-iterators +.. _`forward traversal iterator`: new-iter-concepts.html#forward-traversal-iterators-lib-forward-traversal-iterators +.. _`bidirectional traversal iterator`: new-iter-concepts.html#bidirectional-traversal-iterators-lib-bidirectional-traversal-iterators +.. _`random access traversal iterator`: new-iter-concepts.html#random-access-traversal-iterators-lib-random-access-traversal-iterators + diff --git a/libs/iterator/doc/iterator_traits.html b/libs/iterator/doc/iterator_traits.html new file mode 100644 index 00000000..ed892416 --- /dev/null +++ b/libs/iterator/doc/iterator_traits.html @@ -0,0 +1,109 @@ + + + + + + +Iterator Traits + + + + + + + +

+

Iterator Traits

+ +++ + + + + + + + + + + + +
Author:David Abrahams
Contact:dave@boost-consulting.com
Organization:Boost Consulting
Date:$Date$
Copyright:Copyright David Abrahams 2004.
+ + + + +++ + + + +
abstract:Header <boost/iterator/iterator_traits.hpp> provides +the ability to access an iterator's associated types using +MPL-compatible metafunctions.
+
+

Overview

+

std::iterator_traits provides access to five associated types +of any iterator: its value_type, reference, pointer, +iterator_category, and difference_type. Unfortunately, +such a "multi-valued" traits template can be difficult to use in a +metaprogramming context. <boost/iterator/iterator_traits.hpp> +provides access to these types using a standard metafunctions.

+
+
+

Summary

+

Header <boost/iterator/iterator_traits.hpp>:

+
+template <class Iterator>
+struct iterator_value
+{
+    typedef typename
+      std::iterator_traits<Iterator>::value_type
+    type;
+};
+
+template <class Iterator>
+struct iterator_reference
+{
+    typedef typename
+      std::iterator_traits<Iterator>::reference
+    type;
+};
+
+
+template <class Iterator>
+struct iterator_pointer
+{
+    typedef typename
+      std::iterator_traits<Iterator>::pointer
+    type;
+};
+
+template <class Iterator>
+struct iterator_difference
+{
+    typedef typename
+      detail::iterator_traits<Iterator>::difference_type
+    type;
+};
+
+template <class Iterator>
+struct iterator_category
+{
+    typedef typename
+      detail::iterator_traits<Iterator>::iterator_category
+    type;
+};
+
+
+
+ + + diff --git a/libs/iterator/doc/iterator_traits.pdf b/libs/iterator/doc/iterator_traits.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b5c765a81e404eefe815b9d4dc1ac051af3ba470 GIT binary patch literal 49650 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 HaiaeN8zBeD literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/iterator_traits.rst b/libs/iterator/doc/iterator_traits.rst new file mode 100644 index 00000000..664001a2 --- /dev/null +++ b/libs/iterator/doc/iterator_traits.rst @@ -0,0 +1,77 @@ +.. 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) + ++++++++++++++++++ + Iterator Traits ++++++++++++++++++ + +:Author: David Abrahams +:Contact: dave@boost-consulting.com +:organization: `Boost Consulting`_ +:date: $Date$ +:copyright: Copyright David Abrahams 2004. + +.. _`Boost Consulting`: http://www.boost-consulting.com + +:abstract: Header ```` provides + the ability to access an iterator's associated types using + MPL-compatible metafunctions_. + +.. _metafunctions: ../../mpl/doc/index.html#metafunctions + +Overview +======== + +``std::iterator_traits`` provides access to five associated types +of any iterator: its ``value_type``, ``reference``, ``pointer``, +``iterator_category``, and ``difference_type``. Unfortunately, +such a "multi-valued" traits template can be difficult to use in a +metaprogramming context. ```` +provides access to these types using a standard metafunctions_. + +Summary +======= + +Header ````:: + + template + struct iterator_value + { + typedef typename + std::iterator_traits::value_type + type; + }; + + template + struct iterator_reference + { + typedef typename + std::iterator_traits::reference + type; + }; + + + template + struct iterator_pointer + { + typedef typename + std::iterator_traits::pointer + type; + }; + + template + struct iterator_difference + { + typedef typename + detail::iterator_traits::difference_type + type; + }; + + template + struct iterator_category + { + typedef typename + detail::iterator_traits::iterator_category + type; + }; diff --git a/libs/iterator/doc/make_counting_iterator.rst b/libs/iterator/doc/make_counting_iterator.rst new file mode 100644 index 00000000..84770939 --- /dev/null +++ b/libs/iterator/doc/make_counting_iterator.rst @@ -0,0 +1,12 @@ +.. Copyright David Abrahams 2006. 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) + +:: + + template + counting_iterator make_counting_iterator(Incrementable x); + +:Returns: An instance of ``counting_iterator`` + with ``current`` constructed from ``x``. + diff --git a/libs/iterator/doc/make_filter_iterator.rst b/libs/iterator/doc/make_filter_iterator.rst new file mode 100644 index 00000000..4374b60a --- /dev/null +++ b/libs/iterator/doc/make_filter_iterator.rst @@ -0,0 +1,19 @@ +.. Copyright David Abrahams 2006. 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) + +:: + + template + filter_iterator + make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); + +:Returns: filter_iterator(f, x, end) + +:: + + template + filter_iterator + make_filter_iterator(Iterator x, Iterator end = Iterator()); + +:Returns: filter_iterator(x, end) diff --git a/libs/iterator/doc/make_reverse_iterator.rst b/libs/iterator/doc/make_reverse_iterator.rst new file mode 100644 index 00000000..dea13641 --- /dev/null +++ b/libs/iterator/doc/make_reverse_iterator.rst @@ -0,0 +1,13 @@ +.. Copyright David Abrahams 2006. 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) + +:: + + template + reverse_iteratorn + make_reverse_iterator(BidirectionalIterator x); + +:Returns: An instance of ``reverse_iterator`` + with a ``current`` constructed from ``x``. + diff --git a/libs/iterator/doc/make_transform_iterator.rst b/libs/iterator/doc/make_transform_iterator.rst new file mode 100644 index 00000000..6ac566bf --- /dev/null +++ b/libs/iterator/doc/make_transform_iterator.rst @@ -0,0 +1,23 @@ +.. Copyright David Abrahams 2006. 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) + +:: + + template + transform_iterator + make_transform_iterator(Iterator it, UnaryFunction fun); + +:Returns: An instance of ``transform_iterator`` with ``m_f`` + initialized to ``f`` and ``m_iterator`` initialized to ``x``. + + + +:: + + template + transform_iterator + make_transform_iterator(Iterator it); + +:Returns: An instance of ``transform_iterator`` with ``m_f`` + default constructed and ``m_iterator`` initialized to ``x``. diff --git a/libs/iterator/doc/make_zip_iterator.rst b/libs/iterator/doc/make_zip_iterator.rst new file mode 100644 index 00000000..e74b8953 --- /dev/null +++ b/libs/iterator/doc/make_zip_iterator.rst @@ -0,0 +1,12 @@ +.. Copyright David Abrahams 2006. 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) + +:: + + template + zip_iterator + make_zip_iterator(IteratorTuple t); + +:Returns: An instance of ``zip_iterator`` with ``m_iterator_tuple`` + initialized to ``t``. diff --git a/libs/iterator/doc/new-iter-concepts.html b/libs/iterator/doc/new-iter-concepts.html new file mode 100644 index 00000000..426bedeb --- /dev/null +++ b/libs/iterator/doc/new-iter-concepts.html @@ -0,0 +1,1029 @@ + + + + + + +New Iterator Concepts + + + + + + + +
+

New Iterator Concepts

+ +++ + + + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@styleadvisor.com
Organization:Boost Consulting, Indiana University Open Systems +Lab, Zephyr Associates, Inc.
Date:2006-09-11
Number:This is a revised version of n1550=03-0133, which was +accepted for Technical Report 1 by the C++ standard +committee's library working group. This proposal is a +revision of paper n1297, n1477, and n1531.
Copyright:Copyright David Abrahams, Jeremy Siek, and Thomas Witt +2003.
+ + + + + +++ + + + +
Abstract:We propose a new system of iterator concepts that treat +access and positioning independently. This allows the +concepts to more closely match the requirements +of algorithms and provides better categorizations +of iterators that are used in practice.
+ +
+

Motivation

+

The standard iterator categories and requirements are flawed because +they use a single hierarchy of concepts to address two orthogonal +issues: iterator traversal and value access. As a result, many +algorithms with requirements expressed in terms of the iterator +categories are too strict. Also, many real-world iterators can not be +accurately categorized. A proxy-based iterator with random-access +traversal, for example, may only legally have a category of "input +iterator", so generic algorithms are unable to take advantage of its +random-access capabilities. The current iterator concept hierarchy is +geared towards iterator traversal (hence the category names), while +requirements that address value access sneak in at various places. The +following table gives a summary of the current value access +requirements in the iterator categories.

+ ++++ + + + + + + + + + + + + + + + + + + +
Value Access Requirements in Existing Iterator Categories
Output Iterator*i = a
Input Iterator*i is convertible to T
Forward Iterator*i is T& (or const T& once issue 200 +is resolved)
Random Access Iteratori[n] is convertible to T (also i[n] = t +is required for mutable iterators once issue 299 +is resolved)
+

Because iterator traversal and value access are mixed together in a +single hierarchy, many useful iterators can not be appropriately +categorized. For example, vector<bool>::iterator is almost a +random access iterator, but the return type is not bool& (see +issue 96 and Herb Sutter's paper J16/99-0008 = WG21 +N1185). Therefore, the iterators of vector<bool> only meet the +requirements of input iterator and output iterator. This is so +nonintuitive that the C++ standard contradicts itself on this point. +In paragraph 23.2.4/1 it says that a vector is a sequence that +supports random access iterators.

+

Another difficult-to-categorize iterator is the transform iterator, an +adaptor which applies a unary function object to the dereferenced +value of the some underlying iterator (see transform_iterator). +For unary functions such as times, the return type of +operator* clearly needs to be the result_type of the function +object, which is typically not a reference. Because random access +iterators are required to return lvalues from operator*, if you +wrap int* with a transform iterator, you do not get a random +access iterator as might be expected, but an input iterator.

+

A third example is found in the vertex and edge iterators of the +Boost Graph Library. These iterators return vertex and edge +descriptors, which are lightweight handles created on-the-fly. They +must be returned by-value. As a result, their current standard +iterator category is input_iterator_tag, which means that, +strictly speaking, you could not use these iterators with algorithms +like min_element(). As a temporary solution, the concept +Multi-Pass Input Iterator was introduced to describe the vertex and +edge descriptors, but as the design notes for the concept suggest, a +better solution is needed.

+

In short, there are many useful iterators that do not fit into the +current standard iterator categories. As a result, the following bad +things happen:

+
    +
  • Iterators are often mis-categorized.
  • +
  • Algorithm requirements are more strict than necessary, because they +cannot separate the need for random access or bidirectional +traversal from the need for a true reference return type.
  • +
+
+
+

Impact on the Standard

+

This proposal for TR1 is a pure extension. Further, the new iterator +concepts are backward-compatible with the old iterator requirements, +and old iterators are forward-compatible with the new iterator +concepts. That is to say, iterators that satisfy the old requirements +also satisfy appropriate concepts in the new system, and iterators +modeling the new concepts will automatically satisfy the appropriate +old requirements.

+ + +
+

Possible (but not proposed) Changes to the Working Paper

+

The extensions in this paper suggest several changes we might make +to the working paper for the next standard. These changes are not +a formal part of this proposal for TR1.

+
+

Changes to Algorithm Requirements

+

The algorithms in the standard library could benefit from the new +iterator concepts because the new concepts provide a more accurate way +to express their type requirements. The result is algorithms that are +usable in more situations and have fewer type requirements.

+

For the next working paper (but not for TR1), the committee should +consider the following changes to the type requirements of algorithms. +These changes are phrased as textual substitutions, listing the +algorithms to which each textual substitution applies.

+

Forward Iterator -> Forward Traversal Iterator and Readable Iterator

+
+find_end, adjacent_find, search, search_n, rotate_copy, +lower_bound, upper_bound, equal_range, binary_search, +min_element, max_element
+

Forward Iterator (1) -> Single Pass Iterator and Readable Iterator, +Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator

+
+find_first_of
+

Forward Iterator -> Readable Iterator and Writable Iterator

+
+iter_swap
+

Forward Iterator -> Single Pass Iterator and Writable Iterator

+
+fill, generate
+

Forward Iterator -> Forward Traversal Iterator and Swappable Iterator

+
+rotate
+

Forward Iterator (1) -> Swappable Iterator and Single Pass Iterator, +Forward Iterator (2) -> Swappable Iterator and Incrementable Iterator

+
+swap_ranges
+
+
Forward Iterator -> Forward Traversal Iterator and Readable Iterator and Writable Iterator
+
remove, remove_if, unique
+
+

Forward Iterator -> Single Pass Iterator and Readable Iterator and Writable Iterator

+
+replace, replace_if
+
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator
+
reverse
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable and Swappable Iterator
+
partition
+
+

Bidirectional Iterator (1) -> Bidirectional Traversal Iterator and Readable Iterator, +Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable Iterator

+
+copy_backwards
+
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator and Readable Iterator
+
next_permutation, prev_permutation
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator and Writable Iterator
+
stable_partition, inplace_merge
+
Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator
+
reverse_copy
+
Random Access Iterator -> Random Access Traversal Iterator and Readable and Writable Iterator
+
random_shuffle, sort, stable_sort, partial_sort, nth_element, push_heap, pop_heap +make_heap, sort_heap
+
Input Iterator (2) -> Incrementable Iterator and Readable Iterator
+
equal, mismatch
+
Input Iterator (2) -> Incrementable Iterator and Readable Iterator
+
transform
+
+
+
+

Deprecations

+

For the next working paper (but not for TR1), the committee should +consider deprecating the old iterator tags, and +std::iterator_traits, since it will be superceded by individual +traits metafunctions.

+
+
+

vector<bool>

+

For the next working paper (but not for TR1), the committee should +consider reclassifying vector<bool>::iterator as a Random +Access Traversal Iterator and Readable Iterator and Writable +Iterator.

+
+
+
+
+

Design

+

The iterator requirements are to be separated into two groups. One set +of concepts handles the syntax and semantics of value access:

+
    +
  • Readable Iterator
  • +
  • Writable Iterator
  • +
  • Swappable Iterator
  • +
  • Lvalue Iterator
  • +
+

The access concepts describe requirements related to operator* and +operator->, including the value_type, reference, and +pointer associated types.

+

The other set of concepts handles traversal:

+
    +
  • Incrementable Iterator
  • +
  • Single Pass Iterator
  • +
  • Forward Traversal Iterator
  • +
  • Bidirectional Traversal Iterator
  • +
  • Random Access Traversal Iterator
  • +
+

The refinement relationships for the traversal concepts are in the +following diagram.

+traversal.png +

In addition to the iterator movement operators, such as +operator++, the traversal concepts also include requirements on +position comparison such as operator== and operator<. The +reason for the fine grain slicing of the concepts into the +Incrementable and Single Pass is to provide concepts that are exact +matches with the original input and output iterator requirements.

+

This proposal also includes a concept for specifying when an iterator +is interoperable with another iterator, in the sense that int* is +interoperable with int const*.

+
    +
  • Interoperable Iterators
  • +
+

The relationship between the new iterator concepts and the old are +given in the following diagram.

+oldeqnew.png +

Like the old iterator requirements, we provide tags for purposes of +dispatching based on the traversal concepts. The tags are related via +inheritance so that a tag is convertible to another tag if the concept +associated with the first tag is a refinement of the second tag.

+

Our design reuses iterator_traits<Iter>::iterator_category to +indicate an iterator's traversal capability. To specify +capabilities not captured by any old-style iterator category, an +iterator designer can use an iterator_category type that is +convertible to both the the most-derived old iterator category tag +which fits, and the appropriate new iterator traversal tag.

+ +

We do not provide tags for the purposes of dispatching based on the +access concepts, in part because we could not find a way to +automatically infer the right access tags for old-style iterators. +An iterator's writability may be dependent on the assignability of +its value_type and there's no known way to detect whether an +arbitrary type is assignable. Fortunately, the need for +dispatching based on access capability is not as great as the need +for dispatching based on traversal capability.

+

A difficult design decision concerned the operator[]. The direct +approach for specifying operator[] would have a return type of +reference; the same as operator*. However, going in this +direction would mean that an iterator satisfying the old Random Access +Iterator requirements would not necessarily be a model of Readable or +Writable Lvalue Iterator. Instead we have chosen a design that +matches the preferred resolution of issue 299: operator[] is +only required to return something convertible to the value_type +(for a Readable Iterator), and is required to support assignment +i[n] = t (for a Writable Iterator).

+
+
+

Proposed Text

+
+

Addition to [lib.iterator.requirements]

+
+

Iterator Value Access Concepts [lib.iterator.value.access]

+

In the tables below, X is an iterator type, a is a constant +object of type X, R is +std::iterator_traits<X>::reference, T is +std::iterator_traits<X>::value_type, and v is a constant +object of type T.

+
+

Readable Iterators [lib.readable.iterators]

+

A class or built-in type X models the Readable Iterator concept +for value type T if, in addition to X being Assignable and +Copy Constructible, the following expressions are valid and respect +the stated semantics. U is the type of any specified member of +type T.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
Readable Iterator Requirements (in addition to Assignable and Copy Constructible)
ExpressionReturn TypeNote/Precondition
iterator_traits<X>::value_typeTAny non-reference, +non-cv-qualified type
*aConvertible to T
+
pre: a is dereferenceable. If a == b then *a
+
is equivalent to *b.
+
+
a->mU&pre: pre: (*a).m is well-defined. Equivalent to (*a).m.
+ +
+
+

Writable Iterators [lib.writable.iterators]

+

A class or built-in type X models the Writable Iterator concept +if, in addition to X being Copy Constructible, the following +expressions are valid and respect the stated semantics. Writable +Iterators have an associated set of value types.

+ +++++ + + + + + + + + + + + + + + +
Writable Iterator Requirements (in addition to Copy Constructible)
ExpressionReturn TypePrecondition
*a = o pre: The type of o +is in the set of +value types of X
+
+
+

Swappable Iterators [lib.swappable.iterators]

+

A class or built-in type X models the Swappable Iterator concept +if, in addition to X being Copy Constructible, the following +expressions are valid and respect the stated semantics.

+ +++++ + + + + + + + + + + + + + + +
Swappable Iterator Requirements (in addition to Copy Constructible)
ExpressionReturn TypePostcondition
iter_swap(a, b)voidthe pointed to values are +exchanged
+

[Note: An iterator that is a model of the Readable Iterator and +Writable Iterator concepts is also a model of Swappable +Iterator. --end note]

+
+
+

Lvalue Iterators [lib.lvalue.iterators]

+

The Lvalue Iterator concept adds the requirement that the return +type of operator* type be a reference to the value type of the +iterator.

+ +++++ + + + + + + + + + + + + + + +
Lvalue Iterator Requirements
ExpressionReturn TypeNote/Assertion
*aT&T is cv +iterator_traits<X>::value_type +where cv is an optional +cv-qualification. pre: a is +dereferenceable.
+

If X is a Writable Iterator then a == b if and only if +*a is the same object as *b. If X is a Readable +Iterator then a == b implies *a is the same object as +*b.

+
+
+
+

Iterator Traversal Concepts [lib.iterator.traversal]

+

In the tables below, X is an iterator type, a and b are +constant objects of type X, r and s are mutable objects of +type X, T is std::iterator_traits<X>::value_type, and +v is a constant object of type T.

+
+

Incrementable Iterators [lib.incrementable.iterators]

+

A class or built-in type X models the Incrementable Iterator +concept if, in addition to X being Assignable and Copy +Constructible, the following expressions are valid and respect the +stated semantics.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible)
ExpressionReturn TypeAssertion
++rX&&r == &++r
r++  
*r++  
iterator_traversal<X>::typeConvertible to +incrementable_traversal_tag 
+

If X is a Writable Iterator then X a(r++); is equivalent +to X a(r); ++r; and *r++ = o is equivalent +to *r = o; ++r. +If X is a Readable Iterator then T z(*r++); is equivalent +to T z(*r); ++r;.

+ +
+
+

Single Pass Iterators [lib.single.pass.iterators]

+

A class or built-in type X models the Single Pass Iterator +concept if the following expressions are valid and respect the stated +semantics.

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality +Comparable)
ExpressionReturn TypeOperational +SemanticsAssertion/ +Pre-/Post-condition
++rX& pre: r is +dereferenceable; post: +r is dereferenceable or +r is past-the-end
a == bconvertible to bool == is an equivalence +relation over its domain
a != bconvertible to bool!(a == b) 
iterator_traits<X>::difference_typeA signed integral type +representing the distance +between iterators  
iterator_traversal<X>::typeConvertible to +single_pass_traversal_tag  
+ +
+
+

Forward Traversal Iterators [lib.forward.traversal.iterators]

+

A class or built-in type X models the Forward Traversal Iterator +concept if, in addition to X meeting the requirements of Default +Constructible and Single Pass Iterator, the following expressions are +valid and respect the stated semantics.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
Forward Traversal Iterator Requirements (in addition to Default Constructible and Single Pass Iterator)
ExpressionReturn TypeAssertion/Note
X u;X&note: u may have a +singular value.
++rX&r == s and r is +dereferenceable implies +++r == ++s.
iterator_traversal<X>::typeConvertible to +forward_traversal_tag 
+ +
+
+

Bidirectional Traversal Iterators [lib.bidirectional.traversal.iterators]

+

A class or built-in type X models the Bidirectional Traversal +Iterator concept if, in addition to X meeting the requirements of +Forward Traversal Iterator, the following expressions are valid and +respect the stated semantics.

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal +Iterator)
ExpressionReturn TypeOperational +SemanticsAssertion/ +Pre-/Post-condition
--rX& 

pre: there exists +s such that r +== ++s. post: +s is +dereferenceable.

+

++(--r) == r. +--r == --s +implies r == +s. &r == &--r.

+
r--convertible to const X&
+{
+  X tmp = r;
+  --r;
+  return tmp;
+}
+
+
 
iterator_traversal<X>::typeConvertible to +bidirectional_traversal_tag  
+ +
+
+

Random Access Traversal Iterators [lib.random.access.traversal.iterators]

+

A class or built-in type X models the Random Access Traversal +Iterator concept if the following expressions are valid and respect +the stated semantics. In the table below, Distance is +iterator_traits<X>::difference_type and n represents a +constant object of type Distance.

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator)
ExpressionReturn TypeOperational SemanticsAssertion/ +Precondition
r += nX&
+{
+  Distance m = n;
+  if (m >= 0)
+    while (m--)
+      ++r;
+  else
+    while (m++)
+      --r;
+  return r;
+}
+
+
 
a + n, n + aX{ X tmp = a; return tmp ++= n; } 
r -= nX&return r += -n 
a - nX{ X tmp = a; return tmp +-= n; } 
b - aDistancea < b ?  distance(a,b) +: -distance(b,a)pre: there exists a +value n of +Distance such that +a + n == b. b +== a + (b - a).
a[n]convertible to T*(a + n)pre: a is a Readable +Iterator
a[n] = vconvertible to T*(a + n) = vpre: a is a Writable +Iterator
a < bconvertible to boolb - a > 0< is a total +ordering relation
a > bconvertible to boolb < a> is a total +ordering relation
a >= bconvertible to bool!(a < b) 
a <= bconvertible to bool!(a > b) 
iterator_traversal<X>::typeConvertible to +random_access_traversal_tag  
+ +
+
+

Interoperable Iterators [lib.interoperable.iterators]

+

A class or built-in type X that models Single Pass Iterator is +interoperable with a class or built-in type Y that also models +Single Pass Iterator if the following expressions are valid and +respect the stated semantics. In the tables below, x is an object +of type X, y is an object of type Y, Distance is +iterator_traits<Y>::difference_type, and n represents a +constant object of type Distance.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionReturn TypeAssertion/Precondition/Postcondition
y = xYpost: y == x
Y(x)Ypost: Y(x) == x
x == yconvertible to bool== is an equivalence relation over its domain.
y == xconvertible to bool== is an equivalence relation over its domain.
x != yconvertible to boolbool(a==b) != bool(a!=b) over its domain.
y != xconvertible to boolbool(a==b) != bool(a!=b) over its domain.
+

If X and Y both model Random Access Traversal Iterator then +the following additional requirements must be met.

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionReturn TypeOperational SemanticsAssertion/ Precondition
x < yconvertible to booly - x > 0< is a total ordering relation
y < xconvertible to boolx - y > 0< is a total ordering relation
x > yconvertible to booly < x> is a total ordering relation
y > xconvertible to boolx < y> is a total ordering relation
x >= yconvertible to bool!(x < y) 
y >= xconvertible to bool!(y < x) 
x <= yconvertible to bool!(x > y) 
y <= xconvertible to bool!(y > x) 
y - xDistancedistance(Y(x),y)pre: there exists a value n of +Distance such that x + n == y. +y == x + (y - x).
x - yDistancedistance(y,Y(x))pre: there exists a value n of +Distance such that y + n == x. +x == y + (x - y).
+
+
+
+
+

Addition to [lib.iterator.synopsis]

+
+// lib.iterator.traits, traits and tags
+template <class Iterator> struct is_readable_iterator;
+template <class Iterator> struct iterator_traversal;
+
+struct incrementable_traversal_tag { };
+struct single_pass_traversal_tag : incrementable_traversal_tag { };
+struct forward_traversal_tag : single_pass_traversal_tag { };
+struct bidirectional_traversal_tag : forward_traversal_tag { };
+struct random_access_traversal_tag : bidirectional_traversal_tag { };
+
+
+
+

Addition to [lib.iterator.traits]

+

The is_readable_iterator class +template satisfies the UnaryTypeTrait requirements.

+

Given an iterator type X, is_readable_iterator<X>::value +yields true if, for an object a of type X, *a is +convertible to iterator_traits<X>::value_type, and false +otherwise.

+

iterator_traversal<X>::type is

+
+category-to-traversal(iterator_traits<X>::iterator_category)
+
+

where category-to-traversal is defined as follows

+
+category-to-traversal(C) =
+    if (C is convertible to incrementable_traversal_tag)
+        return C;
+    else if (C is convertible to random_access_iterator_tag)
+        return random_access_traversal_tag;
+    else if (C is convertible to bidirectional_iterator_tag)
+        return bidirectional_traversal_tag;
+    else if (C is convertible to forward_iterator_tag)
+        return forward_traversal_tag;
+    else if (C is convertible to input_iterator_tag)
+        return single_pass_traversal_tag;
+    else if (C is convertible to output_iterator_tag)
+        return incrementable_traversal_tag;
+    else
+        the program is ill-formed
+
+
+
+
+

Footnotes

+

The UnaryTypeTrait concept is defined in n1519; the LWG is +considering adding the requirement that specializations are derived +from their nested ::type.

+ +
+
+ + + diff --git a/libs/iterator/doc/new-iter-concepts.pdf b/libs/iterator/doc/new-iter-concepts.pdf new file mode 100644 index 0000000000000000000000000000000000000000..aa680ec96e1fffcee99b52be9ac8c528d8d1c72c GIT binary patch literal 175676 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::iterator`` is almost a +random access iterator, but the return type is not ``bool&`` (see +`issue 96`_ and Herb Sutter's paper J16/99-0008 = WG21 +N1185). Therefore, the iterators of ``vector`` only meet the +requirements of input iterator and output iterator. This is so +nonintuitive that the C++ standard contradicts itself on this point. +In paragraph 23.2.4/1 it says that a ``vector`` is a sequence that +supports random access iterators. + +.. _issue 96: http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#96 + +Another difficult-to-categorize iterator is the transform iterator, an +adaptor which applies a unary function object to the dereferenced +value of the some underlying iterator (see `transform_iterator`_). +For unary functions such as ``times``, the return type of +``operator*`` clearly needs to be the ``result_type`` of the function +object, which is typically not a reference. Because random access +iterators are required to return lvalues from ``operator*``, if you +wrap ``int*`` with a transform iterator, you do not get a random +access iterator as might be expected, but an input iterator. + +.. _`transform_iterator`: http://www.boost.org/libs/utility/transform_iterator.htm + +A third example is found in the vertex and edge iterators of the +`Boost Graph Library`_. These iterators return vertex and edge +descriptors, which are lightweight handles created on-the-fly. They +must be returned by-value. As a result, their current standard +iterator category is ``input_iterator_tag``, which means that, +strictly speaking, you could not use these iterators with algorithms +like ``min_element()``. As a temporary solution, the concept +`Multi-Pass Input Iterator`_ was introduced to describe the vertex and +edge descriptors, but as the design notes for the concept suggest, a +better solution is needed. + +.. _Boost Graph Library: http://www.boost.org/libs/graph/doc/table_of_contents.html +.. _Multi-Pass Input Iterator: http://www.boost.org/libs/utility/MultiPassInputIterator.html + +In short, there are many useful iterators that do not fit into the +current standard iterator categories. As a result, the following bad +things happen: + +- Iterators are often mis-categorized. + +- Algorithm requirements are more strict than necessary, because they + cannot separate the need for random access or bidirectional + traversal from the need for a true reference return type. + + +======================== + Impact on the Standard +======================== + +This proposal for TR1 is a pure extension. Further, the new iterator +concepts are backward-compatible with the old iterator requirements, +and old iterators are forward-compatible with the new iterator +concepts. That is to say, iterators that satisfy the old requirements +also satisfy appropriate concepts in the new system, and iterators +modeling the new concepts will automatically satisfy the appropriate +old requirements. + +.. I think we need to say something about the resolution to allow + convertibility to any of the old-style tags as a TR issue (hope it + made it). -DWA + +.. Hmm, not sure I understand. Are you talking about whether a + standards conforming input iterator is allowed to have + a tag that is not input_iterator_tag but that + is convertible to input_iterator_tag? -JGS + +Possible (but not proposed) Changes to the Working Paper +======================================================== + +The extensions in this paper suggest several changes we might make +to the working paper for the next standard. These changes are not +a formal part of this proposal for TR1. + +Changes to Algorithm Requirements ++++++++++++++++++++++++++++++++++ + +The algorithms in the standard library could benefit from the new +iterator concepts because the new concepts provide a more accurate way +to express their type requirements. The result is algorithms that are +usable in more situations and have fewer type requirements. + +For the next working paper (but not for TR1), the committee should +consider the following changes to the type requirements of algorithms. +These changes are phrased as textual substitutions, listing the +algorithms to which each textual substitution applies. + +Forward Iterator -> Forward Traversal Iterator and Readable Iterator + + ``find_end, adjacent_find, search, search_n, rotate_copy, + lower_bound, upper_bound, equal_range, binary_search, + min_element, max_element`` + +Forward Iterator (1) -> Single Pass Iterator and Readable Iterator, +Forward Iterator (2) -> Forward Traversal Iterator and Readable Iterator + + ``find_first_of`` + +Forward Iterator -> Readable Iterator and Writable Iterator + + ``iter_swap`` + +Forward Iterator -> Single Pass Iterator and Writable Iterator + + ``fill, generate`` + +Forward Iterator -> Forward Traversal Iterator and Swappable Iterator + + ``rotate`` + +Forward Iterator (1) -> Swappable Iterator and Single Pass Iterator, +Forward Iterator (2) -> Swappable Iterator and Incrementable Iterator + + ``swap_ranges`` + +Forward Iterator -> Forward Traversal Iterator and Readable Iterator and Writable Iterator + ``remove, remove_if, unique`` + +Forward Iterator -> Single Pass Iterator and Readable Iterator and Writable Iterator + + ``replace, replace_if`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator + ``reverse`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable and Swappable Iterator + ``partition`` + +Bidirectional Iterator (1) -> Bidirectional Traversal Iterator and Readable Iterator, +Bidirectional Iterator (2) -> Bidirectional Traversal Iterator and Writable Iterator + + ``copy_backwards`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Swappable Iterator and Readable Iterator + ``next_permutation, prev_permutation`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator and Writable Iterator + ``stable_partition, inplace_merge`` + +Bidirectional Iterator -> Bidirectional Traversal Iterator and Readable Iterator + ``reverse_copy`` + +Random Access Iterator -> Random Access Traversal Iterator and Readable and Writable Iterator + ``random_shuffle, sort, stable_sort, partial_sort, nth_element, push_heap, pop_heap + make_heap, sort_heap`` + +Input Iterator (2) -> Incrementable Iterator and Readable Iterator + ``equal, mismatch`` + +Input Iterator (2) -> Incrementable Iterator and Readable Iterator + ``transform`` + +Deprecations +++++++++++++ + +For the next working paper (but not for TR1), the committee should +consider deprecating the old iterator tags, and +std::iterator_traits, since it will be superceded by individual +traits metafunctions. + +``vector`` +++++++++++++++++ + +For the next working paper (but not for TR1), the committee should +consider reclassifying ``vector::iterator`` as a Random +Access Traversal Iterator and Readable Iterator and Writable +Iterator. + +======== + Design +======== + +The iterator requirements are to be separated into two groups. One set +of concepts handles the syntax and semantics of value access: + +- Readable Iterator +- Writable Iterator +- Swappable Iterator +- Lvalue Iterator + +The access concepts describe requirements related to ``operator*`` and +``operator->``, including the ``value_type``, ``reference``, and +``pointer`` associated types. + +The other set of concepts handles traversal: + +- Incrementable Iterator +- Single Pass Iterator +- Forward Traversal Iterator +- Bidirectional Traversal Iterator +- Random Access Traversal Iterator + +The refinement relationships for the traversal concepts are in the +following diagram. + +.. image:: traversal.png + +In addition to the iterator movement operators, such as +``operator++``, the traversal concepts also include requirements on +position comparison such as ``operator==`` and ``operator<``. The +reason for the fine grain slicing of the concepts into the +Incrementable and Single Pass is to provide concepts that are exact +matches with the original input and output iterator requirements. + +This proposal also includes a concept for specifying when an iterator +is interoperable with another iterator, in the sense that ``int*`` is +interoperable with ``int const*``. + +- Interoperable Iterators + + +The relationship between the new iterator concepts and the old are +given in the following diagram. + +.. image:: oldeqnew.png + +Like the old iterator requirements, we provide tags for purposes of +dispatching based on the traversal concepts. The tags are related via +inheritance so that a tag is convertible to another tag if the concept +associated with the first tag is a refinement of the second tag. + +Our design reuses ``iterator_traits::iterator_category`` to +indicate an iterator's traversal capability. To specify +capabilities not captured by any old-style iterator category, an +iterator designer can use an ``iterator_category`` type that is +convertible to both the the most-derived old iterator category tag +which fits, and the appropriate new iterator traversal tag. + +.. dwa2003/1/2: Note that we are not *requiring* convertibility to + a new-style traversal tag in order to meet new concepts. + Old-style iterators still fit, after all. + +We do not provide tags for the purposes of dispatching based on the +access concepts, in part because we could not find a way to +automatically infer the right access tags for old-style iterators. +An iterator's writability may be dependent on the assignability of +its ``value_type`` and there's no known way to detect whether an +arbitrary type is assignable. Fortunately, the need for +dispatching based on access capability is not as great as the need +for dispatching based on traversal capability. + +A difficult design decision concerned the ``operator[]``. The direct +approach for specifying ``operator[]`` would have a return type of +``reference``; the same as ``operator*``. However, going in this +direction would mean that an iterator satisfying the old Random Access +Iterator requirements would not necessarily be a model of Readable or +Writable Lvalue Iterator. Instead we have chosen a design that +matches the preferred resolution of `issue 299`_: ``operator[]`` is +only required to return something convertible to the ``value_type`` +(for a Readable Iterator), and is required to support assignment +``i[n] = t`` (for a Writable Iterator). + + +=============== + Proposed Text +=============== + +Addition to [lib.iterator.requirements] +======================================= + +Iterator Value Access Concepts [lib.iterator.value.access] +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +In the tables below, ``X`` is an iterator type, ``a`` is a constant +object of type ``X``, ``R`` is +``std::iterator_traits::reference``, ``T`` is +``std::iterator_traits::value_type``, and ``v`` is a constant +object of type ``T``. + +.. _Readable Iterator: + +Readable Iterators [lib.readable.iterators] +------------------------------------------- + +A class or built-in type ``X`` models the *Readable Iterator* concept +for value type ``T`` if, in addition to ``X`` being Assignable and +Copy Constructible, the following expressions are valid and respect +the stated semantics. ``U`` is the type of any specified member of +type ``T``. + ++-----------------------------------------------------------------------------------------------------------------------------+ +|Readable Iterator Requirements (in addition to Assignable and Copy Constructible) | ++-----------------------------------+------------------------+----------------------------------------------------------------+ +|Expression |Return Type |Note/Precondition | ++===================================+========================+================================================================+ +|``iterator_traits::value_type`` |``T`` |Any non-reference, | +| | |non-cv-qualified type | ++-----------------------------------+------------------------+----------------------------------------------------------------+ +|``*a`` | Convertible to ``T`` |pre: ``a`` is dereferenceable. If ``a == b`` then ``*a`` | +| | | is equivalent to ``*b``. | ++-----------------------------------+------------------------+----------------------------------------------------------------+ +|``a->m`` |``U&`` |pre: ``pre: (*a).m`` is well-defined. Equivalent to ``(*a).m``. | ++-----------------------------------+------------------------+----------------------------------------------------------------+ + +.. We won't say anything about iterator_traits::reference until the DR is resolved. -JGS + +.. _Writable Iterator: + +Writable Iterators [lib.writable.iterators] +------------------------------------------- + +A class or built-in type ``X`` models the *Writable Iterator* concept +if, in addition to ``X`` being Copy Constructible, the following +expressions are valid and respect the stated semantics. Writable +Iterators have an associated *set of value types*. + ++---------------------------------------------------------------------+ +|Writable Iterator Requirements (in addition to Copy Constructible) | ++-------------------------+--------------+----------------------------+ +|Expression |Return Type |Precondition | ++=========================+==============+============================+ +|``*a = o`` | | pre: The type of ``o`` | +| | | is in the set of | +| | | value types of ``X`` | ++-------------------------+--------------+----------------------------+ + +Swappable Iterators [lib.swappable.iterators] +--------------------------------------------- + +A class or built-in type ``X`` models the *Swappable Iterator* concept +if, in addition to ``X`` being Copy Constructible, the following +expressions are valid and respect the stated semantics. + ++---------------------------------------------------------------------+ +|Swappable Iterator Requirements (in addition to Copy Constructible) | ++-------------------------+-------------+-----------------------------+ +|Expression |Return Type |Postcondition | ++=========================+=============+=============================+ +|``iter_swap(a, b)`` |``void`` |the pointed to values are | +| | |exchanged | ++-------------------------+-------------+-----------------------------+ + +[*Note:* An iterator that is a model of the `Readable Iterator`_ and +`Writable Iterator`_ concepts is also a model of *Swappable +Iterator*. *--end note*] + + +Lvalue Iterators [lib.lvalue.iterators] +--------------------------------------- + +The *Lvalue Iterator* concept adds the requirement that the return +type of ``operator*`` type be a reference to the value type of the +iterator. + ++-------------------------------------------------------------+ +| Lvalue Iterator Requirements | ++-------------+-----------+-----------------------------------+ +|Expression |Return Type|Note/Assertion | ++=============+===========+===================================+ +|``*a`` | ``T&`` |``T`` is *cv* | +| | |``iterator_traits::value_type`` | +| | |where *cv* is an optional | +| | |cv-qualification. pre: ``a`` is | +| | |dereferenceable. | ++-------------+-----------+-----------------------------------+ + +If ``X`` is a `Writable Iterator`_ then ``a == b`` if and only if +``*a`` is the same object as ``*b``. If ``X`` is a `Readable +Iterator`_ then ``a == b`` implies ``*a`` is the same object as +``*b``. + + +Iterator Traversal Concepts [lib.iterator.traversal] +++++++++++++++++++++++++++++++++++++++++++++++++++++ + +In the tables below, ``X`` is an iterator type, ``a`` and ``b`` are +constant objects of type ``X``, ``r`` and ``s`` are mutable objects of +type ``X``, ``T`` is ``std::iterator_traits::value_type``, and +``v`` is a constant object of type ``T``. + +Incrementable Iterators [lib.incrementable.iterators] +----------------------------------------------------- + +A class or built-in type ``X`` models the *Incrementable Iterator* +concept if, in addition to ``X`` being Assignable and Copy +Constructible, the following expressions are valid and respect the +stated semantics. + ++------------------------------------------------------------------------------------+ +|Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible) | +| | ++--------------------------------+-------------------------------+-------------------+ +|Expression |Return Type |Assertion | ++================================+===============================+===================+ +|``++r`` |``X&`` |``&r == &++r`` | ++--------------------------------+-------------------------------+-------------------+ +|``r++`` | | | ++--------------------------------+-------------------------------+-------------------+ +|``*r++`` | | | ++--------------------------------+-------------------------------+-------------------+ +|``iterator_traversal::type`` |Convertible to | | +| |``incrementable_traversal_tag``| | ++--------------------------------+-------------------------------+-------------------+ + + +If ``X`` is a `Writable Iterator`_ then ``X a(r++);`` is equivalent +to ``X a(r); ++r;`` and ``*r++ = o`` is equivalent +to ``*r = o; ++r``. +If ``X`` is a `Readable Iterator`_ then ``T z(*r++);`` is equivalent +to ``T z(*r); ++r;``. + +.. TR1: incrementable_iterator_tag changed to + incrementable_traversal_tag for consistency. + +Single Pass Iterators [lib.single.pass.iterators] +------------------------------------------------- + +A class or built-in type ``X`` models the *Single Pass Iterator* +concept if the following expressions are valid and respect the stated +semantics. + + ++----------------------------------------------------------------------------------------------------------------+ +|Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality Comparable) | +| | ++----------------------------------------+-----------------------------+-------------+---------------------------+ +|Expression |Return Type | Operational |Assertion/ | +| | | Semantics |Pre-/Post-condition | ++========================================+=============================+=============+===========================+ +|``++r`` |``X&`` | |pre: ``r`` is | +| | | |dereferenceable; post: | +| | | |``r`` is dereferenceable or| +| | | |``r`` is past-the-end | ++----------------------------------------+-----------------------------+-------------+---------------------------+ +|``a == b`` |convertible to ``bool`` | |``==`` is an equivalence | +| | | |relation over its domain | ++----------------------------------------+-----------------------------+-------------+---------------------------+ +|``a != b`` |convertible to ``bool`` |``!(a == b)``| | ++----------------------------------------+-----------------------------+-------------+---------------------------+ +|``iterator_traits::difference_type`` |A signed integral type | | | +| |representing the distance | | | +| |between iterators | | | ++----------------------------------------+-----------------------------+-------------+---------------------------+ +|``iterator_traversal::type`` |Convertible to | | | +| |``single_pass_traversal_tag``| | | ++----------------------------------------+-----------------------------+-------------+---------------------------+ + +.. TR1: single_pass_iterator_tag changed to + single_pass_traversal_tag for consistency + + +Forward Traversal Iterators [lib.forward.traversal.iterators] +------------------------------------------------------------- + +A class or built-in type ``X`` models the *Forward Traversal Iterator* +concept if, in addition to ``X`` meeting the requirements of Default +Constructible and Single Pass Iterator, the following expressions are +valid and respect the stated semantics. + ++--------------------------------------------------------------------------------------------------------+ +|Forward Traversal Iterator Requirements (in addition to Default Constructible and Single Pass Iterator) | ++---------------------------------------+-----------------------------------+----------------------------+ +|Expression |Return Type |Assertion/Note | ++=======================================+===================================+============================+ +|``X u;`` |``X&`` |note: ``u`` may have a | +| | |singular value. | ++---------------------------------------+-----------------------------------+----------------------------+ +|``++r`` |``X&`` |``r == s`` and ``r`` is | +| | |dereferenceable implies | +| | |``++r == ++s.`` | ++---------------------------------------+-----------------------------------+----------------------------+ +|``iterator_traversal::type`` |Convertible to | | +| |``forward_traversal_tag`` | | ++---------------------------------------+-----------------------------------+----------------------------+ + + + +.. TR1: forward_traversal_iterator_tag changed to + forward_traversal_tag for consistency + + +Bidirectional Traversal Iterators [lib.bidirectional.traversal.iterators] +------------------------------------------------------------------------- + +A class or built-in type ``X`` models the *Bidirectional Traversal +Iterator* concept if, in addition to ``X`` meeting the requirements of +Forward Traversal Iterator, the following expressions are valid and +respect the stated semantics. + ++-----------------------------------------------------------------------------------------------------+ +|Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal | +|Iterator) | ++--------------------------------+-------------------------------+--------------+---------------------+ +|Expression |Return Type | Operational |Assertion/ | +| | | Semantics |Pre-/Post-condition | ++================================+===============================+==============+=====================+ +|``--r`` |``X&`` | |pre: there exists | +| | | |``s`` such that ``r | +| | | |== ++s``. post: | +| | | |``s`` is | +| | | |dereferenceable. | +| | | | | +| | | |``++(--r) == r``. | +| | | |``--r == --s`` | +| | | |implies ``r == | +| | | |s``. ``&r == &--r``. | ++--------------------------------+-------------------------------+--------------+---------------------+ +|``r--`` |convertible to ``const X&`` |:: | | +| | | | | +| | | { | | +| | | X tmp = r; | | +| | | --r; | | +| | | return tmp;| | +| | | } | | ++--------------------------------+-------------------------------+--------------+---------------------+ +|``iterator_traversal::type`` |Convertible to | | | +| |``bidirectional_traversal_tag``| | | +| | | | | ++--------------------------------+-------------------------------+--------------+---------------------+ + +.. TR1: bidirectional_traversal_iterator_tag changed to + bidirectional_traversal_tag for consistency + +Random Access Traversal Iterators [lib.random.access.traversal.iterators] +------------------------------------------------------------------------- + +A class or built-in type ``X`` models the *Random Access Traversal +Iterator* concept if the following expressions are valid and respect +the stated semantics. In the table below, ``Distance`` is +``iterator_traits::difference_type`` and ``n`` represents a +constant object of type ``Distance``. + ++------------------------------------------------------------------------------------------------------------------+ +|Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal Iterator) | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|Expression |Return Type |Operational Semantics |Assertion/ | +| | | |Precondition | ++===============================+=================================+=========================+======================+ +|``r += n`` |``X&`` |:: | | +| | | | | +| | | { | | +| | | Distance m = n; | | +| | | if (m >= 0) | | +| | | while (m--) | | +| | | ++r; | | +| | | else | | +| | | while (m++) | | +| | | --r; | | +| | | return r; | | +| | | } | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a + n``, ``n + a`` |``X`` |``{ X tmp = a; return tmp| | +| | |+= n; }`` | | +| | | | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``r -= n`` |``X&`` |``return r += -n`` | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a - n`` |``X`` |``{ X tmp = a; return tmp| | +| | |-= n; }`` | | +| | | | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``b - a`` |``Distance`` |``a < b ? distance(a,b) |pre: there exists a | +| | |: -distance(b,a)`` |value ``n`` of | +| | | |``Distance`` such that| +| | | |``a + n == b``. ``b | +| | | |== a + (b - a)``. | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a[n]`` |convertible to T |``*(a + n)`` |pre: a is a `Readable | +| | | |Iterator`_ | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a[n] = v`` |convertible to T |``*(a + n) = v`` |pre: a is a `Writable | +| | | |Iterator`_ | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a < b`` |convertible to ``bool`` |``b - a > 0`` |``<`` is a total | +| | | |ordering relation | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a > b`` |convertible to ``bool`` |``b < a`` |``>`` is a total | +| | | |ordering relation | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a >= b`` |convertible to ``bool`` |``!(a < b)`` | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``a <= b`` |convertible to ``bool`` |``!(a > b)`` | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ +|``iterator_traversal::type``|Convertible to | | | +| |``random_access_traversal_tag`` | | | ++-------------------------------+---------------------------------+-------------------------+----------------------+ + +.. TR1: random_access_traversal_iterator_tag changed to + random_access_traversal_tag for consistency + + +Interoperable Iterators [lib.interoperable.iterators] +----------------------------------------------------- + +A class or built-in type ``X`` that models Single Pass Iterator is +*interoperable with* a class or built-in type ``Y`` that also models +Single Pass Iterator if the following expressions are valid and +respect the stated semantics. In the tables below, ``x`` is an object +of type ``X``, ``y`` is an object of type ``Y``, ``Distance`` is +``iterator_traits::difference_type``, and ``n`` represents a +constant object of type ``Distance``. + ++-----------+-----------------------+---------------------------------------------------+ +|Expression |Return Type |Assertion/Precondition/Postcondition | ++===========+=======================+===================================================+ +|``y = x`` |``Y`` |post: ``y == x`` | ++-----------+-----------------------+---------------------------------------------------+ +|``Y(x)`` |``Y`` |post: ``Y(x) == x`` | ++-----------+-----------------------+---------------------------------------------------+ +|``x == y`` |convertible to ``bool``|``==`` is an equivalence relation over its domain. | ++-----------+-----------------------+---------------------------------------------------+ +|``y == x`` |convertible to ``bool``|``==`` is an equivalence relation over its domain. | ++-----------+-----------------------+---------------------------------------------------+ +|``x != y`` |convertible to ``bool``|``bool(a==b) != bool(a!=b)`` over its domain. | ++-----------+-----------------------+---------------------------------------------------+ +|``y != x`` |convertible to ``bool``|``bool(a==b) != bool(a!=b)`` over its domain. | ++-----------+-----------------------+---------------------------------------------------+ + +If ``X`` and ``Y`` both model Random Access Traversal Iterator then +the following additional requirements must be met. + ++-----------+-----------------------+---------------------+--------------------------------------+ +|Expression |Return Type |Operational Semantics|Assertion/ Precondition | ++===========+=======================+=====================+======================================+ +|``x < y`` |convertible to ``bool``|``y - x > 0`` |``<`` is a total ordering relation | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``y < x`` |convertible to ``bool``|``x - y > 0`` |``<`` is a total ordering relation | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``x > y`` |convertible to ``bool``|``y < x`` |``>`` is a total ordering relation | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``y > x`` |convertible to ``bool``|``x < y`` |``>`` is a total ordering relation | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``x >= y`` |convertible to ``bool``|``!(x < y)`` | | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``y >= x`` |convertible to ``bool``|``!(y < x)`` | | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``x <= y`` |convertible to ``bool``|``!(x > y)`` | | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``y <= x`` |convertible to ``bool``|``!(y > x)`` | | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``y - x`` |``Distance`` |``distance(Y(x),y)`` |pre: there exists a value ``n`` of | +| | | |``Distance`` such that ``x + n == y``.| +| | | |``y == x + (y - x)``. | ++-----------+-----------------------+---------------------+--------------------------------------+ +|``x - y`` |``Distance`` |``distance(y,Y(x))`` |pre: there exists a value ``n`` of | +| | | |``Distance`` such that ``y + n == x``.| +| | | |``x == y + (x - y)``. | ++-----------+-----------------------+---------------------+--------------------------------------+ + + + +Addition to [lib.iterator.synopsis] +=================================== + + +:: + + // lib.iterator.traits, traits and tags + template struct is_readable_iterator; + template struct iterator_traversal; + + struct incrementable_traversal_tag { }; + struct single_pass_traversal_tag : incrementable_traversal_tag { }; + struct forward_traversal_tag : single_pass_traversal_tag { }; + struct bidirectional_traversal_tag : forward_traversal_tag { }; + struct random_access_traversal_tag : bidirectional_traversal_tag { }; + +Addition to [lib.iterator.traits] +================================= + +The ``is_readable_iterator`` class +template satisfies the UnaryTypeTrait_ requirements. + +Given an iterator type ``X``, ``is_readable_iterator::value`` +yields ``true`` if, for an object ``a`` of type ``X``, ``*a`` is +convertible to ``iterator_traits::value_type``, and ``false`` +otherwise. + +``iterator_traversal::type`` is + +.. parsed-literal:: + + *category-to-traversal*\ (iterator_traits::iterator_category) + +where *category-to-traversal* is defined as follows + +.. _`category-to-traversal`: + +.. parsed-literal:: + + *category-to-traversal*\ (C) = + if (C is convertible to incrementable_traversal_tag) + return C; + else if (C is convertible to random_access_iterator_tag) + return random_access_traversal_tag; + else if (C is convertible to bidirectional_iterator_tag) + return bidirectional_traversal_tag; + else if (C is convertible to forward_iterator_tag) + return forward_traversal_tag; + else if (C is convertible to input_iterator_tag) + return single_pass_traversal_tag; + else if (C is convertible to output_iterator_tag) + return incrementable_traversal_tag; + else + *the program is ill-formed* + + +=========== + Footnotes +=========== + +.. _UnaryTypeTrait: n1519_ + +The UnaryTypeTrait concept is defined in n1519_; the LWG is +considering adding the requirement that specializations are derived +from their nested ``::type``. + +.. _n1519: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1519.htm + +.. + LocalWords: Abrahams Siek Witt const bool Sutter's WG int UL LI href Lvalue + LocalWords: ReadableIterator WritableIterator SwappableIterator cv pre iter + LocalWords: ConstantLvalueIterator MutableLvalueIterator CopyConstructible TR + LocalWords: ForwardTraversalIterator BidirectionalTraversalIterator lvalue + LocalWords: RandomAccessTraversalIterator dereferenceable Incrementable tmp + LocalWords: incrementable xxx min prev inplace png oldeqnew AccessTag struct + LocalWords: TraversalTag typename lvalues DWA Hmm JGS mis enum diff --git a/libs/iterator/doc/oldeqnew.png b/libs/iterator/doc/oldeqnew.png new file mode 100644 index 0000000000000000000000000000000000000000..30cd1598cb0b5f4cc54a8c600b7d55de7de270d5 GIT binary patch literal 33786 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 z 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 literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/permutation_iter_abstract.rst b/libs/iterator/doc/permutation_iter_abstract.rst new file mode 100644 index 00000000..787c51a5 --- /dev/null +++ b/libs/iterator/doc/permutation_iter_abstract.rst @@ -0,0 +1,8 @@ +.. Copyright David Abrahams 2006. 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 permutation iterator adaptor provides a permuted view of a given +range. That is, the view includes every element of the given range but +in a potentially different order. + diff --git a/libs/iterator/doc/permutation_iterator.html b/libs/iterator/doc/permutation_iterator.html new file mode 100644 index 00000000..ce27429d --- /dev/null +++ b/libs/iterator/doc/permutation_iterator.html @@ -0,0 +1,311 @@ + + + + + + +Permutation Iterator + + + + + + + +
+

Permutation Iterator

+ +++ + + + + + + + + + + + +
Author:Toon Knapen, David Abrahams, Roland Richter, Jeremy Siek
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu
Organization:Boost Consulting, Indiana University Open Systems +Lab
Date:2006-09-11
Copyright:Copyright Toon Knapen, David Abrahams, Roland Richter, and Jeremy Siek 2003.
+ + + + +++ + + + +
abstract: + + +The permutation iterator adaptor provides a permuted view of a given +range. That is, the view includes every element of the given range but +in a potentially different order.
+
+
+

Introduction

+ + + +

The adaptor takes two arguments:

+
+
    +
  • an iterator to the range V on which the permutation +will be applied
  • +
  • the reindexing scheme that defines how the +elements of V will be permuted.
  • +
+
+

Note that the permutation iterator is not limited to strict +permutations of the given range V. The distance between begin and end +of the reindexing iterators is allowed to be smaller compared to the +size of the range V, in which case the permutation iterator only +provides a permutation of a subrange of V. The indexes neither need +to be unique. In this same context, it must be noted that the past the +end permutation iterator is completely defined by means of the +past-the-end iterator to the indices.

+
+
+

Reference

+ + + +
+template< class ElementIterator
+        , class IndexIterator
+        , class ValueT        = use_default
+        , class CategoryT     = use_default
+        , class ReferenceT    = use_default
+        , class DifferenceT   = use_default >
+class permutation_iterator
+{
+public:
+  permutation_iterator();
+  explicit permutation_iterator(ElementIterator x, IndexIterator y);
+
+  template< class OEIter, class OIIter, class V, class C, class R, class D >
+  permutation_iterator(
+      permutation_iterator<OEIter, OIIter, V, C, R, D> const& r
+      , typename enable_if_convertible<OEIter, ElementIterator>::type* = 0
+      , typename enable_if_convertible<OIIter, IndexIterator>::type* = 0
+      );
+  reference operator*() const;
+  permutation_iterator& operator++();
+  ElementIterator const& base() const;
+private:
+  ElementIterator m_elt;      // exposition only
+  IndexIterator m_order;      // exposition only
+};
+
+template <class ElementIterator, class IndexIterator>
+permutation_iterator<ElementIterator, IndexIterator>
+make_permutation_iterator( ElementIterator e, IndexIterator i);
+
+
+

permutation_iterator requirements

+

ElementIterator shall model Random Access Traversal Iterator. +IndexIterator shall model Readable Iterator. The value type of +the IndexIterator must be convertible to the difference type of +ElementIterator.

+
+
+

permutation_iterator models

+

permutation_iterator models the same iterator traversal concepts +as IndexIterator and the same iterator access concepts as +ElementIterator.

+

If IndexIterator models Single Pass Iterator and +ElementIterator models Readable Iterator then +permutation_iterator models Input Iterator.

+

If IndexIterator models Forward Traversal Iterator and +ElementIterator models Readable Lvalue Iterator then +permutation_iterator models Forward Iterator.

+

If IndexIterator models Bidirectional Traversal Iterator and +ElementIterator models Readable Lvalue Iterator then +permutation_iterator models Bidirectional Iterator.

+

If IndexIterator models Random Access Traversal Iterator and +ElementIterator models Readable Lvalue Iterator then +permutation_iterator models Random Access Iterator.

+

permutation_iterator<E1, X, V1, C2, R1, D1> is interoperable +with permutation_iterator<E2, Y, V2, C2, R2, D2> if and only if +X is interoperable with Y and E1 is convertible +to E2.

+
+
+

permutation_iterator operations

+

In addition to those operations required by the concepts that +permutation_iterator models, permutation_iterator provides the +following operations.

+

permutation_iterator();

+ +++ + + + +
Effects:Default constructs m_elt and m_order.
+

explicit permutation_iterator(ElementIterator x, IndexIterator y);

+ +++ + + + +
Effects:Constructs m_elt from x and m_order from y.
+
+template< class OEIter, class OIIter, class V, class C, class R, class D >
+permutation_iterator(
+    permutation_iterator<OEIter, OIIter, V, C, R, D> const& r
+    , typename enable_if_convertible<OEIter, ElementIterator>::type* = 0
+    , typename enable_if_convertible<OIIter, IndexIterator>::type* = 0
+    );
+
+ +++ + + + +
Effects:Constructs m_elt from r.m_elt and +m_order from y.m_order.
+

reference operator*() const;

+ +++ + + + +
Returns:*(m_elt + *m_order)
+

permutation_iterator& operator++();

+ +++ + + + + + +
Effects:++m_order
Returns:*this
+

ElementIterator const& base() const;

+ +++ + + + +
Returns:m_order
+
+template <class ElementIterator, class IndexIterator>
+permutation_iterator<ElementIterator, IndexIterator>
+make_permutation_iterator(ElementIterator e, IndexIterator i);
+
+ +++ + + + +
Returns:permutation_iterator<ElementIterator, IndexIterator>(e, i)
+
+
+
+

Example

+ + + +
+using namespace boost;
+int i = 0;
+
+typedef std::vector< int > element_range_type;
+typedef std::list< int > index_type;
+
+static const int element_range_size = 10;
+static const int index_size = 4;
+
+element_range_type elements( element_range_size );
+for(element_range_type::iterator el_it = elements.begin() ; el_it != elements.end() ; ++el_it)
+  *el_it = std::distance(elements.begin(), el_it);
+
+index_type indices( index_size );
+for(index_type::iterator i_it = indices.begin() ; i_it != indices.end() ; ++i_it )
+  *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it);
+std::reverse( indices.begin(), indices.end() );
+
+typedef permutation_iterator< element_range_type::iterator, index_type::iterator > permutation_type;
+permutation_type begin = make_permutation_iterator( elements.begin(), indices.begin() );
+permutation_type it = begin;
+permutation_type end = make_permutation_iterator( elements.begin(), indices.end() );
+
+std::cout << "The original range is : ";
+std::copy( elements.begin(), elements.end(), std::ostream_iterator< int >( std::cout, " " ) );
+std::cout << "\n";
+
+std::cout << "The reindexing scheme is : ";
+std::copy( indices.begin(), indices.end(), std::ostream_iterator< int >( std::cout, " " ) );
+std::cout << "\n";
+
+std::cout << "The permutated range is : ";
+std::copy( begin, end, std::ostream_iterator< int >( std::cout, " " ) );
+std::cout << "\n";
+
+std::cout << "Elements at even indices in the permutation : ";
+it = begin;
+for(i = 0; i < index_size / 2 ; ++i, it+=2 ) std::cout << *it << " ";
+std::cout << "\n";
+
+std::cout << "Permutation backwards : ";
+it = begin + (index_size);
+assert( it != begin );
+for( ; it-- != begin ; ) std::cout << *it << " ";
+std::cout << "\n";
+
+std::cout << "Iterate backward with stride 2 : ";
+it = begin + (index_size - 1);
+for(i = 0 ; i < index_size / 2 ; ++i, it-=2 ) std::cout << *it << " ";
+std::cout << "\n";
+
+

The output is:

+
+The original range is : 0 1 2 3 4 5 6 7 8 9
+The reindexing scheme is : 9 8 7 6
+The permutated range is : 9 8 7 6
+Elements at even indices in the permutation : 9 7
+Permutation backwards : 6 7 8 9
+Iterate backward with stride 2 : 6 8
+
+

The source code for this example can be found here.

+
+
+ + + diff --git a/libs/iterator/doc/permutation_iterator.pdf b/libs/iterator/doc/permutation_iterator.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3f69d1d34a2af5a77e0dbe0364aac291ce3e764b GIT binary patch literal 66744 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 O8)?zA=dh7(7XJswOC5dy literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/permutation_iterator.rst b/libs/iterator/doc/permutation_iterator.rst new file mode 100644 index 00000000..0c8070cf --- /dev/null +++ b/libs/iterator/doc/permutation_iterator.rst @@ -0,0 +1,41 @@ +.. 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) + +++++++++++++++++++++++ + Permutation Iterator +++++++++++++++++++++++ + +:Author: Toon Knapen, David Abrahams, Roland Richter, Jeremy Siek +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_ +:date: $Date$ +:copyright: Copyright Toon Knapen, David Abrahams, Roland Richter, and Jeremy Siek 2003. + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu + +:abstract: + + .. include:: permutation_iter_abstract.rst + +.. contents:: Table of Contents + + +Introduction +============ + +.. include:: permutation_iterator_body.rst + + +Reference +========= + +.. include:: permutation_iterator_ref.rst + + +Example +======= + +.. include:: permutation_iterator_eg.rst diff --git a/libs/iterator/doc/permutation_iterator_body.rst b/libs/iterator/doc/permutation_iterator_body.rst new file mode 100644 index 00000000..8b1333c1 --- /dev/null +++ b/libs/iterator/doc/permutation_iterator_body.rst @@ -0,0 +1,19 @@ +.. Copyright David Abrahams 2006. 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 adaptor takes two arguments: + + * an iterator to the range V on which the permutation + will be applied + * the reindexing scheme that defines how the + elements of V will be permuted. + +Note that the permutation iterator is not limited to strict +permutations of the given range V. The distance between begin and end +of the reindexing iterators is allowed to be smaller compared to the +size of the range V, in which case the permutation iterator only +provides a permutation of a subrange of V. The indexes neither need +to be unique. In this same context, it must be noted that the past the +end permutation iterator is completely defined by means of the +past-the-end iterator to the indices. diff --git a/libs/iterator/doc/permutation_iterator_eg.rst b/libs/iterator/doc/permutation_iterator_eg.rst new file mode 100644 index 00000000..eddf0a11 --- /dev/null +++ b/libs/iterator/doc/permutation_iterator_eg.rst @@ -0,0 +1,71 @@ +.. Copyright David Abrahams 2006. 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) + +:: + + using namespace boost; + int i = 0; + + typedef std::vector< int > element_range_type; + typedef std::list< int > index_type; + + static const int element_range_size = 10; + static const int index_size = 4; + + element_range_type elements( element_range_size ); + for(element_range_type::iterator el_it = elements.begin() ; el_it != elements.end() ; ++el_it) + *el_it = std::distance(elements.begin(), el_it); + + index_type indices( index_size ); + for(index_type::iterator i_it = indices.begin() ; i_it != indices.end() ; ++i_it ) + *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it); + std::reverse( indices.begin(), indices.end() ); + + typedef permutation_iterator< element_range_type::iterator, index_type::iterator > permutation_type; + permutation_type begin = make_permutation_iterator( elements.begin(), indices.begin() ); + permutation_type it = begin; + permutation_type end = make_permutation_iterator( elements.begin(), indices.end() ); + + std::cout << "The original range is : "; + std::copy( elements.begin(), elements.end(), std::ostream_iterator< int >( std::cout, " " ) ); + std::cout << "\n"; + + std::cout << "The reindexing scheme is : "; + std::copy( indices.begin(), indices.end(), std::ostream_iterator< int >( std::cout, " " ) ); + std::cout << "\n"; + + std::cout << "The permutated range is : "; + std::copy( begin, end, std::ostream_iterator< int >( std::cout, " " ) ); + std::cout << "\n"; + + std::cout << "Elements at even indices in the permutation : "; + it = begin; + for(i = 0; i < index_size / 2 ; ++i, it+=2 ) std::cout << *it << " "; + std::cout << "\n"; + + std::cout << "Permutation backwards : "; + it = begin + (index_size); + assert( it != begin ); + for( ; it-- != begin ; ) std::cout << *it << " "; + std::cout << "\n"; + + std::cout << "Iterate backward with stride 2 : "; + it = begin + (index_size - 1); + for(i = 0 ; i < index_size / 2 ; ++i, it-=2 ) std::cout << *it << " "; + std::cout << "\n"; + + +The output is:: + + The original range is : 0 1 2 3 4 5 6 7 8 9 + The reindexing scheme is : 9 8 7 6 + The permutated range is : 9 8 7 6 + Elements at even indices in the permutation : 9 7 + Permutation backwards : 6 7 8 9 + Iterate backward with stride 2 : 6 8 + + +The source code for this example can be found `here`__. + +__ ../example/permutation_iter_example.cpp diff --git a/libs/iterator/doc/permutation_iterator_ref.rst b/libs/iterator/doc/permutation_iterator_ref.rst new file mode 100644 index 00000000..d51864fc --- /dev/null +++ b/libs/iterator/doc/permutation_iterator_ref.rst @@ -0,0 +1,130 @@ +.. Copyright David Abrahams 2006. 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) + +.. parsed-literal:: + + template< class ElementIterator + , class IndexIterator + , class ValueT = use_default + , class CategoryT = use_default + , class ReferenceT = use_default + , class DifferenceT = use_default > + class permutation_iterator + { + public: + permutation_iterator(); + explicit permutation_iterator(ElementIterator x, IndexIterator y); + + template< class OEIter, class OIIter, class V, class C, class R, class D > + permutation_iterator( + permutation_iterator const& r + , typename enable_if_convertible::type* = 0 + , typename enable_if_convertible::type* = 0 + ); + reference operator*() const; + permutation_iterator& operator++(); + ElementIterator const& base() const; + private: + ElementIterator m_elt; // exposition only + IndexIterator m_order; // exposition only + }; + + template + permutation_iterator + make_permutation_iterator( ElementIterator e, IndexIterator i); + + + +``permutation_iterator`` requirements +------------------------------------- + +``ElementIterator`` shall model Random Access Traversal Iterator. +``IndexIterator`` shall model Readable Iterator. The value type of +the ``IndexIterator`` must be convertible to the difference type of +``ElementIterator``. + + +``permutation_iterator`` models +------------------------------- + +``permutation_iterator`` models the same iterator traversal concepts +as ``IndexIterator`` and the same iterator access concepts as +``ElementIterator``. + +If ``IndexIterator`` models Single Pass Iterator and +``ElementIterator`` models Readable Iterator then +``permutation_iterator`` models Input Iterator. + +If ``IndexIterator`` models Forward Traversal Iterator and +``ElementIterator`` models Readable Lvalue Iterator then +``permutation_iterator`` models Forward Iterator. + +If ``IndexIterator`` models Bidirectional Traversal Iterator and +``ElementIterator`` models Readable Lvalue Iterator then +``permutation_iterator`` models Bidirectional Iterator. + +If ``IndexIterator`` models Random Access Traversal Iterator and +``ElementIterator`` models Readable Lvalue Iterator then +``permutation_iterator`` models Random Access Iterator. + +``permutation_iterator`` is interoperable +with ``permutation_iterator`` if and only if +``X`` is interoperable with ``Y`` and ``E1`` is convertible +to ``E2``. + + +``permutation_iterator`` operations +----------------------------------- + +In addition to those operations required by the concepts that +``permutation_iterator`` models, ``permutation_iterator`` provides the +following operations. + +``permutation_iterator();`` + +:Effects: Default constructs ``m_elt`` and ``m_order``. + + +``explicit permutation_iterator(ElementIterator x, IndexIterator y);`` + +:Effects: Constructs ``m_elt`` from ``x`` and ``m_order`` from ``y``. + + +:: + + template< class OEIter, class OIIter, class V, class C, class R, class D > + permutation_iterator( + permutation_iterator const& r + , typename enable_if_convertible::type* = 0 + , typename enable_if_convertible::type* = 0 + ); + +:Effects: Constructs ``m_elt`` from ``r.m_elt`` and + ``m_order`` from ``y.m_order``. + + +``reference operator*() const;`` + +:Returns: ``*(m_elt + *m_order)`` + + +``permutation_iterator& operator++();`` + +:Effects: ``++m_order`` +:Returns: ``*this`` + + +``ElementIterator const& base() const;`` + +:Returns: ``m_order`` + + +:: + + template + permutation_iterator + make_permutation_iterator(ElementIterator e, IndexIterator i); + +:Returns: ``permutation_iterator(e, i)`` + diff --git a/libs/iterator/doc/pointee.html b/libs/iterator/doc/pointee.html new file mode 100644 index 00000000..1ce5d164 --- /dev/null +++ b/libs/iterator/doc/pointee.html @@ -0,0 +1,183 @@ + + + + + + +pointee and indirect_reference + + + + + + + + + + + diff --git a/libs/iterator/doc/pointee.pdf b/libs/iterator/doc/pointee.pdf new file mode 100644 index 0000000000000000000000000000000000000000..53f9f6db8b403253bb39f3d4ddf488a3ac7a6b1a GIT binary patch literal 62356 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 z zl)`}%%d^yX+pWS9%MY<619=Pq1QhsA;)iIiOBdV8i*9xR3SdC+`;6k3zWR9ZJDuBr z3%Zx@uk06lzVps?quu)HlFuxyp5;{f2)~aLc4N%rvM)jFQbZotKu{vwzU9~`zbi?h znuFJaf5rjIM~eS|j}7;8Kr{+IocIHs&|9y1^iQV-uP)kRhHl;)VKin|j{JslgBg`F$Zud{7`01-Q^b?>sWTgDAobp}ypl z6OS;020mzgLE8JYd+wKB(@=6 zz-6~@av%{e&uB1C3hyB}-%2fDf!+L0FAs|Koa+cChHv%y-^w2gNK`uxN1|bC+gNar zt3Z3|?G9t}foNPd`pxS{XPBY3ohqI74;EoU7iqdael`aeIIpEpXgYt~}`BBE~x*^EsEuJ&B_8rjVhhI~?aeT^*i3@HXu5tN-S|V0NUonubeAVN{&_ z(G3Y#eVk%IUo3rF8=C<4?To{$S7XeEsON2Bt0l@)Cq|bBcQ@s+h2yGua*Fo!>t+Xv z(nPuyx?M7~EOKtb+uhH&o&IJqD)$fS(sJzxAy)3fCg%Ma!^VeegExG4z!5&i-RmYP^U|#v?z5L_D!?kT|ME7Zi`O8&-%(|97w9YtgQ*$@^ zv__(|%`jEJcazQF)<#?uvBI&`Mcdx3;~V?d#QN3)L62R((E8RS4|$y1K;`LnNyC{G z`t^A9D0wYHfg!X@kq$qnM`Vf-a^`Us>NoAoT-sDg%`5Cl#G0tkN<&QrS2zhJSG;H+ z5=qW3%}?`b&{Hdc8U^E?biqaLjZ@;SVUxpKNaf$F++0qyH0#}b2u6+TEUAihNDzHY z;Y|&;u^JtEI&g`X$d1$Po!A|#j8l~Nj9=@#$h#X~-vnUL8VsV@a)&Esp-(Dei#L@B zEZZ2ztVHGEy%>ytlq2mP%w-V?;+jx$XsTZqe=Ud%;6k@7ntlpz{i%zb8T{@=*Kl`> zro2E+sZl#OX^-WA1Tp^Th9|KqQzt%7@#rZz+c@23;Xl~mi_)&*vD~i^qEnZZ?=2f{(svPEJz8Y$E-*vsinrSDj4z zE`!Dby5FHHIL#qS#yu&AnaQZv(BOv+8~Vj={Gh8nZ@dp)q#RM*I^N_e zmrs-^t~7_ypC)>2tJcK6?GUN3$X=}^G^!eAizXw4p=mccy?CqSQjpG_5VTeGg2ry@ zFzu4Q#T97WvlR~YC-fo*;;I(TXMpN7+Kn{}SajvST6W2#f5m~|yQ;bm8{byermY|O zj#0EoX{ANu(9XglPjp@4;;|#@*?)ifQ!TmNBjz)S!&-WITAI0%@u337PlxacXU$@B zA8q{`Tg||nwmt14X=sXJ(`c(gSa;lD*IhO5y{;4Ijp(C$va*zds31=&C4ohC(mTU8 z-t*e(Mtenc`5iv5%x)%SrX8++$q9t;sc9rvC%wKqN9?1Ke3(h_^N9VcowLse2-~iS zBdB8OMGe~wNxO^y{zC4Sig5P9&~(oc@KPTaA*H&z;51UPL!T(8WH z6o!#-2Qh+RT6Cs9|qL+9SW>Ow+uHQ22<0Me5g$FW++UyR*0$1h}*!H`Ws~B{dce@zh%|Q?Mlww1t`l^ccfP z9GANuv>I!!WwAf`kU-6sO=`!n^Eg{#>7aVc*cq=Ho-1iG<=SA$S3w;FC_h)*fpJ8o_$q#;PKNW=3~dvYqK1< z6xU28EaZ-)6HxdrB}KmpbPjoQg8sP-6q64lkyElQ(J&2{fEM%2-fP>qz3M-BQ>9NKIbq#5^z9#WPO3-^au49F>4Q$a^-(i85E$*I+`5B7zQOZczF-_59Q zUnjpt5S5Dbr31tBOo!fXe5N{F{{j4Hy1L?g1+^R-5g}&h5G8ThdC=hyrx)p()dr7T zvBAka;WiL25X!4;>Mb5))1Iw_rYSxf=RH!CGO%dd^k{JTd~oTW+$Cw?jV;I<$zb2` zGRxYDZU)uyBXWcCR?kQtUI4Ud$R%Sk9?YgL;=1z@+Pqnqu3Y9*zVV6IyOqDYn;6C)@swZi`Tlrxmgh|o%Ib0W zgmeF8hDURE(K2SWZyH2NOy2b)#Fw{7G?(_2Q~WD>4285aznF1iuIN*;MyJ_K>~iX_ z!cp<}Z5X7e#huw`yGwCb3L$kCv+LyXe2$Akdkxj%A^W)j5cgOEOL3Snm{og21bPOx zGN(OhSkxm!S8#c0WdrvC-rT;;=rgD4I|*zZmq#L(8|C>4DV#gtXW&7I98ty!t!nd9+rkC!g)D5uKLuZAd$G%;mh-i9h)dIwuJh1XmPF~^5I0(+ zykBpDuSj%o^0KK^(~VjXmDCh*r5&A$&A8(k>3`R(g6`EM`$3O>c&(uuMt#@wW;y0| zCqg304Zh~VUG8J&USijdFdVH^O+h1>e|EhhlpiRF_0n*R>K0MQ;6uEe?4Gk)+#m)}M3nEH%MQEGPny1nDYHnTKTj%I zGB9PQPSDN<&1t$>sj~HjX){c@u)=(Z`Jofln6A*DDdcFnpxkJ`NvT#01l0&GAaFOo zMU-~aroo;-i^F$c0=~*rSFp!C%*GB<;`j^sXGtT-^v-`)!tgo6z7GgWvNptPk`~Lv zpzVP!zeem_Zj#zAhloeykht9)IXeK7)KaM&Ir_9}ibkMOC$bem*KqwxgrI2>$TdnHurlLh65Xs>01D|!SE!MAb? z1;i3fnEbBEZB<)|2v6#6uj`f)+t+iI22x;b={dc7hJ(`$5|AcJ|I>4Q_Qcfh%J1!n zOTC%~voevGSc(DD$P4u60r1pz-jz{Uy72?_YIgUb5vHb!iKda%DfHPG7dT;BZ&I{N z9SPCm)GAOkS~5r<6Ay^rU>mLMm%@=-X22Uc=GTF(Y1m1C;x|na|hugYc6h zcF`e`%OM@Hu5S6%&}K-gT+9+*(;7t^65EEgrQ)WbTbvnd#3>BHiWqa z4nZo<#Lmto4iz^r%tdUDJ*d8OT6KOy!n*vp`rt{}`$7QEBbse$-|hyrJ--8##=ADS zN0*BJNfk60Oa@+TB%6&8tG#2%16N61f5RCrO)PyzfseNEQ)5ZMGh*X@^s`AukH}A6 za4XRbk4bqjjLf?-&_M$|XDUC@O)KFDj3HgJX<<0Ty|3aox4Qc zFul@3i)^7w5p+(zY%$Uiv~N2^d0?L>J}%RUuCgLDhkl`VOf^|teNTvO)MTBHn}W8o zG|osng1Q$|hc$9`>>(DCoEbHNikXVAlPdI%=GKhxvEKnu;X{`|6kT&UmKDH_j10?i z$UT~(zBM4+44P@XIZBuO*u9|{xV}q!q1r*l&YOdx?lhsOQ`I{g5Tb2QTfu8ks7%~d zg`H*B@7qPL1_3+1zZ3f`l-+VI^WF1d1^(pLA0K@I49)0eR>+1z$?f& z!30u~dq?XxQ|aoUHl!7*lUSkT4t`z(8pO^tVHV-lX(BFYQNkviu`0?(v6BWU$c#D3 z0`m6}TS)g7aM~)N6SQHqKBtWn5JIv)$7HEe>#(=p zZ00d#E;=pHzZjm?T8#4}Kv1_L7WOJ?((j-SvE34?nqE)`ElHq$c~FRW9ZuYtgCNw9WQ3b%?;S5cSVZ zqV-w-(TWcL%pWa`EWRp_4ryDwRJ5D5-O(g;>cNLoz_&LZdU8GI116f@G;@;I%G2BR zhO;kGF*Wde6Gv4JhC1+cwWFl?2k|CTj`#FQ1YZeKwyOIq>^7HJIf%k3qF(y44~~2D zm1tTBK)AXTRwI!^2S&0!oFDGq16LRI0dMwgjoXv{hfU-0J@%Vly?2a6kNh09aV z1wKYz6gy%B;wB2&dpA#QG?O{hd)%G`zSAP^(JwrtHWOcpo5JK}Rlv zCER48duW(xM`Fd3IF>)sc=jrlfKkf2NuIEibVHCQ*%M6jG)`f5RRgyTpW|`W@E380 zaOsospm=W-iAk^xF#KR^PzN%CZ+j&Qw+zMIi0jV^CS}XH%s)%TO|Et-0|T$p4erQz zoE8GdC^KN5&;Z=`C;A8K`kQ2dtORA$(!wyAgVd+vRI`)(cmqGvN9$6UCcGs<=EB>b zT_b7gEXeOtQ&4Y4*a=T-bjW%Qrdv2X=`d~bU}}gwABm&$g3Y3cmG0h{lyr0-+{?d* z8%4s!TZDP4@Fy^B@3=Trhb&G%s)4g$(D}Ke*s34jU5(hAU5tvhe2-8QF%xUZuhi;R zJWDU33mIJYC&-|wT$8#oXLXMTD3(qC3tL%gnqLUmK>aSw@oJZ+JU< zD=D4$ayAX3l;1MptLFT&$lkt&onKZA_gvXk2c)1!@e$%&RI-ti)tR^|X3%QuGL@p9 zg0F6OO}zD+F0WlGHaTg`XbYep*YFQZ&kLWG5R!BVmKIn{SPtb0%9F~ZG!i(`U8d$?;&}s@BMC7`l`BV4bmiMzPni+_8AEs6 zNm%GtLGiZ)c=!*TSRWy<1c1`Dza=8w6OcxEZg5Aq*3mBZM@5xlFP}M!AK3#PeF@rA zN&a-ifR$9gWL-l9z&BFEYE$-}Up9`N4NLx%MVJO@G$c%lqaayTpJ+5w@HIqhiijSX z71xMT_&mVsaXgeHM;HGwpbohst8{$42bK)^hd`Z;!8+Y%6Nq#%BgI`ctG5<6XPbb! z4VMHh$s_KR!jVj{4Wg6Tdv2X6*dv?nAdT;^iWyqk((zms`l<{G0VokA6R4}bg4EF~ zrAk)gtsj?*Xk)P%Yx0N+5;jqz!|p zJ?Nv_juTpL#0lw*eHtub?>3sSwIw1^NLM&YV#%5|U@&u2Nb?*f^UDp&0xpA?eT^p@ zg3fkGV(+WO1#!MIcL$pdG9*To3nsfuksI9x7>lV9XkV}u@HRq@z zK49MGK7?8{@+v3(jPtY_a33wo#GdZNbFtRgo=gpXjP39U(b2NL;kr3zD)HO`EW-aR zM|n6museST*GndkRVQN5<8pFL_yw`Mpr>}-1wdB8*@`B~Db3JKy;H~w+&$BnEIU?t z5}3Q8R7i2^8mNuK9w^hye~#Z^NQ`I`UVRp16*l5yg*KUaD4OULcJq|Q0NzHk>42EP z+lcrv%ILCC!!fenn=>#kY3%NUTprnw*EQx&3oxKmdyk{}CM6s9oj6ysNBt*B&>b|V zpJ2Q8If^{#I(y@U-Wc553myw}NxZ-mb#W4*9A-`A&9a}V=*%H8WBsHT#@3;Wr)yb? zkSk-pe(4u}FMytfI$_{zn zl-rARAHi26@K~d{*RF)?vmMdgC~Yjge0~sSBDThn97#W%vx*FltCom&9#S+j^jvv! z@nD30Cz_>ylmd;LVJcwbzyNJN)ZX9Ao9{H9vk^a^sD@qwQAU`ps&i_^raedwqalD7$dtdR@#D&1y z$%&7Qs($bJ4H*at`DlLJZS>$NZ-#L=c!tBtw>IPi51;$$=aIKS47O)pU<{2DBGS-K zdMN$9J3=r;pijfGg!)JW^dig3NZFomzcv+4C!~DsXG7Iqy|(qrGF_b9bE%x-M1&(B zd#mqK6L?xDgmPBN`9cAAw&N{7VY_E&XAw5Zy08e_P=X-yQg5thT{Tw2%#}1Z>4$U5 zR{XJLxC@j0+=<8kKjz*ts;*^e7se7SxVr~;cXxM9AZUQ#?(XjH?iSo7xCe*emf-Gi zSBUKFea?CBdG8qC7~c;TYxeBfRkLQVwW_+GdP>7M6Ty=jlH;~S;Z0I@p6~G+-T{mq zYoFa!Y7K@fqp67~CZqTQgUJH`oou)u3_~u*pbfj{R1>Q}&MPKK>3i)8$ksF2k^7bQ zi;8+6=khHC^Ll=3BGi(M+7=?i9B{U!Aym-1me0^q276WyU@%1vtm4GYk_YuGHZUE! zxpo?-RBj}(aygOqxbRN2Au5vT99FY@bOYuNK)$y=I_@xj@699FfraU>=O+rKI+8)pFe;;nmnm7K$+=^}a9-4N4I=>)%V3z4BK|R`V{C z*HO-waqmtShYptkxFv)gcp-L*VMKy?Fk$dz^ z%hD>Hi^wHHTcxN&-DVB&b_fZ&jbFA(M~ahWhZ0lV^0m;XPGQd#?lQMk+GItl3$n&c zi0jxI>(slnb?rs{{gkjl4V5Q`Y=m0&OZ&6CP^Q zZ&9Kx%{k2cgc8P9O$x|LVTR^2LnG9EoF081!nsbcLH~eAE%zuvQtc7`~XU5a}(`F#v1%yaDP|jrb>nYpH;aTjf zgiU?P9w&MW9V2m|(S-r~^^nF?-L?oC4#6Btw`iN~krEs~+@*T2&S73TYL>!@ibA_oDdI)>UW}^VpOu~HI z?a1rSgA<|gdCBbq|4AIbk&f%_;Th9>p=5=)3eh1LKMnW?E#uaCwyB1P;L?amNGpYV zI@*~Kv~E0Zw$GZI&RFycTY<+mVreZ|hbp)Z<%0x%7j|DN@fkFd#&Z=muQJeu;!vPh zHa%J#r)vhgSd{wC1X8_}jqt!a&?E-QnbxWVKl;F08K6BJ&Q|%Pv~%z(T7no>EU{$7 z!QbIoS$GR(X@hn^y54s0wIgr*$1$<2+-|-5g zaRuDHn>*cg0o*fHg^;P>nxYeVbtr$@_1G$743KoY3V3^^))-T?6);&@T^G(rQ z$yW$(9~kaEz{S>z1~v$3wN9o+@O|rNT6^k7dwh~Tei8!Vgn)n$?b7nHM7w`_fxT%Y z{4ZD_#_xq^erJNg0TgR`?)q2RC~;*qF;#T{7D)Wx zgMt2;L-Q=`@9O;*V4y$1J4}B7P`*QOe%Dz7ROtDQO!-l{i2V;>4?P_qImY07J)XaM zJ)>-%%Nfzr{ZT;aIgiEykOuN+*B|LLKfpBffRaDIMbXm(ph*t+|1qQH*<{~uSo0ZL z^6!8ve{cH^EBSlN|I5)|qx^XH3#{_zSik!GI``-CUm%u$mzVRu0I~dYg8YeMp{8e| zp#!A8DB2pBso?)lP!>RH69CG>h|dD38N|ZQ@*kiqKMH>Ro)Q3bi2?2RB0LtfKhPw9 zOVnZfXQIw?!>_6N3oyd|UB4d(4EPKzEC9I9zr%|#GOz(k@cdu#A_`7iv3Izm@l@); z)!QQq`2(TGbm;R5J(*PjCc`bmbcTtatospz$nKJljqrhsYQ+`D#EYGBm>yi`bfKT=W?w#s=ne_@^ zXRrkd>Ln9=AHF=fKikVfNB}4f-V^sT4qqWCL~MR=Q$B?x7`j|5=zC%ZLQpv-PgkTY zAa2@7k**CgpqG94-fyYkxWZqlDV`8VA^?G&_v-`Q9lXTp@V1TIhDOwBfdJ#fU&HXE z+?B~b?rIli$ZL=Xp2B1D`uborfR;OXT$X0Zjw3 zZGaa7cRaLpdstMr@l5kZ8kF0<3Idy&Vgh1@sXcol>}E7(itM^>>nY`b2>K#cI^mtk z8@PjmnYliJfNMM*MbatqVob6T-?k`pJU_e)y#^SL3R)Za68{Ub z#2Y$FAEYIvzE33=-U}dQYiQa~^#`b4T4Nu#A3Z&eT>V?Quf$_ARqfA*BZp%hV9vWM zm%f><1ZdTd?7$bgp7;%=lK6mXt9Ww@HuVNvPeNLME^47^yx1ns{Ib7yJsReOWCCor zD{|+)Gd$g@9ng~^qU{*IKRO;b@M*szl_&`1^bO=v1HO0${Klp@RqFd;9f;nzWT~QD z&H501$X+QLQ~9WIQL?iBv!(1Bti?N~u`lkAc0l{>k@->E`wYM(OL5k)Hgf)}x>ab6 z&Hi!^y)U1TM|@-SMKnVd4mU@n!Q~;pa#2?-yk&>LVK*v`jxnylDkGmaI!L1D1x0~8 zmq*&s*|!{8_lFp8ulp!e?GfMC@#4xKQ?aYJq}NIH<2=cSH%=bn8pd>H8=H0>u}!o+ zP<6v3K_r&bCSsVos2|3ljfuPw3UZvU)?RyGu$`HrIEzSP2R1kk)gG8flw_@;6==*+ z$)=?1NSU)RRzzl7AZj-8b|aa>Oh(t+$_k{5(m3Ld9xJ+KlDEIlKJ$}jZ7+uKVYYt_ zs|9UJa{1aO&5InZ{l<~dQ`ahky2dy)20P-gNWp6>+niUH519oS6H)aql-bfoFVq zHj)eq^e!{_wYD&naL8Yc`AxspasKQ+2?}Z^*H(q0s)%+QQWkf*)X%dXjt-RVjrG5Lb`qNbJ?P}I&jsKbkqrG8P zCw$222`Ni>3dIy~nV1?|BH}9&lk$p;nvA^V1WN5*R?3wHZauc1tSWG=-GQ$H@38e!L)&_4=$)bMsgfh=lc1(=THwgLAwH}=+;gG@99hGKwKbefp;EASJXp+_rEe*kL~!dAg=cH+Bb}=)f3YrEav|mH@Tt=>`nY(2 z{3vaHNIJ>BJEV@|3Nd?S&>@%8*HQ_WCV2*TL>9-Z1$u?fvDWPC6s$vp=Zw?og6}2{ z#hJFt3Bl4g{Pmd;*sy+xwGZ=FQ337bb_ZHFy78~hjj?ux^t#E~k_87qrPW6u-*+RF z_fF3{YgFG1r*#xu#m~Qd@Ejk?p2-_YpcXpPc4UcjqRrs6bg$mO?QPm`<<#!!y-T6A zcNU4gM^vwY*X{f$kj3b#U{u#lh>3WC*mMeYj}6*?n|sa4RXl3p#YhMNur`-z$qDl6-C9$5%wDoIlb>TAkIacm!PF~3986fSGGCqv$*YI{gX*S_MBa7nRc!j z+ZbMOgd5{|^rLHrqO*>l3gAbBN=8JBdz}w)b|@t05Y33QWYp47i)6G-MD+4@`rr{_ zqTn*>H4MZ#hm;ebU;0UYKI-Pw#Ouj6l810zoZ`2m)*D@|*i7wisD-C=5(xdT??wAi)PhY!-$E>>N}!=&<;74l#`kLbfCP{$BY z`OMm>mN85Bw1#46^N*5OEEB21U6f|+07lzLZl)VaE#9wtK>~NpGi-9k>h+cFehOQ! ze0#+ARf2^UwT!xb5!+;qmq%t|2C!IoD9@xHxCCRbIRc;p6G=5cxDEO1J0~Q!e&M)G zOCH_WMer)QhAH!7&`i#ll^K4NDVU3yVXLd3Iy?6Nwq^)}hLvdH#|t){n$Y0SbO8%< zh%ZymWY-sQfccx zK^YpFviC^Gk|y$(=a>iwVI?4Wbs0)hStkG$&<{59zn^arT<<70e1a0Len%hvwmd0_gcYxO$5x&olyHK2&^ z@BZ}kfczyuRcb)RY0K|i6MvooEMZs!+Wxi}0l3r_(DuiY!=HIK&-VDaya2fFM|jT+ zc=zYu_tx*nzk>h2pZjs<`|IzZ|JiE4jP(DIx$=)^@@LEs;Jx@6?gJk2Z!V61RtkO& z_W@Or0l7#l0Nelj%$2{gsQ`o=KT7Tz|17g>O>6sSatPBulS7^xe%;`&Sf7pk&sd-F zKap}Uu(JSE|G&oi(STUr6ss=<-d{-yagAR;NPS=9gWjfEbXA;PD0nwjD1l%sb#*}X zP&{IQk4*eNfo8u-6t_~pGq!k(Vp?AP+0NbLh5Pc(kCToqC|52@3CQ&KqHHb#rQrCVekUXS`!05GdZ8)RUj z7ckN|Qm(U4xV0QHq9yUFu_x%R6u#h^Hul%3G&0ZA`pTSyy9{!R$ZrF5FT@z6B!FLq zgd;OV!LoVF$TcANS)uh?ekbI}Ve1VMW9o`(>-R{TD(Y>H0I`MB#v zUta;cdVAaZ9+W$Y7xk9eIFu;TIN$cFU8!Bk!(ek|7#%Kd6;zF26CQ#%C(`QizUF3) z0f!-dT@0V`t#3A>XO4oEE!l=KofyKgAP87B(JrVb&#P`rb_T!R_rU0kC*Y}MO1lYe z#S|cxv?2)8NU~Yp+SV&w#X#6kXaoolK!?{jguraqIN3lApB?%miSNV2L}+g~_0JXB z1Vt+D914LtidM1^fePF{dB~_qhOBRphJfkIpF(*ON&w3#D4##oGqj+^K}8#Duh8g8 zdQ>BMRVl!q1D}km3L@VZ!O!N3&O(FOTD#y?iV1#9rCbjk#JV+Q_tswag+Jpw=g#dL zq^gHfbZRhEH}s>mfOZs_(rP?@RfD{XkigZzxM#+j@=cROr!m~yV%uO%tMG)GV21C5&PE8oeM7~XFh43Ylh7<1xDQJ0xx}IFbkuHHD;!R;G*w-$| zzLdUUZ+Q~Y$G8@duvamARmd5u1&U7Amj?}oB<8C0tX&Pw+q-L^i-2{izV5K4Th&5p zm~m3?k%T(a%<@Z4SLIEg<8W&AI2mCqzpOX5%2G^2`&`$s&&&&>@lE$j03sAkaDhaw zQcR39)5kJh!t>hWg&2;F$|SY{uOOjE?YIKw@G+hg$Bd={WUuNmg-~27oKB6dE415i z@e3isG7^? zfQ%aI8{*>H;YoI>U16u;HSYc;`m@6K2AkZscZipSd-L%hiVW2}of?Lj6Rfr_DVJM< zD8*(YjJ6y=*;c#ONs*hcR!;V|troA=>MU@K&Wqm}xk)4*E(=>>?37@t4qDvV`h}Z! z+i6G@TY$gUI9=c=pkk7hWW7ol)9!A;RW=WZs3>)^RH9Me(LhDrN{4NjqF1u`jL80& z8_=quAuJ(BS}|e1_1eIM|H=mIF6+j2$>PD#ZsUMRluFR9by_1{vbo{TerRhh@fK9h ztNZI`Aw{QgsqEbt%=N^Z8Cr}Xcb4I(CYtn}-eR(EU+2uvCfpB;8H-)V)+H-55Uplm z;FJZF%tdT0o9k20KKQ3%=lI4*ylAR9ze;y2<(^2{Vj-15(l5cZf)w1Y4?u!j;iYE3 zZwezlZ&iC;V^$jN!unZkTZ^xP5y`Q{t&B-YvsotWZsbCgkv&Ctm%3C|+jbV*7b_uG z16Ms`W{f-?49>y}#XN*_10Jsp{GSjpc3blJ95H3F&&7qiw@ScR; zHVOKs1H+Qc@~Ag2?6}ViPmZ0L>i4F#csU{3y~y92Bzl|#Ps)P`@kwnb>`HM5{Yu#1A=);TKW~oi& zUUAfu|8Z^K-NSuooe{&{X75${#Nw2xR*Dym8eXF=O!GjULjOd*PF`s&;TX zPi@Swpwhy>w8126F<3ObgVxdP9640P9x5Fb8?544a$SEkXpONo!jWObQ``jn)+Z@ z_ILU=2MR@rwfn!W;y`Xi&mM|$TxcDWI4|eF#~^JRjk|So>Qgs+yG!floXq^8*BWml zJSG|3+rwbKeF()eXrO*|wU>Vkr6{fFE15ykSc_oWhdl$;B^ddtMcC+c-C&U812jT; z(5^&`drDjD`(V-J8j|*IX4SAT@L}tFdn45(tZxZuAu1o0v};N&;i)RtTtlE(iqF-N^XkzWEn>?qV6zR5BWM*d*S6je;uc#6Y$1s$PqFdr4lg zcu6~ci2*(R36wwr^Rm)2xkazhC8ZTBqRyA9KbbUfluAqzC+riZq{O{9a&8$8|5#%i z7{lJ?hBAEW)J^~H_6*MS_TY-o6B?otH7yAqECdOqlIcA=7sb@QfEm;{k_^vCqs`?4;vch0?)^Q_wTh zFDBv96~cY1o~c=Eoab+UMJgDejcv?m-S58qd5k-_yEm8Exv&Jzk1{RUAFa6Fb_rh9 zIpT{eVdhLi@*|CngWVT#8@v735e5hP>d4Jx0kbWln0%qn^Ac`ivOEQb$adWBN}%%v z@kpBiTD0ZdyAW}EC>f{I6>^xFDzO2`G&7?GIyB=ji$(#PyuBg@Y|JNBdxuV29&{Yn zCh@Kc8e4B|jCwc~^vb4&Z1Gi7kN616UQ-knu=y`CW+wK4K)qd+$wt+F^K}#X=_6(?n8tgAl;W? zKEx}YFBK${z93c9@EO$qJgbOSWAkw9^ugH*%)vW1R_T#Xl$==PMt#KEU`z9e0)K*S}hiJ!Sr;<3~r>TB$nS9D92SM6o=CN||!caAv^_PYlfrCQ_F}AvQ<$1i#C@^O4w83G*os5np_<;(GmY zBwlm)Mb&Ijd$V{n?JP{}w}r!&8G`wlA^zxe=71*D+!xhv>lV>ZPp=ZcP@u#oQt{mf z;GI8#JRyNN5(ef>k`ZH1!`#w7mcfJkOQg#5zuqfn`tSG3pNSCv7O6_h^YaUee2-Mc z{|#@(Gu`5!k?OOoUopym9jX3@t@8gL?T9}c=10iN2;kfJ6_oye`=1%GgZx7R6U+Di z-(UY~`*G&iF%y6tgNcqEpYa(>K?m4$X8I#E{&)M~-vh@#NFCS!+yTEy9q7NG{EO7# zACutE(D)zQ;Q&IG{~R9!pbr4DN;<&8000od4%ij{_aXAn9r6EhBOEZm-Io#0d=Sbia@O!C1-6066ns1;=-beM9m71dvf%BJowjx+!w%A~Pa&*zfd* zm%4Qf(PQ2a_e4ck$3>Dzr09)6s1IsD%qK+m#>b|XKID%caTOG-WQ?87o;e>LJ@j3< zm1WG@xuNKr?N5gVGQo|r}O8_OCP_IgX8=9 z%>*bv6a230@#3T1xf}=l3n0NW=&Ts-R&-B>mzUfSFzE7p97&!9AZlFQ(7BbS@W*YQ z++ln#F$gR>`e)H9@6r)~=DdLMx#5Ys2*{B6h>_4e!FR>;1>jeh)#b#QfF2T(9D9!} zRPn{&bV5L4J^FotKST*(PP2mHdlN%+CHEe_tggMc=)bLP_==&eZOXOfa)TFh3&)!- za0zqc02a3H;14_rOce$(S=8?T`0|ki78-HDh^*b28r@Nwp)>H?S7?xLWYla5d$gSF z9kJN25Y75ud86@l-M#eW-N%o+E+%%U6k(WUkB@1@cD!Q{*p*Hh6Uaqq+f{; z{gr3uhffe}alJYPK>GtiK*X3hr*0J*3qW0zJ!8Q1?c24=`338Hkv-O&}*Zxl)UK5cJw&#P?A$c?c1 zb-*=4;OWsMegpRQiPCr!bJS8*n~um(0SroAaO2x2!WM4gWwx0;MyQb~>ETZ6OC#L* zr7+(YG5JmSg;+ccf->_>+bg(n?P#%n^)F!O^kFpwCxnF`rCoAcTv{9bCK3$LZ0VY- z(Oxe~U=RANHeBu=wz-U{!f&Y_S#Qm1;-asrCk6|yeXFkHAZBA%uTT@qqiMYua&^nq zRcZF*J=q#y2)p1ZdoQA}QU(j!4U54lYc>6TVyV+?b3rsAB3qk+!;e6vd6MUtEf zL}q4W2JXuy!zV*umaA+mr`e5b-&Im=->jUoGR!s6<=`}I=Y~|XP7g@MgV%K(!Bp-o zw3jWroy$nO`B zA`Pign$JGV2nUnfQ^H0|Wxr9k=T(X6B2Bj@FDVc@dAxDL$9h~6A&YPnOVq^c+obz~ zV@{)aQY78^&K_??6Yb)*JhX5xVS%LrBHT!DBi!%qi_0ck`)fz|MY;ZcPIkYX>})v& zds;KxX;D7HpbQIPNkLT8wRdn7RCReDoM?kH88f6`E1knNh-;LT=w6fR&uno%b>uZ+ z?$Li<)1t7m>U6SHd!1cxanW>N=Q&{(635}w*%CkIO=Mvi`gt6Kc@(;#4?=6^s1`2P`S-#aBH6%C>`)IFMlgZ zo8}>LTZSj4&WPLo_APT-%{{d;j2}cR&!b(sgvn%T&RH}%+=-~#&e70$OrfhdxAxAj zdX!aXY~yk$bv|iRrd&J(6a~Z$v=ulBCEMWK9BXS=aIfq#S@2r$W4G&>D+mWXU|Ofd zBkzWa7!y5}?A}O1SH72~Hh7!#g)(@!T#>c0_PP}(j|c768q3sy?G8)o`ic|ptqNTN zrHysbnN`Oquc~n-ok4`8D~|7VMgvk{Tw{Dmr9L26UQYY*;HY)TDjs+}c_+bTuwLV) z;gwP5V3%R{3G>_brzrColBLcimo;F+Q?rZZW*1HIaW49|`@Tn%8#(^qrnFq2N`@zR zzqu#F)F0GFj1#QFV-(=abMTJ|4^yboCaa}PFi0#>iv=fB&3%Chb~8oOb~I&Cu)Z6o z)aebkyB0x$#znXVQbMy3aW&~Iuj*ZH0MnK5EAAVjGF7=8@Mts^k5q^LKsHEjqz2KH z!Li^Q+3e54*ebRa>Vm*I!7m@ie^`CS#ObWZ0VgeIRz3xh*1ld_Bilj!Ro{%3#F@Z{ zp{+=(QERtJu*$Kj!M=|Hr9V)66_VA7m)c8V*W*FtW}DA`dM1XYk?zqIufJKz@bFXv z4T?uKT$AlU3~f#Q;F~=s3j5X@9HiT-(nbjD>qzSi&n@n+!ko)Zz=iHI$(UoF+N1fx z?cY*n)q6!lC|DED8^VLGFIze}H=$?s><%vvY)x<$`cBN1$9U&Fj;i=0W@HB(D7+`G zXR%bTr-CQ3IV)hA7Qh!VlsPtTkUDoKGVP~hhSQ*J0^o+Ley^D2d>!Ups>>~%{a%gj4TMR zos*%`anuO|af*eb^SQs|1>H__OqfHO6}h{bzm+d@aDGK6Efdo#eYD->rsvEZKP`!< zt*lB?AzkEzHnZ=>v^UUP`>#DQJ1gjhs2Xna@{HT^ALhu@X> zOy%8+1Md0)4N*6eMtz>CL5$X=*PYPBlT&9&)wqPh+EUw8<|N3}+kSonE2>Zqnp&@D zVNzFQoV0>3HJ{1LBZk$jZ)b@s;BiB76Dai zbT8HTB_jE#Hm?&2Z9u>MiW$+!l$x-M@kiOze9uGV)Eu*spz^hTp)a)ao&$ zrvY172XCVLMo(T+X;QPpj`7K)DlomToBgb8 zr6qm0Og0=73RhS#L|D>0i^##i^g8M4az=8m@5H^*e46Aut~O%m$||x(HTzAR%54pX3-h1BB{BHTX|6?ci&}W> zH7N~PW)RGyAhqpVe5GmlMt)H!N*s9xb)Ww$_A?d_jI?U1^iVlijOaGAQe^F_7H`8*wVdRIuH!$(V^rh%+#pXvM(Mx z{2RV-xjNactxlDtgHP}IpX*G7A3Wwe9yQA67sRbM){wUZBYbtI9{eg?;Cj8!`B6kY zCxEy+%aC>|I95m`&^9aCFoAN_L|sJ!{$v_5^lWW_Cm|IjDBDbW@@0`d*8Xg;6s1*^{8Qz(F|HWo~JF$Q+0>v_#j7~~S-%E1@G?N*~E)^vO4 zRO?aK>n%m-z}m`NeO-Cv(o2_lk4h$OCO?Pq$>v~8K`-2HXKTtTjigk^H7{f9SL}YrCsLawoEz z*dc=q;2Ntz;vAH1bBRbwb;{Vm;w`j^MLt8dh;X6qRz$o({e%>yMM~^iD17!V8x-N2 z6f|{rk-Dg~7s^7*qC)Y4`ddCm8{j_rj+KpyetyA7^X%Dr5hd)!Q8Ub(VC}F-M@Hi8 zaSPO;!mZOeF>TCCRJ}B*qYB$6ct%@N*s{K;Hc@HV@jJTaqYH1vVM?0pj)HaVtIzK@ zI&8=>OYc)J`oz1%8M`aXq7Jx~!-?Qiia5(5sRvo3#}}+cuOFH!#;?XCJy8-JnU`1H z^m!qPR_4n;x{S7r<{QOboAt>0jW!moOwd(maWva0v40I+XDogveYH2;C<#XZ8R=iM z^)jdbX$|}au$)2)1@FqwmByd5`jscr1Nf*8&Glc`Q~uof|93Iq&j1pifq{+g`<}dw zEr3kZ49YRJ6?4&iqxa&CHvc(^wY41;kBOFawl0&&^OdS<49y8Uc*OLj|Fet-MU zaGa5$SXoOaYUkkQaFR_s?3r^X1=Lejag@-cjI#71LK#Yl%HoSMmg6G}1Q7}8+)0=g zsr?xNxk*T1*(Rc}_bC1pnHcca<1jv?<+Z?1_tqyTv(+VPf^3S_O)YOKWun8y)rA{| zQa(jYpMK3QZY+*(hUTkpsc(-!L$N5{de`bN&HpYBZtvJd4~-neKIG)uy_G{tiB~yc zg{G}3v=pjSd`MaIorpFlG;il6jM&A2H{zGNCXOy>5&;Q$GqmJHlBe6s>#KF}Qi_Pv zH(k)c#rmZqek&Cg)O~vo3qe&H384<5Ou<7EptT}FpD!UgnEmUpfl2u^ZOqE}8{dg3 zX&6tw2eNtfa4}zP)llP+Dt(!r7twBx@G=Wh6@+O+)*VD8N~z!ECXaiX6RVBizRDj7 zyHE?f=jHgsw|c?cm`V+B31+=q#b6h2ZG2RIr3~Opvt^+(s!jAx%ogF5aiZl}(u;vUTC#Wr}wDuC)_ zh7>gJ*M37Z#;AnvT$eTOh2$?`aKlCKbGAY|$|N+vr3!<9iD*0Mn*Ri$T+Nl^AtSz6 zn{I&T8E}ys+(@hhVvgMqTvD!KEuk#UF2;!zw6+^0=4u^vjq23VYU9O;mlGpJF3|x* z_%7HK!g>56CL|mz@AFaGVvzj}OcHpV-?S%j-n4+SvY8~9*;MSr2VGS{>S6=ucp(VL z7oa&5FpG9VbR#0(GL)?w?v{_+erh=R-a=4hJp06bc0d$K;vj-`k*^y1lWuU0tyzn# z73WG#Y9ZFvn9PToUfPu2l9Ki?bKH2Q!%bWsb`V6`RHO&qonce%LI#JgsM&wX5Zx3_ zAKbN)<-u{0*Ku*cO7B`W-`8B=nU5!CLVuwel?kIi}F(udqVQQNuFwIfR&crvP>yPaQy05zmtL z`o&t<5YS%hRm_DI1DafBkJR)@z*D-i_#&NxDehUD3k&qP1@$bjE}lyGp?-$RT4f19&diRqxFS9k+ri7{m_+)HT>K3hbo#4&q;fgJyQd% zA8MU}G^|_Ca!9HC;tC9+V_2wM!E##A*?d3nWu!`HrnveCfff90I5IaO@h4U;e%v)(KaiEvb&R8m`rs zHt3zZV^7L6K@I%Sc720Zk3b0QIYU(za0k6n)_Z;HmE6>fnDy2-n86h^8vGr7A{AWA z7XiaJ(;u%y`&3;=_w9r-oZebzu%LpLvb+~b$X6K>dASjmj-Mwo*j3@wz&Q*AsqHJF;(aDnG-%n1~@n z@aR-%F}K`RIO(lHJ&WF+euY46N4P0{>3!^le3R?jS(cHUB#HD$dN;`+?Zce2*G=N* zBg~{>Vl*~y_vz&X)Jpm|S&uLrU(srs5P90zY{rhVzM;$Dsc41y`p*>8SJxA0P*?$es9=%vx{t7v>amV z!)2hiO-Pp=Us18F&wTCtY+>O3cvN?@2+T`np)Su9lsq`ryEhB7x-!tNFc8dbiE6@V z{4rBE4-hnr4V2bZcNqe$F1FvOy*o$k!zczx#ikBk;Yw{W?YQ(fO(h_?s#tYq&bP#3 zGEq9o16Q>PVKoLcDrU5~aCFNh#k3y1V!czwvZ|v%e#AZ4QHmPv>v+Oq%pzi zhe(#aXwMG91G>#6S_~LDFvlj^?@|wHSTo+eh+sVP-wljD|8&-SKI=f@ghoG4___LH zGIL9$d$WkcTH@IoM`;szA^}6pmcmy!mgcnh9GFEyxFLG9UA-aKRc?{qac)&ial=0cS3Y7$|wC_9j5QwAHP=Ge{Au{y)!a^qUAR?x3IOr*TiRfW?%oly02hhV_|2l zXJCU5SoVL0OG+E)8^05_&)^ih}T-Fce z^lSmgjI69QEUbWvXRM4&H0+FYOn`kBHX0^+Rsab#6Eh9#&(u9dJ6&5RO8^JDl(D%f z;AZjv5UOWuY+(+-2;$Q!D*&VbUhv5bjXxN07@O-GTN~)vY8wOC*WcM%Skt_>HTyvR z-HrSU-T7>qUk3fY>GC|Z2pc{CKly9{5f&DFhTre$0iNiub~b?aKi@Mm0rEMY-vdUb zm9w_cQ#AN~d$e*wBKWjQ29CCXd;UY{cVqq*YW(3lJ3Ot(2LMaFkb$0sKHzcw*f+ta zXJcdjo7;P!A!&id3g338x?dC-L)Gd^lZ46*W){3Xp6%s@JDC}`8Mo1O$`OBRGV!#m z-o~`FHE6BNDNF$t6~DA*`8M^2?Q{=RL+LmIwH7~{p}Me^Ktfz&I00PQ3hK!tkV$}y zFt_+!q?4wE3PKq&rNr>&z)9zX;u~~bWW`S>>-dMcWJPgBAsaD1XrDH}!8=MN*FHGw z@qU^5^iDoF7%j%w@i-UyYD*OD(sWskP+kfxKg)9R6Z1H#8OljtbLA zPI##DCw+e*&4Ahx`}yWNI4e`#)Qr~beadfOt$lR zeMgpYQ4vw4$0p2S*s0#4_Ko4AN=O7nMLR`22D2Xatfl6yOU=Gx2?oxPxtb}eN^N=( zp4lpfR=OV<5GQT3-u7iShmY$DF(V)-JObr*w@87ErN~godc5(JL#I(D5?{45HBDPU zsAK2Irylw|bcc3);kAShT=3el+7Ou}9TQtPA~_1&%YyV(ajY-^T4=L$xinda<>+|J zfG)xzI1ftbGg%!LYl(6USSaJbIoFp`X;!B=h9s9K=jAhWNN8luWswJn%pz?W&@q`e zrddZ3dMfL+uZvMj3!S7tGIiyZA5Kpfc{qkgtL4(3fTZ+9i(#BT#Coy|GO{VY_n)Pw!}{)2MX=J`x&Rd0kY& zdMrV<7tlf!q%5cw#=J2|am7G>h~5`i$WVzNP>@nc?#zkZ_7hbI7cmz4M?5&=>s7^; zC~YzI<~Rn-*NZ!GJ?_wO^vB;E=OzuGTzgW@XCk3cuY$2xcZ0uckhpS)VPtX&2lGIK zz@1x@M-PWQwj1s&TIH|sKrEK>m2lB=MAbGRvgJ~sr^G5!&?jV8@YB1&Y&_qm*mk~l z=0Z*Z+1#j|r?AHe^haD979b(f0w(+_etup#4m??j2|sa8$W>c2ig$cECLPxwXQqr$ zOc3BJal@l2YpVMSDXJe;w0VT13%iM5MB1HF%sTip3|~XeSrU>q(p&yX7*5_nXtE&0 zeq@^RvzJ+^eECN{X>rUUbw)X$g(K{UWm26<;2J#w`sz~dTAO~wDD=rE4W9*@_t#kF znGkSr(W4Gt4KPt8aTZ}ygaW*sAQEiqNHlm|N;q*=F?k3KFA|z@+yO1WxEkr64xxaE zgi&k8SS;BuUZyKT-0&{oJIz)yQ1p=()VfRgh17#|0eb>VhRd%#51=YOUZo^A+w53> zU^ylyiYx!78G6sqM0R}G_`cMZTO?y-^}xE4++SmUI9+fhczj{J@Nk?lbYkizv?{W- zNpzSDHc@T7tY?pGac-PAv$bo&j{>YQJ{Hy(#t!&tF4ss_$NI3 zU7n+Iu4N9`Y_Ze5!$zmGcl7Jh*v(WYtkTpdw3LoKdymGBYJ_;DePLUHyj`~qIOEQF z!VW2Gped_u0|OnrF7VsSy)mlci6_Z3wMMjXR%Y&3;V7v2YyZI^y5nk|hOvx4Puya=* z^Vv&Rzj9~ZLt7+PPV%Nb>Q5p(&F_e`ReT{g{b?b|Rz_FE;wD7g-rM3)yP}Ks9b(;F zP4_?1K1eUm$pV*p3*>fC-DQAW^1fIal?C>ZnHzD3n(LX2&j1O1EhWG(Lh!_=NSFgqbIB*=m} z#Y0~sTA^5BSfN%Oj0_^0XEo{soRb4Iz2GQ>1UT}z~*CC%Vv zAaDgcN>EIhx8y-Cop|X-e(OVkgUrX}5zh!}6ur&(fV9R-7_}&7*i$fs*={h0 zuxCF$sS7_Ed_U!E8Rn2HlcZE|SK#=RiRZ&<`VutkE!l>p?Gi%(l0qtrtiN;?f&%9> zW!_L>K)j)i#Y{2%80F;)4%LO7f1PH3;)8xnGg&*^560#OHs5hE);6~I%s&7(&lD>F zuO09>pIvji?|%B9ZsqrGzaF%bvF!%~e1LQR+?gN$88`*F?C0cV{w@`8DD&Mn{Watd zX@J^9&!@f^e5zDuM2o4D^|e-}q4Yj0p}Z)^Zy%K+Tn_m*d2zcc}O=Asr# z76613KAFYOo-}mNe)zBMe~Tra6@SKD0rca?XZaC%{8Mo`YXke=hWV-ZPuKieah9Jq z_-_<{9{X8w1p`9^K)9o4@LTg|Y5z`h>t9{}t~$%#z9fFA{_|@9p!!etn_o8n`Q)B$ z{!_odKKB5C)=zU~C@FKh5;hF25A}sqwR!e$Kx? z%=G76`BUaktNmT>^X31^AguqGSwH3eFvyP&!C!KpJO3K#Pr1MBL;c%6|4`x283F+L z0fK4PA2Z~S!GAsb?}n5#*8d*Jvp!Frzr~HuO}})Id1nR)?KSbqg#J%wSKHgR4TQh@ zSMW%blFf~kYgG4+S-BbEbD&#o}(36;>k@qp&!b}Jl>JK zBTvVOx4Axlx39PRGbEv=$re*61`4@9xd4eo$kR_ngF^0JF67_x44~M)G9UYLhD1

TCeR_YFe45^j7!yrd$&4y%A2`hbwi zo7Lx4j?MI^YTB>c4-Vuxyr1M(6eG!F_x$SjKcEv5e`ku=NYFA^q?cdce)=?25#rjX zMzT6mi2*sjkd!LoW-CtKw`gMijpW4aA@0^DsV%%K&b@Ejr?{Uc&zjojJ~DDT1!*nR zi80Tb{Qs#3Rz5y!zCyeWdBR3`lcW#u{t9(}e>kNvG0Cbz6p#0tbhpoYY|6uF@>1cl z+gvEzSIA3+8<{hwwDcAMIWBvtZ{J4!7f|i zk!0yBcr~27uW-G6yjy24R>NQ|!s5qydU3m7ZnoHS>%UiX@d7ypm-Xizz8pU|Thn%b z5|o1Uelz{E+m28Vk?g;)5s4}O|B@1eQfqJO%jQblt@cZSzrSy`AP_h8^+)WMsD^Oz z{Pr3l;_1zN(V*tJmPXeCo;&>KW-ex5#M`%fYwx+E}AGXOK%kg=E#pLuz=e&3oJ!)X9xAHQgl~lfq7i7Sz>{foMAoOkAa0? zh$YQ*$YSX)$Im7|Qjbom%Jy)eRbURP!7)At&eAOw!}gp-lF<@#Fy#^p3dw{E+FzFGLxUU} zsTbLNz&x1VdyEz15i~L-7qSG+^xg*;4XbCE4SJkymSgXO24=|H)tXX$;o zz(&R|jf`J{Rx;X(t&<*K0J1qxVMM;j?GkHokH>yn + void f(Dereferenceable p) + { + *what-goes-here?* value = \*p; + ... + } + + +``pointee`` +----------- + +It turns out to be impossible to come up with a fully-general +algorithm to do determine *what-goes-here* directly, but it is +possible to require that ``pointee::type`` is +correct. Naturally, ``pointee`` has the same difficulty: it can't +determine the appropriate ``::type`` reliably for all +``Dereferenceable``\ s, but it makes very good guesses (it works +for all pointers, standard and boost smart pointers, and +iterators), and when it guesses wrongly, it can be specialized as +necessary:: + + namespace boost + { + template + struct pointee > + { + typedef T type; + }; + } + +``indirect_reference`` +---------------------- + +``indirect_reference::type`` is rather more specialized than +``pointee``, and is meant to be used to forward the result of +dereferencing an object of its argument type. Most dereferenceable +types just return a reference to their pointee, but some return +proxy references or return the pointee by value. When that +information is needed, call on ``indirect_reference``. + +Both of these templates are essential to the correct functioning of +|indirect_iterator|_. + +.. |indirect_iterator| replace:: ``indirect_iterator`` +.. _indirect_iterator: indirect_iterator.html + +Reference +========= + +``pointee`` +----------- + +.. include:: pointee_ref.rst + +``indirect_reference`` +---------------------- + +.. include:: indirect_reference_ref.rst + diff --git a/libs/iterator/doc/pointee_ref.rst b/libs/iterator/doc/pointee_ref.rst new file mode 100644 index 00000000..19aed249 --- /dev/null +++ b/libs/iterator/doc/pointee_ref.rst @@ -0,0 +1,38 @@ +.. Copyright David Abrahams 2004. Use, modification and distribution is +.. subject to 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) + +:: + + template + struct pointee + { + typedef /* see below */ type; + }; + +:Requires: For an object ``x`` of type ``Dereferenceable``, ``*x`` + is well-formed. If ``++x`` is ill-formed it shall neither be + ambiguous nor shall it violate access control, and + ``Dereferenceable::element_type`` shall be an accessible type. + Otherwise ``iterator_traits::value_type`` shall + be well formed. [Note: These requirements need not apply to + explicit or partial specializations of ``pointee``] + +``type`` is determined according to the following algorithm, where +``x`` is an object of type ``Dereferenceable``:: + + if ( ++x is ill-formed ) + { + return ``Dereferenceable::element_type`` + } + else if (``*x`` is a mutable reference to + std::iterator_traits::value_type) + { + return iterator_traits::value_type + } + else + { + return iterator_traits::value_type const + } + + \ No newline at end of file diff --git a/libs/iterator/doc/quickbook/adaptor.qbk b/libs/iterator/doc/quickbook/adaptor.qbk new file mode 100644 index 00000000..849b2a09 --- /dev/null +++ b/libs/iterator/doc/quickbook/adaptor.qbk @@ -0,0 +1,332 @@ +[section:adaptor Iterator Adaptor] + +The `iterator_adaptor` class template adapts some `Base` [#base]_ +type to create a new iterator. Instantiations of `iterator_adaptor` +are derived from a corresponding instantiation of `iterator_facade` +and implement the core behaviors in terms of the `Base` type. In +essence, `iterator_adaptor` merely forwards all operations to an +instance of the `Base` type, which it stores as a member. + +.. [#base] The term "Base" here does not refer to a base class and is + not meant to imply the use of derivation. We have followed the lead + of the standard library, which provides a base() function to access + the underlying iterator object of a `reverse_iterator` adaptor. + +The user of `iterator_adaptor` creates a class derived from an +instantiation of `iterator_adaptor` and then selectively +redefines some of the core member functions described in the +`iterator_facade` core requirements table. The `Base` type need +not meet the full requirements for an iterator; it need only +support the operations used by the core interface functions of +`iterator_adaptor` that have not been redefined in the user's +derived class. + +Several of the template parameters of `iterator_adaptor` default +to `use_default`. This allows the +user to make use of a default parameter even when she wants to +specify a parameter later in the parameter list. Also, the +defaults for the corresponding associated types are somewhat +complicated, so metaprogramming is required to compute them, and +`use_default` can help to simplify the implementation. Finally, +the identity of the `use_default` type is not left unspecified +because specification helps to highlight that the `Reference` +template parameter may not always be identical to the iterator's +`reference` type, and will keep users from making mistakes based on +that assumption. + +[section:adaptor_reference Reference] + +[h2 Synopsis] + + template < + class Derived + , class Base + , class Value = use_default + , class CategoryOrTraversal = use_default + , class Reference = use_default + , class Difference = use_default + > + class iterator_adaptor + : public iterator_facade // see details + { + friend class iterator_core_access; + public: + iterator_adaptor(); + explicit iterator_adaptor(Base const& iter); + typedef Base base_type; + Base const& base() const; + protected: + typedef iterator_adaptor iterator_adaptor\_; + Base const& base_reference() const; + Base& base_reference(); + private: // Core iterator interface for iterator_facade. + typename iterator_adaptor::reference dereference() const; + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor const& x) const; + + void advance(typename iterator_adaptor::difference_type n); + void increment(); + void decrement(); + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename iterator_adaptor::difference_type distance_to( + iterator_adaptor const& y) const; + + private: + Base m_iterator; // exposition only + }; + +__ base_parameters_ + +.. _requirements: + +[h2 Requirements] + +`static_cast(iterator_adaptor*)` shall be well-formed. +The `Base` argument shall be Assignable and Copy Constructible. + + +.. _base_parameters: + +[h2 Base Class Parameters] + +The *V'*, *C'*, *R'*, and *D'* parameters of the `iterator_facade` +used as a base class in the summary of `iterator_adaptor` +above are defined as follows: + +[pre + *V'* = if (Value is use_default) + return iterator_traits::value_type + else + return Value + + *C'* = if (CategoryOrTraversal is use_default) + return iterator_traversal::type + else + return CategoryOrTraversal + + *R'* = if (Reference is use_default) + if (Value is use_default) + return iterator_traits::reference + else + return Value& + else + return Reference + + *D'* = if (Difference is use_default) + return iterator_traits::difference_type + else + return Difference +] + +[h2 Operations] + +[h3 Public] + + + iterator_adaptor(); + +[*Requires:] The `Base` type must be Default Constructible.[br] +[*Returns:] An instance of `iterator_adaptor` with + `m_iterator` default constructed. + + + explicit iterator_adaptor(Base const& iter); + +[*Returns:] An instance of `iterator_adaptor` with + `m_iterator` copy constructed from `iter`. + + Base const& base() const; + +[*Returns:] `m_iterator` + + +[h3 Protected] + + Base const& base_reference() const; + +[*Returns:] A const reference to `m_iterator`. + + + Base& base_reference(); + +[*Returns:] A non-const reference to `m_iterator`. + +[h3 Private] + + typename iterator_adaptor::reference dereference() const; + +[*Returns:] `*m_iterator` + + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor const& x) const; + +[*Returns:] `m_iterator == x.base()` + + + void advance(typename iterator_adaptor::difference_type n); + +[*Effects:] `m_iterator += n;` + + void increment(); + +[*Effects:] `++m_iterator;` + + void decrement(); + +[*Effects:] `--m_iterator;` + + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename iterator_adaptor::difference_type distance_to( + iterator_adaptor const& y) const; + +[*Returns:] `y.base() - m_iterator` + +[endsect] + +[section:adaptor_tutorial Tutorial] + +In this section we'll further refine the `node_iter` class +template we developed in the |fac_tut|_. If you haven't already +read that material, you should go back now and check it out because +we're going to pick up right where it left off. + +.. |fac_tut| replace:: `iterator_facade` tutorial +.. _fac_tut: iterator_facade.html#tutorial-example + +[blurb [*`node_base*` really *is* an iterator][br][br] + It's not really a very interesting iterator, since `node_base` + is an abstract class: a pointer to a `node_base` just points + at some base subobject of an instance of some other class, and + incrementing a `node_base*` moves it past this base subobject + to who-knows-where? The most we can do with that incremented + position is to compare another `node_base*` to it. In other + words, the original iterator traverses a one-element array. +] + +You probably didn't think of it this way, but the `node_base*` +object that underlies `node_iterator` is itself an iterator, +just like all other pointers. If we examine that pointer closely +from an iterator perspective, we can see that it has much in common +with the `node_iterator` we're building. First, they share most +of the same associated types (`value_type`, `reference`, +`pointer`, and `difference_type`). Second, even some of the +core functionality is the same: `operator*` and `operator==` on +the `node_iterator` return the result of invoking the same +operations on the underlying pointer, via the `node_iterator`\ 's +|dereference_and_equal|_). The only real behavioral difference +between `node_base*` and `node_iterator` can be observed when +they are incremented: `node_iterator` follows the +`m_next` pointer, while `node_base*` just applies an address offset. + +.. |dereference_and_equal| replace:: `dereference` and `equal` member functions +.. _dereference_and_equal: iterator_facade.html#implementing-the-core-operations + +It turns out that the pattern of building an iterator on another +iterator-like type (the `Base` [#base]_ type) while modifying +just a few aspects of the underlying type's behavior is an +extremely common one, and it's the pattern addressed by +`iterator_adaptor`. Using `iterator_adaptor` is very much like +using `iterator_facade`, but because iterator_adaptor tries to +mimic as much of the `Base` type's behavior as possible, we +neither have to supply a `Value` argument, nor implement any core +behaviors other than `increment`. The implementation of +`node_iter` is thus reduced to: + + template + class node_iter + : public boost::iterator_adaptor< + node_iter // Derived + , Value* // Base + , boost::use_default // Value + , boost::forward_traversal_tag // CategoryOrTraversal + > + { + private: + struct enabler {}; // a private type avoids misuse + + public: + node_iter() + : node_iter::iterator_adaptor_(0) {} + + explicit node_iter(Value* p) + : node_iter::iterator_adaptor_(p) {} + + template + node_iter( + node_iter const& other + , typename boost::enable_if< + boost::is_convertible + , enabler + >::type = enabler() + ) + : node_iter::iterator_adaptor_(other.base()) {} + + private: + friend class boost::iterator_core_access; + void increment() { this->base_reference() = this->base()->next(); } + }; + +Note the use of `node_iter::iterator_adaptor_` here: because +`iterator_adaptor` defines a nested `iterator_adaptor_` type +that refers to itself, that gives us a convenient way to refer to +the complicated base class type of `node_iter`. [Note: +this technique is known not to work with Borland C++ 5.6.4 and +Metrowerks CodeWarrior versions prior to 9.0] + +You can see an example program that exercises this version of the +node iterators +[example_link node_iterator3.cpp..here]. + + +In the case of `node_iter`, it's not very compelling to pass +`boost::use_default` as `iterator_adaptor` 's `Value` +argument; we could have just passed `node_iter` 's `Value` +along to `iterator_adaptor`, and that'd even be shorter! Most +iterator class templates built with `iterator_adaptor` are +parameterized on another iterator type, rather than on its +`value_type`. For example, `boost::reverse_iterator` takes an +iterator type argument and reverses its direction of traversal, +since the original iterator and the reversed one have all the same +associated types, `iterator_adaptor` 's delegation of default +types to its `Base` saves the implementor of +`boost::reverse_iterator` from writing: + + std::iterator_traits::*some-associated-type* + +at least four times. + +We urge you to review the documentation and implementations of +|reverse_iterator|_ and the other Boost `specialized iterator +adaptors`__ to get an idea of the sorts of things you can do with +`iterator_adaptor`. In particular, have a look at +|transform_iterator|_, which is perhaps the most straightforward +adaptor, and also |counting_iterator|_, which demonstrates that +`iterator_adaptor`\ 's `Base` type needn't be an iterator. + +.. |reverse_iterator| replace:: `reverse_iterator` +.. _reverse_iterator: reverse_iterator.html + +.. |counting_iterator| replace:: `counting_iterator` +.. _counting_iterator: counting_iterator.html + +.. |transform_iterator| replace:: `transform_iterator` +.. _transform_iterator: transform_iterator.html + +__ index.html#specialized-adaptors + + +[endsect] + +[endsect] diff --git a/libs/iterator/doc/quickbook/algorithms.qbk b/libs/iterator/doc/quickbook/algorithms.qbk new file mode 100644 index 00000000..09041238 --- /dev/null +++ b/libs/iterator/doc/quickbook/algorithms.qbk @@ -0,0 +1,149 @@ +[section:algorithms Algorithms] + +[section:advance Function template `advance()`] + +The `boost::iterators::advance` function template is an adapted version of `std::advance` for the Boost iterator [link iterator.concepts.traversal traversal concepts]. + +[heading Header] + + + +[heading Synopsis] + + template + constexpr void advance(Iterator& it, Distance n); + + +[heading Description] + +Moves `it` forward by `n` increments (or backward by `|n|` decrements if `n` is negative). + +[heading Requirements] + +`Iterator` should model Incrementable Iterator. + +[heading Preconditions] + +Let `it`[sub `i`] be the iterator obtained by incrementing (or decrementing if `n` is negative) `it` by `i`. All the iterators `it`[sub `i`] for `i` = 0, 1, 2, ..., `|n|` should be valid. + +If `Iterator` does not model [link iterator.concepts.traversal.bidirectional Bidirectional Traversal Iterator], `n` should be non-negative. + +[heading Complexity] + +If `Iterator` models [link iterator.concepts.traversal.random_access Random Access Traversal Iterator], it takes constant time; otherwise it takes linear time. + +[heading Notes] + +* This function is not a customization point and is protected against being found by argument-dependent lookup (ADL). +* This function is `constexpr` only in C++14 or later. + +[heading Acknowledgements] + +Contributed by Michel Morin. + +[endsect] + +[section:distance Function template `distance()`] + +The `boost::iterators::distance` function template is an adapted version of `std::distance` for the Boost iterator [link iterator.concepts.traversal traversal concepts]. + +[heading Header] + + + +[heading Synopsis] + + template + constexpr typename iterator_difference::type + distance(Iterator first, Iterator last); + +[heading Description] + +Computes the (signed) distance from `first` to `last`. + +[heading Requirements] + +`Iterator` should model [link iterator.concepts.traversal.single_pass Single Pass Iterator]. + +[heading Preconditions] + +If `Iterator` models [link iterator.concepts.traversal.random_access Random Access Traversal Iterator], `[first, last)` or `[last, first)` should be valid; otherwise `[first, last)` should be valid. + +[heading Complexity] + +If `Iterator` models [link iterator.concepts.traversal.random_access Random Access Traversal Iterator], it takes constant time; otherwise it takes linear time. + +[heading Notes] + +* This function is not a customization point and is protected against being found by argument-dependent lookup (ADL). +* This function is `constexpr` only in C++14 or later. + +[heading Acknowledgements] + +Contributed by Michel Morin. + +[endsect] + +[section:next_prior Function templates `next()` and `prior()`] + +Certain data types, such as the C++ Standard Library's forward and bidirectional iterators, do not provide addition and subtraction via `operator+()` or `operator-()`. This means that non-modifying computation of the next or prior value requires a temporary, even though `operator++()` or `operator--()` is provided. It also means that writing code like `itr+1` inside a template restricts the iterator category to random access iterators. + +The `next()` and `prior()` functions defined in `boost/next_prior.hpp` provide a simple way around these problems. + +[heading Synopsis] + + template + T next(T x) + { + return ++x; + } + + template + T next(T x, Distance n) + { + std::advance(x, n); + return x; + } + + template + T prior(T x) + { + return --x; + } + + template + T prior(T x, Distance n) + { + std::advance(x, -n); + return x; + } + +[note Function implementations above are given for exposition only. The actual implementation has the same effect for iterators, but has different properties, as documented later.] + +[heading Usage] + +Usage is simple: + + const std::list::iterator p = get_some_iterator(); + const std::list::iterator prev = boost::prior(p); + const std::list::iterator next = boost::next(prev, 2); + +The distance from the given iterator should be supplied as an absolute value. For example, the iterator four iterators prior to the given iterator `p` may be obtained by `prior(p, 4)`. + +With C++11, the Standard Library provides `std::next()` and `std::prev()` function templates, which serve the same purpose. However, there are advantages to `boost::next()` and `boost::prior()`. + +First, `boost::next()` and `boost::prior()` are compatible not only with iterators but with any type that provides arithmetic operators `operator++()`, `operator--()`, `operator+()`, `operator-()`, `operator+=()` or `operator-=()`. For example, this is possible: + + int x = 10; + int y = boost::next(x, 5); + assert(y == 15); + +Second, `boost::next()` and `boost::prior()` use [link iterator.concepts.traversal traversal categories] to select the most efficient implementation. For some kinds of iterators, such as [link iterator.specialized.transform transform iterators], the standard iterator category does not reflect the traversal category correctly and therefore `std::next()` and `std::prev()` will fall back to linear complexity. + +[heading Acknowledgements] + +Contributed by [@http://www.boost.org/people/dave_abrahams.htm Dave Abrahams]. Two-argument versions by Daniel Walker. + +[endsect] + +[endsect] diff --git a/libs/iterator/doc/quickbook/archetypes.qbk b/libs/iterator/doc/quickbook/archetypes.qbk new file mode 100644 index 00000000..bbd3ea12 --- /dev/null +++ b/libs/iterator/doc/quickbook/archetypes.qbk @@ -0,0 +1,158 @@ +[section:archetypes Iterator Archetypes] + +The `iterator_archetype` class constructs a minimal implementation of +one of the iterator access concepts and one of the iterator traversal concepts. +This is used for doing a compile-time check to see if a the type requirements +of a template are really enough to cover the implementation of the template. +For further information see the documentation for the |concepts|_ library. + +[h2 Synopsis] + + namespace iterator_archetypes + { + // Access categories + + typedef /*implementation defined*/ readable_iterator_t; + typedef /*implementation defined*/ writable_iterator_t; + typedef /*implementation defined*/ readable_writable_iterator_t; + typedef /*implementation defined*/ readable_lvalue_iterator_t; + typedef /*implementation defined*/ writable_lvalue_iterator_t; + + } + + template < + class Value + , class AccessCategory + , class TraversalCategory + > + class iterator_archetype + { + typedef /* see below */ value_type; + typedef /* see below */ reference; + typedef /* see below */ pointer; + typedef /* see below */ difference_type; + typedef /* see below */ iterator_category; + }; + +[h3 Access Category Tags] + +The access category types provided correspond to the following +standard iterator access concept combinations: + + readable_iterator_t := + + Readable Iterator + + writable_iterator_t := + + Writeable Iterator + + readable_writable_iterator_t := + + Readable Iterator & Writeable Iterator & Swappable Iterator + + readable_lvalue_iterator_t := + + Readable Iterator & Lvalue Iterator + + writeable_lvalue_iterator_t := + + Readable Iterator & Writeable Iterator & Swappable Iterator & Lvalue Iterator + +[h3 Traits] + +The nested trait types are defined as follows: + + + if (AccessCategory == readable_iterator_t) + + value_type = Value + reference = Value + pointer = Value* + + else if (AccessCategory == writable_iterator_t) + + value_type = void + reference = void + pointer = void + + else if (AccessCategory == readable_writable_iterator_t) + + value_type = Value + + reference := + + A type X that is convertible to Value for which the following + expression is valid. Given an object x of type X and v of type + Value. + + x = v + + pointer = Value* + + else if (AccessCategory == readable_lvalue_iterator_t) + + value_type = Value + reference = Value const& + pointer = Value const* + + else if (AccessCategory == writable_lvalue_iterator_t) + + value_type = Value + reference = Value& + pointer = Value* + + if ( TraversalCategory is convertible to forward_traversal_tag ) + + difference_type := ptrdiff_t + + else + + difference_type := unspecified type + + + iterator_category := + + A type X satisfying the following two constraints: + + 1. X is convertible to X1, and not to any more-derived + type, where X1 is defined by: + + if (reference is a reference type + && TraversalCategory is convertible to forward_traversal_tag) + { + if (TraversalCategory is convertible to random_access_traversal_tag) + X1 = random_access_iterator_tag + else if (TraversalCategory is convertible to bidirectional_traversal_tag) + X1 = bidirectional_iterator_tag + else + X1 = forward_iterator_tag + } + else + { + if (TraversalCategory is convertible to single_pass_traversal_tag + && reference != void) + X1 = input_iterator_tag + else + X1 = output_iterator_tag + } + + 2. X is convertible to TraversalCategory + + +[h2 Requirements] + +The `AccessCategory` argument must be one of the predefined access +category tags. The `TraversalCategory` must be one of the standard +traversal tags. The `Value` type must satisfy the requirements of +the iterator concept specified by `AccessCategory` and +`TraversalCategory` as implied by the nested traits types. + +[h2 Concepts] + +`iterator_archetype` models the iterator concepts specified by the +`AccessCategory` and `TraversalCategory` +arguments. `iterator_archetype` does not model any other access +concepts or any more derived traversal concepts. + +[endsect] diff --git a/libs/iterator/doc/quickbook/concept_checking.qbk b/libs/iterator/doc/quickbook/concept_checking.qbk new file mode 100644 index 00000000..97ee7bbf --- /dev/null +++ b/libs/iterator/doc/quickbook/concept_checking.qbk @@ -0,0 +1,54 @@ +[section:concept_checking Concept Checking] + +The iterator concept checking classes provide a mechanism for a +template to report better error messages when a user instantiates the +template with a type that does not meet the requirements of the +template. For an introduction to using concept checking classes, see +the documentation for the _concept_check_ library. + +[h2 `iterator_concepts.hpp` Synopsis] + + namespace boost_concepts { + + // Iterator Access Concepts + + template + class ReadableIteratorConcept; + + template < + typename Iterator + , typename ValueType = std::iterator_traits::value_type + > + class WritableIteratorConcept; + + template + class SwappableIteratorConcept; + + template + class LvalueIteratorConcept; + + // Iterator Traversal Concepts + + template + class IncrementableIteratorConcept; + + template + class SinglePassIteratorConcept; + + template + class ForwardTraversalConcept; + + template + class BidirectionalTraversalConcept; + + template + class RandomAccessTraversalConcept; + + // Interoperability + + template + class InteroperableIteratorConcept; + + } + +[endsect] diff --git a/libs/iterator/doc/quickbook/concepts.qbk b/libs/iterator/doc/quickbook/concepts.qbk new file mode 100644 index 00000000..1e190576 --- /dev/null +++ b/libs/iterator/doc/quickbook/concepts.qbk @@ -0,0 +1,375 @@ +[section:concepts Iterator Concepts] + +[section:access Access] + +[section:readable Readable Iterator Concept] + +A class or built-in type `X` models the *Readable Iterator* concept +for value type `T` if, in addition to `X` being Assignable and +Copy Constructible, the following expressions are valid and respect +the stated semantics. `U` is the type of any specified member of +type `T`. + +[table Readable Iterator Requirements (in addition to Assignable and Copy Constructible) + [ + [Expression] + [Return Type] + [Note/Precondition] + ] + [ + [`iterator_traits::value_type`] + [`T`] + [Any non-reference, non cv-qualified type] + ] + [ + [`*a`] + [ Convertible to `T`] + [pre: `a` is dereferenceable. If `a == b` then `*a` is equivalent to `*b`.] + ] + [ + [`a->m`] + [`U&`] + [pre: `(*a).m` is well-defined. Equivalent to `(*a).m`.] + ] +] + +[endsect] + +[section:writable Writable Iterator Concept] + +A class or built-in type `X` models the *Writable Iterator* concept +if, in addition to `X` being Copy Constructible, the following +expressions are valid and respect the stated semantics. Writable +Iterators have an associated *set of value types*. + +[table Writable Iterator Requirements (in addition to Copy Constructible) + [ + [Expression] + [Return Type] + [Precondition] + ] + [ + [`*a = o` ] + [] + [pre: The type of `o` is in the set of value types of `X`] + ] +] + +[endsect] + +[section:swappable Swappable Iterator Concept] + +A class or built-in type `X` models the *Swappable Iterator* concept +if, in addition to `X` being Copy Constructible, the following +expressions are valid and respect the stated semantics. + +[table Swappable Iterator Requirements (in addition to Copy Constructible) + [ + [Expression] + [Return Type] + [Postcondition] + ] + [ + [`iter_swap(a, b)`] + [`void`] + [the pointed to values are exchanged] + ] +] + +[blurb *Note:* An iterator that is a model of the *Readable* and *Writable Iterator* concepts + is also a model of *Swappable Iterator*. *--end note*] + +[endsect] + +[section:lvalue Lvalue Iterator Concept] + +The *Lvalue Iterator* concept adds the requirement that the return +type of `operator*` type be a reference to the value type of the +iterator. + +[table Lvalue Iterator Requirements + [ + [Expression] + [Return Type] + [Note/Assertion] + ] + [ + [`*a` ] + [`T&` ] + [ + `T` is *cv* `iterator_traits::value_type` where *cv* is an optional cv-qualification. + pre: `a` is dereferenceable. If `a == b` then `*a` is equivalent to `*b`. + ] + ] +] + +[endsect] + +[endsect] + +[section:traversal Traversal] + +[section:incrementable Incrementable Iterator Concept] + +A class or built-in type `X` models the *Incrementable Iterator* +concept if, in addition to `X` being Assignable and Copy +Constructible, the following expressions are valid and respect the +stated semantics. + +[table Incrementable Iterator Requirements (in addition to Assignable, Copy Constructible) + [ + [Expression ] + [Return Type] + [Assertion/Semantics ] + ] + [ + [`++r` ] + [`X&` ] + [`&r == &++r`] + ] + [ + [`r++` ] + [`X` ] + [`` + { + X tmp = r; + ++r; + return tmp; + } + ``] + ] + [ + [`iterator_traversal::type`] + [Convertible to `incrementable_traversal_tag`] + [] + ] +] + +[endsect] + +[section:single_pass Single Pass Iterator Concept] + +A class or built-in type `X` models the *Single Pass Iterator* +concept if the following expressions are valid and respect the stated +semantics. + +[table Single Pass Iterator Requirements (in addition to Incrementable Iterator and Equality Comparable) + [ + [Expression] + [Return Type] + [Assertion/Semantics / Pre-/Post-condition] + ] + [ + [`++r`] + [`X&`] + [pre:[br]`r` is dereferenceable;[br]post:[br]`r` is dereferenceable or[br]`r` is past-the-end] + ] + [ + [`a == b`] + [convertible to `bool`] + [`==` is an equivalence relation over its domain] + ] + [ + [`a != b`] + [convertible to `bool`] + [`!(a == b)`] + ] + [ + [`iterator_traits::difference_type`] + [A signed integral type representing the distance between iterators] + [] + ] + [ + [`iterator_traversal::type`] + [Convertible to`single_pass_traversal_tag`] + [] + ] +] + +[endsect] + +[section:forward Forward Traversal Concept] + +A class or built-in type `X` models the *Forward Traversal* +concept if, in addition to `X` meeting the requirements of Default +Constructible and Single Pass Iterator, the following expressions are +valid and respect the stated semantics. + +[table Forward Traversal Iterator Requirements (in addition to Default Constructible and Single Pass Iterator) + [ + [Expression] + [Return Type] + [Assertion/Note] + ] + [ + [`X u;`] + [`X&`] + [note: `u` may have a singular value.] + ] + [ + [`++r`] + [`X&`] + [`r == s` and `r` is dereferenceable implies `++r == ++s.`] + ] + [ + [`iterator_traversal::type`] + [Convertible to `forward_traversal_tag`] + [] + ] +] + +[endsect] + +[section:bidirectional Bidirectional Traversal Concept] + +A class or built-in type `X` models the *Bidirectional Traversal* +concept if, in addition to `X` meeting the requirements of Forward +Traversal Iterator, the following expressions are valid and respect +the stated semantics. + +[table Bidirectional Traversal Iterator Requirements (in addition to Forward Traversal Iterator) + [ + [Expression] + [Return Type] + [Assertion/Semantics/Pre-/Post-condition] + ] + [ + [`--r`] + [`X&`] + [pre: there exists `s` such that `r == ++s`.[br] post: `s` is dereferenceable. `--(++r) == r`. `--r == --s` implies `r == s`. `&r == &--r`.] + ] + [ + [`r--`] + [convertible to `const X&`] + [`` + { + X tmp = r; + --r; + return tmp; + } + ``] + ] + [ + [`iterator_traversal::type`] + [Convertible to `bidirectional_traversal_tag`] + [] + ] +] + +[endsect] + +[section:random_access Random Access Traversal Concept] + +A class or built-in type `X` models the *Random Access Traversal* +concept if the following expressions are valid and respect the stated +semantics. In the table below, `Distance` is +`iterator_traits::difference_type` and `n` represents a +constant object of type `Distance`. + +[table Random Access Traversal Iterator Requirements (in addition to Bidirectional Traversal) + [ + [Expression] + [Return Type] + [Operational Semantics] + [Assertion/Precondition] + ] + [ + [`r += n`] + [ `X&`] + [`` + { + Distance m = n; + if (m >= 0) + while (m--) + ++r; + else + while (m++) + --r; + return r; + } + ``] + [ ] + ] + [ + [`a + n`, `n + a`] + [`X`] + [`` + { + X tmp = a; + return tmp+= n; + } + ``] + [] + ] + [ + [`r -= n`] + [`X&`] + [`return r += -n`] + [] + ] + [ + [`a - n`] + [`X`] + [`` + { + X tmp = a; + return tmp-= n; + } + ``] + [] + ] + [ + [`b - a`] + [`Distance`] + [`a < b ? distance(a,b) : -distance(b,a)`] + [pre: there exists a value `n` of `Distance` such that `a + n == b`. `b == a + (b - a)`.] + ] + [ + [`a[n]`] + [convertible to T] + [`*(a + n)`] + [pre: a is a *Readable Iterator*] + ] + [ + [`a[n] = v`] + [convertible to T] + [`*(a + n) = v`] + [pre: a is a *Writable iterator*] + ] + [ + [`a < b`] + [convertible to `bool`] + [`b - a > 0`] + [`<` is a total ordering relation] + ] + [ + [`a > b`] + [convertible to `bool`] + [`b < a`] + [`>` is a total ordering relation] + ] + [ + [`a >= b`] + [convertible to `bool`] + [`!(a < b)`] + [] + ] + [ + [`a <= b`] + [convertible to `bool`] + [`!(a > b)`] + [] + ] + [ + [`iterator_traversal::type`] + [convertible to `random_access_traversal_tag`] + [] + [] + ] +] + +[endsect] + +[endsect] + +[endsect] diff --git a/libs/iterator/doc/quickbook/counting_iterator.qbk b/libs/iterator/doc/quickbook/counting_iterator.qbk new file mode 100644 index 00000000..7fdff9ef --- /dev/null +++ b/libs/iterator/doc/quickbook/counting_iterator.qbk @@ -0,0 +1,193 @@ +[section:counting Counting Iterator] + +A `counting_iterator` adapts an object by adding an `operator*` that +returns the current value of the object. All other iterator operations +are forwarded to the adapted object. + + +[h2 Example] + + +This example fills an array with numbers and a second array with +pointers into the first array, using `counting_iterator` for both +tasks. Finally `indirect_iterator` is used to print out the numbers +into the first array via indirection through the second array. + + int N = 7; + std::vector numbers; + typedef std::vector::iterator n_iter; + std::copy(boost::counting_iterator(0), + boost::counting_iterator(N), + std::back_inserter(numbers)); + + std::vector::iterator> pointers; + std::copy(boost::make_counting_iterator(numbers.begin()), + boost::make_counting_iterator(numbers.end()), + std::back_inserter(pointers)); + + std::cout << "indirectly printing out the numbers from 0 to " + << N << std::endl; + std::copy(boost::make_indirect_iterator(pointers.begin()), + boost::make_indirect_iterator(pointers.end()), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + +The output is: + +[pre +indirectly printing out the numbers from 0 to 7 +0 1 2 3 4 5 6 +] + +The source code for this example can be found [example_link counting_iterator_example.cpp..here]. + +[h2 Reference] + + +[h3 Synopsis] + + template < + class Incrementable + , class CategoryOrTraversal = use_default + , class Difference = use_default + > + class counting_iterator + { + public: + typedef Incrementable value_type; + typedef const Incrementable& reference; + typedef const Incrementable* pointer; + typedef /* see below */ difference_type; + typedef /* see below */ iterator_category; + + counting_iterator(); + counting_iterator(counting_iterator const& rhs); + explicit counting_iterator(Incrementable x); + Incrementable const& base() const; + reference operator*() const; + counting_iterator& operator++(); + counting_iterator& operator--(); + private: + Incrementable m_inc; // exposition + }; + + +If the `Difference` argument is `use_default` then +`difference_type` is an unspecified signed integral +type. Otherwise `difference_type` is `Difference`. + +`iterator_category` is determined according to the following +algorithm: + + if (CategoryOrTraversal is not use_default) + return CategoryOrTraversal + else if (numeric_limits::is_specialized) + return |iterator-category|_\ ( + random_access_traversal_tag, Incrementable, const Incrementable&) + else + return |iterator-category|_\ ( + iterator_traversal::type, + Incrementable, const Incrementable&) + +[blurb *Note:* implementers are encouraged to provide an implementation of + `operator-` and a `difference_type` that avoids overflows in + the cases where `std::numeric_limits::is_specialized` + is true.] + +[h3 Requirements] + + +The `Incrementable` argument shall be Copy Constructible and Assignable. + +If `iterator_category` is convertible to `forward_iterator_tag` +or `forward_traversal_tag`, the following must be well-formed: + + Incrementable i, j; + ++i; // pre-increment + i == j; // operator equal + + +If `iterator_category` is convertible to +`bidirectional_iterator_tag` or `bidirectional_traversal_tag`, +the following expression must also be well-formed: + + --i + +If `iterator_category` is convertible to +`random_access_iterator_tag` or `random_access_traversal_tag`, +the following must must also be valid: + + counting_iterator::difference_type n; + i += n; + n = i - j; + i < j; + + +[h3 Concepts] + + +Specializations of `counting_iterator` model Readable Lvalue +Iterator. In addition, they model the concepts corresponding to the +iterator tags to which their `iterator_category` is convertible. +Also, if `CategoryOrTraversal` is not `use_default` then +`counting_iterator` models the concept corresponding to the iterator +tag `CategoryOrTraversal`. Otherwise, if +`numeric_limits::is_specialized`, then +`counting_iterator` models Random Access Traversal Iterator. +Otherwise, `counting_iterator` models the same iterator traversal +concepts modeled by `Incrementable`. + +`counting_iterator` is interoperable with +`counting_iterator` if and only if `X` is +interoperable with `Y`. + + +[h3 Operations] + + +In addition to the operations required by the concepts modeled by +`counting_iterator`, `counting_iterator` provides the following +operations. + + + counting_iterator(); + +[*Requires: ] `Incrementable` is Default Constructible.[br] +[*Effects: ] Default construct the member `m_inc`. + + + counting_iterator(counting_iterator const& rhs); + +[*Effects: ] Construct member `m_inc` from `rhs.m_inc`. + + + + explicit counting_iterator(Incrementable x); + +[*Effects: ] Construct member `m_inc` from `x`. + + + reference operator*() const; + +[*Returns: ] `m_inc` + + + counting_iterator& operator++(); + +[*Effects: ] `++m_inc`[br] +[*Returns: ] `*this` + + + counting_iterator& operator--(); + +[*Effects: ] `--m_inc`[br] +[*Returns: ] `*this` + + + Incrementable const& base() const; + +[*Returns: ] `m_inc` + + +[endsect] diff --git a/libs/iterator/doc/quickbook/facade.qbk b/libs/iterator/doc/quickbook/facade.qbk new file mode 100644 index 00000000..4e029b0f --- /dev/null +++ b/libs/iterator/doc/quickbook/facade.qbk @@ -0,0 +1,636 @@ +[section:facade Iterator Facade] + +While the iterator interface is rich, there is a core subset of the +interface that is necessary for all the functionality. We have +identified the following core behaviors for iterators: + +* dereferencing +* incrementing +* decrementing +* equality comparison +* random-access motion +* distance measurement + +In addition to the behaviors listed above, the core interface elements +include the associated types exposed through iterator traits: +`value_type`, `reference`, `difference_type`, and +`iterator_category`. + +Iterator facade uses the Curiously Recurring Template +Pattern (CRTP) [Cop95]_ so that the user can specify the behavior +of `iterator_facade` in a derived class. Former designs used +policy objects to specify the behavior, but that approach was +discarded for several reasons: + +1. the creation and eventual copying of the policy object may create + overhead that can be avoided with the current approach. + +2. The policy object approach does not allow for custom constructors + on the created iterator types, an essential feature if + `iterator_facade` should be used in other library + implementations. + +3. Without the use of CRTP, the standard requirement that an + iterator's `operator++` returns the iterator type itself + would mean that all iterators built with the library would + have to be specializations of `iterator_facade<...>`, rather + than something more descriptive like + `indirect_iterator`. Cumbersome type generator + metafunctions would be needed to build new parameterized + iterators, and a separate `iterator_adaptor` layer would be + impossible. + +[h2 Usage] + +The user of `iterator_facade` derives his iterator class from a +specialization of `iterator_facade` and passes the derived +iterator class as `iterator_facade`\ 's first template parameter. +The order of the other template parameters have been carefully +chosen to take advantage of useful defaults. For example, when +defining a constant lvalue iterator, the user can pass a +const-qualified version of the iterator's `value_type` as +`iterator_facade`\ 's `Value` parameter and omit the +`Reference` parameter which follows. + +The derived iterator class must define member functions implementing +the iterator's core behaviors. The following table describes +expressions which are required to be valid depending on the category +of the derived iterator type. These member functions are described +briefly below and in more detail in the iterator facade +requirements. + +[table Core Interface + [ + [Expression] + [Effects] + ] + [ + [`i.dereference()`] + [Access the value referred to] + ] + [ + [`i.equal(j)`] + [Compare for equality with `j`] + ] + [ + [`i.increment()`] + [Advance by one position] + ] + [ + [`i.decrement()`] + [Retreat by one position] + ] + [ + [`i.advance(n)`] + [Advance by `n` positions] + ] + [ + [`i.distance_to(j)`] + [Measure the distance to `j`] + ] +] + +[/ .. Should we add a comment that a zero overhead implementation of iterator_facade is possible with proper inlining?] + +In addition to implementing the core interface functions, an iterator +derived from `iterator_facade` typically defines several +constructors. To model any of the standard iterator concepts, the +iterator must at least have a copy constructor. Also, if the iterator +type `X` is meant to be automatically interoperate with another +iterator type `Y` (as with constant and mutable iterators) then +there must be an implicit conversion from `X` to `Y` or from `Y` +to `X` (but not both), typically implemented as a conversion +constructor. Finally, if the iterator is to model Forward Traversal +Iterator or a more-refined iterator concept, a default constructor is +required. + +[h2 Iterator Core Access] + +`iterator_facade` and the operator implementations need to be able +to access the core member functions in the derived class. Making the +core member functions public would expose an implementation detail to +the user. The design used here ensures that implementation details do +not appear in the public interface of the derived iterator type. + +Preventing direct access to the core member functions has two +advantages. First, there is no possibility for the user to accidently +use a member function of the iterator when a member of the value_type +was intended. This has been an issue with smart pointer +implementations in the past. The second and main advantage is that +library implementers can freely exchange a hand-rolled iterator +implementation for one based on `iterator_facade` without fear of +breaking code that was accessing the public core member functions +directly. + +In a naive implementation, keeping the derived class' core member +functions private would require it to grant friendship to +`iterator_facade` and each of the seven operators. In order to +reduce the burden of limiting access, `iterator_core_access` is +provided, a class that acts as a gateway to the core member functions +in the derived iterator class. The author of the derived class only +needs to grant friendship to `iterator_core_access` to make his core +member functions available to the library. + + +`iterator_core_access` will be typically implemented as an empty +class containing only private static member functions which invoke the +iterator core member functions. There is, however, no need to +standardize the gateway protocol. Note that even if +`iterator_core_access` used public member functions it would not +open a safety loophole, as every core member function preserves the +invariants of the iterator. + +[h2 `operator[]`] + +The indexing operator for a generalized iterator presents special +challenges. A random access iterator's `operator[]` is only +required to return something convertible to its `value_type`. +Requiring that it return an lvalue would rule out currently-legal +random-access iterators which hold the referenced value in a data +member (e.g. |counting|_), because `*(p+n)` is a reference +into the temporary iterator `p+n`, which is destroyed when +`operator[]` returns. + +.. |counting| replace:: `counting_iterator` + +Writable iterators built with `iterator_facade` implement the +semantics required by the preferred resolution to `issue 299`_ and +adopted by proposal n1550_: the result of `p[n]` is an object +convertible to the iterator's `value_type`, and `p[n] = x` is +equivalent to `*(p + n) = x` (Note: This result object may be +implemented as a proxy containing a copy of `p+n`). This approach +will work properly for any random-access iterator regardless of the +other details of its implementation. A user who knows more about +the implementation of her iterator is free to implement an +`operator[]` that returns an lvalue in the derived iterator +class; it will hide the one supplied by `iterator_facade` from +clients of her iterator. + +.. _n1550: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1550.htm + +.. _`issue 299`: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#299 + +.. _`operator arrow`: + +[h2 `operator->`] + +The `reference` type of a readable iterator (and today's input +iterator) need not in fact be a reference, so long as it is +convertible to the iterator's `value_type`. When the `value_type` +is a class, however, it must still be possible to access members +through `operator->`. Therefore, an iterator whose `reference` +type is not in fact a reference must return a proxy containing a copy +of the referenced value from its `operator->`. + +The return types for `iterator_facade`\ 's `operator->` and +`operator[]` are not explicitly specified. Instead, those types +are described in terms of a set of requirements, which must be +satisfied by the `iterator_facade` implementation. + +.. [Cop95] [Coplien, 1995] Coplien, J., Curiously Recurring Template + Patterns, C++ Report, February 1995, pp. 24-27. + +[section:facade_reference Reference] + + template < + class Derived + , class Value + , class CategoryOrTraversal + , class Reference = Value& + , class Difference = ptrdiff_t + > + class iterator_facade { + public: + typedef remove_const::type value_type; + typedef Reference reference; + typedef Value\* pointer; + typedef Difference difference_type; + typedef /* see below__ \*/ iterator_category; + + reference operator\*() const; + /* see below__ \*/ operator->() const; + /* see below__ \*/ operator[](difference_type n) const; + Derived& operator++(); + Derived operator++(int); + Derived& operator--(); + Derived operator--(int); + Derived& operator+=(difference_type n); + Derived& operator-=(difference_type n); + Derived operator-(difference_type n) const; + protected: + typedef iterator_facade iterator_facade\_; + }; + + // Comparison operators + template + typename enable_if_interoperable::type // exposition + operator ==(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator !=(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator <(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator <=(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator >(iterator_facade const& lhs, + iterator_facade const& rhs); + + template + typename enable_if_interoperable::type + operator >=(iterator_facade const& lhs, + iterator_facade const& rhs); + + // Iterator difference + template + /* see below__ \*/ + operator-(iterator_facade const& lhs, + iterator_facade const& rhs); + + // Iterator addition + template + Derived operator+ (iterator_facade const&, + typename Derived::difference_type n); + + template + Derived operator+ (typename Derived::difference_type n, + iterator_facade const&); + +__ `iterator category`_ + +__ `operator arrow`_ + +__ brackets_ + +__ minus_ + +.. _`iterator category`: + +The `iterator_category` member of `iterator_facade` is + +.. parsed-literal:: + + *iterator-category*\ (CategoryOrTraversal, reference, value_type) + +where *iterator-category* is defined as follows: + +.. include:: facade_iterator_category.rst + +The `enable_if_interoperable` template used above is for exposition +purposes. The member operators should only be in an overload set +provided the derived types `Dr1` and `Dr2` are interoperable, +meaning that at least one of the types is convertible to the other. The +`enable_if_interoperable` approach uses SFINAE to take the operators +out of the overload set when the types are not interoperable. +The operators should behave *as-if* `enable_if_interoperable` +were defined to be: + + template enable_if_interoperable_impl + {}; + + template enable_if_interoperable_impl + { typedef T type; }; + + template + struct enable_if_interoperable + : enable_if_interoperable_impl< + is_convertible::value || is_convertible::value + , T + > + {}; + + +[h2 Requirements] + +The following table describes the typical valid expressions on +`iterator_facade`\ 's `Derived` parameter, depending on the +iterator concept(s) it will model. The operations in the first +column must be made accessible to member functions of class +`iterator_core_access`. In addition, +`static_cast(iterator_facade*)` shall be well-formed. + +In the table below, `F` is `iterator_facade`, `a` is an +object of type `X`, `b` and `c` are objects of type `const X`, +`n` is an object of `F::difference_type`, `y` is a constant +object of a single pass iterator type interoperable with `X`, and `z` +is a constant object of a random access traversal iterator type +interoperable with `X`. + +.. _`core operations`: + +.. topic:: `iterator_facade` Core Operations + +[table Core Operations + [ + [Expression] + [Return Type] + [Assertion/Note] + [Used to implement Iterator Concept(s)] + ] + [ + [`c.dereference()`] + [`F::reference`] + [] + [Readable Iterator, Writable Iterator] + ] + [ + [`c.equal(y)`] + [convertible to bool] + [true iff `c` and `y` refer to the same position] + [Single Pass Iterator] + ] + [ + [`a.increment()`] + [unused] + [] + [Incrementable Iterator] + ] + [ + [`a.decrement()`] + [unused] + [] + [Bidirectional Traversal Iterator] + ] + [ + [`a.advance(n)`] + [unused] + [] + [Random Access Traversal Iterator] + ] + [ + [`c.distance_to(z)`] + [convertible to `F::difference_type`] + [equivalent to `distance(c, X(z))`.] + [Random Access Traversal Iterator] + ] +] + +[h2 Operations] + +The operations in this section are described in terms of operations on +the core interface of `Derived` which may be inaccessible +(i.e. private). The implementation should access these operations +through member functions of class `iterator_core_access`. + + reference operator*() const; + +[*Returns:] `static_cast(this)->dereference()` + + operator->() const; (see below__) + +__ `operator arrow`_ + +[*Returns:] If `reference` is a reference type, an object of type `pointer` equal to: `&static_cast(this)->dereference()` +Otherwise returns an object of unspecified type such that, +`(*static_cast(this))->m` is equivalent to `(w = **static_cast(this), +w.m)` for some temporary object `w` of type `value_type`. + +.. _brackets: + + *unspecified* operator[](difference_type n) const; + +[*Returns:] an object convertible to `value_type`. For constant + objects `v` of type `value_type`, and `n` of type + `difference_type`, `(*this)[n] = v` is equivalent to + `*(*this + n) = v`, and `static_cast((*this)[n])` is equivalent to + `static_cast(*(*this + n))` + + Derived& operator++(); + +[*Effects:] + + static_cast(this)->increment(); + return *static_cast(this); + + Derived operator++(int); + +[*Effects:] + + Derived tmp(static_cast(this)); + ++*this; + return tmp; + + Derived& operator--(); + +[*Effects:] + + static_cast(this)->decrement(); + return *static_cast(this); + + Derived operator--(int); + +[*Effects:] + + Derived tmp(static_cast(this)); + --*this; + return tmp; + + + Derived& operator+=(difference_type n); + +[*Effects:] + + static_cast(this)->advance(n); + return *static_cast(this); + + + Derived& operator-=(difference_type n); + +[*Effects:] + + static_cast(this)->advance(-n); + return *static_cast(this); + + + Derived operator-(difference_type n) const; + +[*Effects:] + + Derived tmp(static_cast(this)); + return tmp -= n; + + template + Derived operator+ (iterator_facade const&, + typename Derived::difference_type n); + + template + Derived operator+ (typename Derived::difference_type n, + iterator_facade const&); + +[*Effects:] + + Derived tmp(static_cast(this)); + return tmp += n; + + template + typename enable_if_interoperable::type + operator ==(iterator_facade const& lhs, + iterator_facade const& rhs); + +[*Returns:] + +[pre + if `is_convertible::value` + + then + `((Dr1 const&)lhs).equal((Dr2 const&)rhs)`. + + Otherwise, + `((Dr2 const&)rhs).equal((Dr1 const&)lhs)`. +] + + + template + typename enable_if_interoperable::type + operator !=(iterator_facade const& lhs, + iterator_facade const& rhs); + +[*Returns:] + +[pre + if `is_convertible::value` + + then + `!((Dr1 const&)lhs).equal((Dr2 const&)rhs)`. + + Otherwise, + `!((Dr2 const&)rhs).equal((Dr1 const&)lhs)`. +] + + + template + typename enable_if_interoperable::type + operator <(iterator_facade const& lhs, + iterator_facade const& rhs); + +[*Returns:] + +[pre + if `is_convertible::value` + + then + `((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) < 0`. + + Otherwise, + `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) > 0`. +] + + + template + typename enable_if_interoperable::type + operator <=(iterator_facade const& lhs, + iterator_facade const& rhs); + +[*Returns:] + +[pre + if `is_convertible::value` + + then + `((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) <= 0`. + + Otherwise, + `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) >= 0`. +] + + + template + typename enable_if_interoperable::type + operator >(iterator_facade const& lhs, + iterator_facade const& rhs); + +[*Returns:] + +[pre + if `is_convertible::value` + + then + `((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) > 0`. + + Otherwise, + `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) < 0`. +] + + + template + typename enable_if_interoperable::type + operator >=(iterator_facade const& lhs, + iterator_facade const& rhs); + +[*Returns:] + +[pre + if `is_convertible::value` + + then + `((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) >= 0`. + + Otherwise, + `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) <= 0`. +] + +.. _minus: + + + template + typename enable_if_interoperable::type + operator -(iterator_facade const& lhs, + iterator_facade const& rhs); + +[*Return Type:] + +[pre + if `is_convertible::value` + + then + `difference` shall be + `iterator_traits::difference_type`. + + Otherwise + `difference` shall be `iterator_traits::difference_type` +] + +[*Returns:] + +[pre + if `is_convertible::value` + + then + `-((Dr1 const&)lhs).distance_to((Dr2 const&)rhs)`. + + Otherwise, + `((Dr2 const&)rhs).distance_to((Dr1 const&)lhs)`. +] + + +[endsect] + +[include facade_tutorial.qbk] + +[endsect] diff --git a/libs/iterator/doc/quickbook/facade_tutorial.qbk b/libs/iterator/doc/quickbook/facade_tutorial.qbk new file mode 100644 index 00000000..08b18acf --- /dev/null +++ b/libs/iterator/doc/quickbook/facade_tutorial.qbk @@ -0,0 +1,506 @@ +[section:facade_tutorial Tutorial] + +In this section we'll walk through the implementation of a few +iterators using `iterator_facade`, based around the simple +example of a linked list of polymorphic objects. This example was +inspired by a +[@http://thread.gmane.org/gmane.comp.lib.boost.user/5100 `posting`] +by Keith Macdonald on the +[@http://www.boost.org/more/mailing_lists.htm#users `Boost-Users`] +mailing list. + + +[h2 The Problem] + + +Say we've written a polymorphic linked list node base class: + + # include + + struct node_base + { + node_base() : m_next(0) {} + + // Each node manages all of its tail nodes + virtual ~node_base() { delete m_next; } + + // Access the rest of the list + node_base* next() const { return m_next; } + + // print to the stream + virtual void print(std::ostream& s) const = 0; + + // double the value + virtual void double_me() = 0; + + void append(node_base* p) + { + if (m_next) + m_next->append(p); + else + m_next = p; + } + + private: + node_base* m_next; + }; + +Lists can hold objects of different types by linking together +specializations of the following template: + + template + struct node : node_base + { + node(T x) + : m_value(x) + {} + + void print(std::ostream& s) const { s << this->m_value; } + void double_me() { m_value += m_value; } + + private: + T m_value; + }; + +And we can print any node using the following streaming operator: + + inline std::ostream& operator<<(std::ostream& s, node_base const& n) + { + n.print(s); + return s; + } + +Our first challenge is to build an appropriate iterator over these +lists. + +[h2 A Basic Iterator Using `iterator_facade`] + +We will construct a `node_iterator` class using inheritance from +`iterator_facade` to implement most of the iterator's operations. + + + # include "node.hpp" + # include + + class node_iterator + : public boost::iterator_facade<...> + { + ... + }; + + + +[h2 Template Arguments for `iterator_facade`] + +`iterator_facade` has several template parameters, so we must decide +what types to use for the arguments. The parameters are `Derived`, +`Value`, `CategoryOrTraversal`, `Reference`, and `Difference`. + + +[h3 `Derived`] + +Because `iterator_facade` is meant to be used with the CRTP +[Cop95]_ the first parameter is the iterator class name itself, +`node_iterator`. + +[h3 `Value`] + +The `Value` parameter determines the `node_iterator`\ 's +`value_type`. In this case, we are iterating over `node_base` +objects, so `Value` will be `node_base`. + + +[h3 `CategoryOrTraversal`] + +Now we have to determine which `iterator traversal concept`_ our +`node_iterator` is going to model. Singly-linked lists only have +forward links, so our iterator can't can't be a `bidirectional +traversal iterator`_. Our iterator should be able to make multiple +passes over the same linked list (unlike, say, an +`istream_iterator` which consumes the stream it traverses), so it +must be a `forward traversal iterator`_. Therefore, we'll pass +`boost::forward_traversal_tag` in this position [#category]_. + +.. [#category] `iterator_facade` also supports old-style category + tags, so we could have passed `std::forward_iterator_tag` here; + either way, the resulting iterator's `iterator_category` will + end up being `std::forward_iterator_tag`. + +[h3 `Reference`] + +The `Reference` argument becomes the type returned by +`node_iterator`\ 's dereference operation, and will also be the +same as `std::iterator_traits::reference`. The +library's default for this parameter is `Value&`; since +`node_base&` is a good choice for the iterator's `reference` +type, we can omit this argument, or pass `use_default`. + +[h3 `Difference`] + +The `Difference` argument determines how the distance between +two `node_iterator`\ s will be measured and will also be the +same as `std::iterator_traits::difference_type`. +The library's default for `Difference` is `std::ptrdiff_t`, an +appropriate type for measuring the distance between any two +addresses in memory, and one that works for almost any iterator, +so we can omit this argument, too. + +The declaration of `node_iterator` will therefore look something +like: + + # include "node.hpp" + # include + + class node_iterator + : public boost::iterator_facade< + node_iterator + , node_base + , boost::forward_traversal_tag + > + { + ... + }; + + +[h2 Constructors and Data Members] + +Next we need to decide how to represent the iterator's position. +This representation will take the form of data members, so we'll +also need to write constructors to initialize them. The +`node_iterator`\ 's position is quite naturally represented using +a pointer to a `node_base`. We'll need a constructor to build an +iterator from a `node_base*`, and a default constructor to +satisfy the `forward traversal iterator`_ requirements [#default]_. +Our `node_iterator` then becomes: + + # include "node.hpp" + # include + + class node_iterator + : public boost::iterator_facade< + node_iterator + , node_base + , boost::forward_traversal_tag + > + { + public: + node_iterator() + : m_node(0) + {} + + explicit node_iterator(node_base* p) + : m_node(p) + {} + + private: + ... + node_base* m_node; + }; + +.. [#default] Technically, the C++ standard places almost no + requirements on a default-constructed iterator, so if we were + really concerned with efficiency, we could've written the + default constructor to leave `m_node` uninitialized. + +[h2 Implementing the Core Operations] + +The last step is to implement the `core operations`_ required by +the concepts we want our iterator to model. Referring to the +table__, we can see that the first three rows are applicable +because `node_iterator` needs to satisfy the requirements for +`readable iterator`_, `single pass iterator`_, and `incrementable +iterator`_. + +__ `core operations`_ + +We therefore need to supply `dereference`, +`equal`, and `increment` members. We don't want these members +to become part of `node_iterator`\ 's public interface, so we can +make them private and grant friendship to +`boost::iterator_core_access`, a "back-door" that +`iterator_facade` uses to get access to the core operations: + + # include "node.hpp" + # include + + class node_iterator + : public boost::iterator_facade< + node_iterator + , node_base + , boost::forward_traversal_tag + > + { + public: + node_iterator() + : m_node(0) {} + + explicit node_iterator(node_base* p) + : m_node(p) {} + + private: + friend class boost::iterator_core_access; + + void increment() { m_node = m_node->next(); } + + bool equal(node_iterator const& other) const + { + return this->m_node == other.m_node; + } + + node_base& dereference() const { return *m_node; } + + node_base* m_node; + }; + +Voila; a complete and conforming readable, forward-traversal +iterator! For a working example of its use, see +[example_link node_iterator1.cpp..this program]. + +__ ../../example/node_iterator1.cpp + +[h2 A constant `node_iterator`] + +[blurb *Constant and Mutable iterators*[br][br] +The term **mutable iterator** means an iterator through which +the object it references (its "referent") can be modified. A +**constant iterator** is one which doesn't allow modification of +its referent.[br][br] +The words *constant* and *mutable* don't refer to the ability to +modify the iterator itself. For example, an `int const*` is a +non-\ `const` *constant iterator*, which can be incremented +but doesn't allow modification of its referent, and `int* +const` is a `const` *mutable iterator*, which cannot be +modified but which allows modification of its referent.[br][br] +Confusing? We agree, but those are the standard terms. It +probably doesn't help much that a container's constant iterator +is called `const_iterator`. +] + +Now, our `node_iterator` gives clients access to both `node`\ +'s `print(std::ostream&) const` member function, but also its +mutating `double_me()` member. If we wanted to build a +*constant* `node_iterator`, we'd only have to make three +changes: + + class const_node_iterator + : public boost::iterator_facade< + const_node_iterator + , node_base **const** + , boost::forward_traversal_tag + > + { + public: + const_node_iterator() + : m_node(0) {} + + explicit const_node_iterator(node_base* p) + : m_node(p) {} + + private: + friend class boost::iterator_core_access; + + void increment() { m_node = m_node->next(); } + + bool equal(const_node_iterator const& other) const + { + return this->m_node == other.m_node; + } + + node_base **const**\ & dereference() const { return \*m_node; } + + node_base **const**\ * m_node; + }; + +[blurb `const` and an iterator's `value_type`[br][br] +The C++ standard requires an iterator's `value_type` *not* be +`const`\ -qualified, so `iterator_facade` strips the +`const` from its `Value` parameter in order to produce the +iterator's `value_type`. Making the `Value` argument +`const` provides a useful hint to `iterator_facade` that the +iterator is a *constant iterator*, and the default `Reference` +argument will be correct for all lvalue iterators. +] + +As a matter of fact, `node_iterator` and `const_node_iterator` +are so similar that it makes sense to factor the common code out +into a template as follows: + + template + class node_iter + : public boost::iterator_facade< + node_iter + , Value + , boost::forward_traversal_tag + > + { + public: + node_iter() + : m_node(0) {} + + explicit node_iter(Value* p) + : m_node(p) {} + + private: + friend class boost::iterator_core_access; + + bool equal(node_iter const& other) const + { + return this->m_node == other.m_node; + } + + void increment() + { m_node = m_node->next(); } + + Value& dereference() const + { return *m_node; } + + Value* m_node; + }; + typedef node_iter node_iterator; + typedef node_iter node_const_iterator; + + +[h2 Interoperability] + +Our `const_node_iterator` works perfectly well on its own, but +taken together with `node_iterator` it doesn't quite meet +expectations. For example, we'd like to be able to pass a +`node_iterator` where a `node_const_iterator` was expected, +just as you can with `std::list`\ 's `iterator` and +`const_iterator`. Furthermore, given a `node_iterator` and a +`node_const_iterator` into the same list, we should be able to +compare them for equality. + +This expected ability to use two different iterator types together +is known as |interoperability|_. Achieving interoperability in +our case is as simple as templatizing the `equal` function and +adding a templatized converting constructor [#broken]_ [#random]_: + + template + class node_iter + : public boost::iterator_facade< + node_iter + , Value + , boost::forward_traversal_tag + > + { + public: + node_iter() + : m_node(0) {} + + explicit node_iter(Value* p) + : m_node(p) {} + + template + node_iter(node_iter const& other) + : m_node(other.m_node) {} + + private: + friend class boost::iterator_core_access; + template friend class node_iter; + + template + bool equal(node_iter const& other) const + { + return this->m_node == other.m_node; + } + + void increment() + { m_node = m_node->next(); } + + Value& dereference() const + { return *m_node; } + + Value* m_node; + }; + typedef impl::node_iterator node_iterator; + typedef impl::node_iterator node_const_iterator; + +.. |interoperability| replace:: **interoperability** +.. _interoperability: new-iter-concepts.html#interoperable-iterators-lib-interoperable-iterators + +.. [#broken] If you're using an older compiler and it can't handle + this example, see the `example code`__ for workarounds. + +.. [#random] If `node_iterator` had been a `random access + traversal iterator`_, we'd have had to templatize its + `distance_to` function as well. + + +__ ../../example/node_iterator2.hpp + +You can see an example program which exercises our interoperable +iterators +[example_link node_iterator2.cpp..here]. + + +[h2 Telling the Truth] + +Now `node_iterator` and `node_const_iterator` behave exactly as +you'd expect... almost. We can compare them and we can convert in +one direction: from `node_iterator` to `node_const_iterator`. +If we try to convert from `node_const_iterator` to +`node_iterator`, we'll get an error when the converting +constructor tries to initialize `node_iterator`\ 's `m_node`, a +`node*` with a `node const*`. So what's the problem? + +The problem is that +`boost::`\ |is_convertible|_\ `::value` +will be `true`, but it should be `false`. |is_convertible|_ +lies because it can only see as far as the *declaration* of +`node_iter`\ 's converting constructor, but can't look inside at +the *definition* to make sure it will compile. A perfect solution +would make `node_iter`\ 's converting constructor disappear when +the `m_node` conversion would fail. + +.. |is_convertible| replace:: `is_convertible` +.. _is_convertible: ../../type_traits/index.html#relationships + +In fact, that sort of magic is possible using +|enable_if|__. By rewriting the converting constructor as +follows, we can remove it from the overload set when it's not +appropriate: + + #include + #include + + ... + + private: + struct enabler {}; + + public: + template + node_iter( + node_iter const& other + , typename boost::enable_if< + boost::is_convertible + , enabler + >::type = enabler() + ) + : m_node(other.m_node) {} + +.. |enable_if| replace:: `boost::enable_if` +__ ../../utility/enable_if.html + + +[h2 Wrap Up] + +This concludes our `iterator_facade` tutorial, but before you +stop reading we urge you to take a look at |iterator_adaptor|__. +There's another way to approach writing these iterators which might +even be superior. + +.. |iterator_adaptor| replace:: `iterator_adaptor` +__ iterator_adaptor.html + +.. _`iterator traversal concept`: new-iter-concepts.html#iterator-traversal-concepts-lib-iterator-traversal +.. _`readable iterator`: new-iter-concepts.html#readable-iterators-lib-readable-iterators +.. _`lvalue iterator`: new-iter-concepts.html#lvalue-iterators-lib-lvalue-iterators +.. _`single pass iterator`: new-iter-concepts.html#single-pass-iterators-lib-single-pass-iterators +.. _`incrementable iterator`: new-iter-concepts.html#incrementable-iterators-lib-incrementable-iterators +.. _`forward traversal iterator`: new-iter-concepts.html#forward-traversal-iterators-lib-forward-traversal-iterators +.. _`bidirectional traversal iterator`: new-iter-concepts.html#bidirectional-traversal-iterators-lib-bidirectional-traversal-iterators +.. _`random access traversal iterator`: new-iter-concepts.html#random-access-traversal-iterators-lib-random-access-traversal-iterators + +[endsect] diff --git a/libs/iterator/doc/quickbook/filter_iterator.qbk b/libs/iterator/doc/quickbook/filter_iterator.qbk new file mode 100644 index 00000000..e7cace82 --- /dev/null +++ b/libs/iterator/doc/quickbook/filter_iterator.qbk @@ -0,0 +1,240 @@ +[section:filter Filter Iterator] + +The filter iterator adaptor creates a view of an iterator range in +which some elements of the range are skipped. A predicate function +object controls which elements are skipped. When the predicate is +applied to an element, if it returns `true` then the element is +retained and if it returns `false` then the element is skipped +over. When skipping over elements, it is necessary for the filter +adaptor to know when to stop so as to avoid going past the end of the +underlying range. A filter iterator is therefore constructed with pair +of iterators indicating the range of elements in the unfiltered +sequence to be traversed. + +[h2 Example] + +This example uses `filter_iterator` and then +`make_filter_iterator` to output only the positive integers from an +array of integers. Then `make_filter_iterator` is is used to output +the integers greater than `-2`. + + struct is_positive_number { + bool operator()(int x) { return 0 < x; } + }; + + int main() + { + int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 }; + const int N = sizeof(numbers_)/sizeof(int); + + typedef int* base_iterator; + base_iterator numbers(numbers_); + + // Example using filter_iterator + typedef boost::filter_iterator + FilterIter; + + is_positive_number predicate; + FilterIter filter_iter_first(predicate, numbers, numbers + N); + FilterIter filter_iter_last(predicate, numbers + N, numbers + N); + + std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + // Example using make_filter_iterator() + std::copy(boost::make_filter_iterator(numbers, numbers + N), + boost::make_filter_iterator(numbers + N, numbers + N), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + // Another example using make_filter_iterator() + std::copy( + boost::make_filter_iterator( + std::bind(std::greater(), std::placeholders::_1, -2) + , numbers, numbers + N) + + , boost::make_filter_iterator( + std::bind(std::greater(), std::placeholders::_1, -2) + , numbers + N, numbers + N) + + , std::ostream_iterator(std::cout, " ") + ); + + std::cout << std::endl; + + return boost::exit_success; + } + + +The output is: + +[pre +4 5 8 +4 5 8 +0 -1 4 5 8 +] + +The source code for this example can be found [example_link filter_iterator_example.cpp..here]. + +[h2 Reference] + + +[h3 Synopsis] + + template + class filter_iterator + { + public: + typedef iterator_traits::value_type value_type; + typedef iterator_traits::reference reference; + typedef iterator_traits::pointer pointer; + typedef iterator_traits::difference_type difference_type; + typedef /* see below */ iterator_category; + + filter_iterator(); + filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); + filter_iterator(Iterator x, Iterator end = Iterator()); + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + ); + Predicate predicate() const; + Iterator end() const; + Iterator const& base() const; + reference operator*() const; + filter_iterator& operator++(); + private: + Predicate m_pred; // exposition only + Iterator m_iter; // exposition only + Iterator m_end; // exposition only + }; + + +If `Iterator` models Readable Lvalue Iterator and Bidirectional Traversal +Iterator then `iterator_category` is convertible to +`std::bidirectional_iterator_tag`. +Otherwise, if `Iterator` models Readable Lvalue Iterator and Forward Traversal +Iterator then `iterator_category` is convertible to +`std::forward_iterator_tag`. +Otherwise `iterator_category` is +convertible to `std::input_iterator_tag`. + + +[h3 Requirements] + +The `Iterator` argument shall meet the requirements of Readable +Iterator and Single Pass Iterator or it shall meet the requirements of +Input Iterator. + + +The `Predicate` argument must be Assignable, Copy Constructible, and +the expression `p(x)` must be valid where `p` is an object of type +`Predicate`, `x` is an object of type +`iterator_traits::value_type`, and where the type of +`p(x)` must be convertible to `bool`. + + +[h3 Concepts] + +The concepts that `filter_iterator` models are dependent on which +concepts the `Iterator` argument models, as specified in the +following tables. + +[table Traversal + [[If `Iterator` models ][then `filter_iterator` models ]] + [[Single Pass Iterator ][Single Pass Iterator ]] + [[Forward Traversal Iterator ][Forward Traversal Iterator ]] + [[Bidirectional Traversal Iterator ][Bidirectional Traversal Iterator]] +] + +[table Access + [[If `Iterator` models ][then `filter_iterator` models ]] + [[Readable Iterator][Readable Iterator]] + [[Writable Iterator][Writable Iterator]] + [[Lvalue Iterator ][Lvalue Iterator ]] +] + +[table C++03 + [[If `Iterator` models ][then `filter_iterator` models ]] + [[Readable Iterator, Single Pass Iterator ][Input Iterator ]] + [[Readable Lvalue Iterator, Forward Traversal Iterator][Forward Iterator ]] + [[Writable Lvalue Iterator, Forward Traversal Iterator][Mutable Forward Iterator ]] + [[Writable Lvalue Iterator, Bidirectional Iterator ][Mutable Bidirectional Iterator]] +] + +`filter_iterator` is interoperable with `filter_iterator` +if and only if `X` is interoperable with `Y`. + + +[h3 Operations] + + +In addition to those operations required by the concepts that +`filter_iterator` models, `filter_iterator` provides the following +operations. + + + filter_iterator(); + +[*Requires: ]`Predicate` and `Iterator` must be Default Constructible.[br] +[*Effects: ] Constructs a `filter_iterator` whose`m_pred`, `m_iter`, and `m_end` + members are a default constructed. + + + filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); + +[*Effects: ] Constructs a `filter_iterator` where `m_iter` is either + the first position in the range `[x,end)` such that `f(*m_iter) == true` + or else`m_iter == end`. The member `m_pred` is constructed from + `f` and `m_end` from `end`. + + + + filter_iterator(Iterator x, Iterator end = Iterator()); + +[*Requires: ] `Predicate` must be Default Constructible and + `Predicate` is a class type (not a function pointer).[br] +[*Effects: ] Constructs a `filter_iterator` where `m_iter` is either + the first position in the range `[x,end)` such that `m_pred(*m_iter) == true` + or else`m_iter == end`. The member `m_pred` is default constructed. + + + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition + ); + +[*Requires: ] `OtherIterator` is implicitly convertible to `Iterator`.[br] +[*Effects: ] Constructs a filter iterator whose members are copied from `t`. + + + Predicate predicate() const; + +[*Returns: ] `m_pred` + + + Ierator end() const; + +[*Returns: ] `m_end` + + + Iterator const& base() const; + +[*Returns: ] `m_iterator` + + + reference operator*() const; + +[*Returns: ] `*m_iter` + + + filter_iterator& operator++(); + +[*Effects: ] Increments `m_iter` and then continues to + increment `m_iter` until either `m_iter == m_end` + or `m_pred(*m_iter) == true`.[br] +[*Returns: ] `*this` + +[endsect] diff --git a/libs/iterator/doc/quickbook/function_output_iterator.qbk b/libs/iterator/doc/quickbook/function_output_iterator.qbk new file mode 100644 index 00000000..914db7d0 --- /dev/null +++ b/libs/iterator/doc/quickbook/function_output_iterator.qbk @@ -0,0 +1,99 @@ +[section:function_output Function Output Iterator] + +The function output iterator adaptor makes it easier to create custom +output iterators. The adaptor takes a unary function and creates a +model of Output Iterator. Each item assigned to the output iterator is +passed as an argument to the unary function. The motivation for this +iterator is that creating a conforming output iterator is non-trivial, +particularly because the proper implementation usually requires a +proxy object. + +[h2 Example] + + struct string_appender + { + string_appender(std::string& s) + : m_str(&s) + {} + + void operator()(const std::string& x) const + { + *m_str += x; + } + + std::string* m_str; + }; + + int main(int, char*[]) + { + std::vector x; + x.push_back("hello"); + x.push_back(" "); + x.push_back("world"); + x.push_back("!"); + + std::string s = ""; + std::copy(x.begin(), x.end(), + boost::make_function_output_iterator(string_appender(s))); + + std::cout << s << std::endl; + + return 0; + } + +[h2 Reference] + +[h3 Synopsis] + + template + class function_output_iterator { + public: + typedef std::output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + explicit function_output_iterator(); + + explicit function_output_iterator(const UnaryFunction& f); + + /* see below */ operator*(); + function_output_iterator& operator++(); + function_output_iterator& operator++(int); + private: + UnaryFunction m_f; // exposition only + }; + +[h3 Requirements] + +`UnaryFunction` must be Assignable and Copy Constructible. + +[h3 Concepts] + +`function_output_iterator` is a model of the Writable and +Incrementable Iterator concepts. + +[h3 Operations] + + explicit function_output_iterator(const UnaryFunction& f = UnaryFunction()); + +[*Effects: ] Constructs an instance of `function_output_iterator` + with `m_f` constructed from `f`. + + unspecified_type operator*(); + +[*Returns: ] An object `r` of unspecified type such that `r = t` + is equivalent to `m_f(t)` for all `t`. + + + function_output_iterator& operator++(); + +[*Returns: ] `*this`. + + + function_output_iterator& operator++(int); + +[*Returns: ] `*this`. + +[endsect] diff --git a/libs/iterator/doc/quickbook/indirect_iterator.qbk b/libs/iterator/doc/quickbook/indirect_iterator.qbk new file mode 100644 index 00000000..89ab38cb --- /dev/null +++ b/libs/iterator/doc/quickbook/indirect_iterator.qbk @@ -0,0 +1,254 @@ +[section:indirect Indirect Iterator] + +`indirect_iterator` adapts an iterator by applying an +*extra* dereference inside of `operator*()`. For example, this +iterator adaptor makes it possible to view a container of pointers +(e.g. `list`) as if it were a container of the pointed-to type +(e.g. `list`). `indirect_iterator` depends on two +auxiliary traits, `pointee` and `indirect_reference`, to +provide support for underlying iterators whose `value_type` is +not an iterator. + +[h2 Example] + +This example prints an array of characters, using +`indirect_iterator` to access the array of characters through an +array of pointers. Next `indirect_iterator` is used with the +`transform` algorithm to copy the characters (incremented by one) to +another array. A constant indirect iterator is used for the source and +a mutable indirect iterator is used for the destination. The last part +of the example prints the original array of characters, but this time +using the `make_indirect_iterator` helper function. + + + char characters[] = "abcdefg"; + const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char + char* pointers_to_chars[N]; // at the end. + for (int i = 0; i < N; ++i) + pointers_to_chars[i] = &characters[i]; + + // Example of using indirect_iterator + + boost::indirect_iterator + indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N); + + std::copy(indirect_first, indirect_last, std::ostream_iterator(std::cout, ",")); + std::cout << std::endl; + + + // Example of making mutable and constant indirect iterators + + char mutable_characters[N]; + char* pointers_to_mutable_chars[N]; + for (int j = 0; j < N; ++j) + pointers_to_mutable_chars[j] = &mutable_characters[j]; + + boost::indirect_iterator mutable_indirect_first(pointers_to_mutable_chars), + mutable_indirect_last(pointers_to_mutable_chars + N); + boost::indirect_iterator const_indirect_first(pointers_to_chars), + const_indirect_last(pointers_to_chars + N); + + std::transform(const_indirect_first, const_indirect_last, + mutable_indirect_first, std::bind(std::plus(), 1, std::placeholders::_1)); + + std::copy(mutable_indirect_first, mutable_indirect_last, + std::ostream_iterator(std::cout, ",")); + std::cout << std::endl; + + + // Example of using make_indirect_iterator() + + std::copy(boost::make_indirect_iterator(pointers_to_chars), + boost::make_indirect_iterator(pointers_to_chars + N), + std::ostream_iterator(std::cout, ",")); + std::cout << std::endl; + + +The output is: + +[pre +a,b,c,d,e,f,g, +b,c,d,e,f,g,h, +a,b,c,d,e,f,g, +] + +The source code for this example can be found +[example_link indirect_iterator_example.cpp..here]. + + +[h2 Reference] + +[h3 Synopsis] + + template < + class Iterator + , class Value = use_default + , class CategoryOrTraversal = use_default + , class Reference = use_default + , class Difference = use_default + > + class indirect_iterator + { + public: + typedef /* see below */ value_type; + typedef /* see below */ reference; + typedef /* see below */ pointer; + typedef /* see below */ difference_type; + typedef /* see below */ iterator_category; + + indirect_iterator(); + indirect_iterator(Iterator x); + + template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 // exposition + ); + + Iterator const& base() const; + reference operator*() const; + indirect_iterator& operator++(); + indirect_iterator& operator--(); + private: + Iterator m_iterator; // exposition + }; + + +The member types of `indirect_iterator` are defined according to +the following pseudo-code, where `V` is +`iterator_traits::value_type` + +[pre + if (Value is use_default) then + typedef remove_const::type>::type value_type; + else + typedef remove_const::type value_type; + + if (Reference is use_default) then + if (Value is use_default) then + typedef indirect_reference::type reference; + else + typedef Value& reference; + else + typedef Reference reference; + + if (Value is use_default) then + typedef pointee::type\* pointer; + else + typedef Value\* pointer; + + if (Difference is use_default) + typedef iterator_traits::difference_type difference_type; + else + typedef Difference difference_type; + + if (CategoryOrTraversal is use_default) + typedef *iterator-category* ( + iterator_traversal::type,`reference`,`value_type` + ) iterator_category; + else + typedef *iterator-category* ( + CategoryOrTraversal,`reference`,`value_type` + ) iterator_category; +] + + +[h3 Requirements] + +The expression `*v`, where `v` is an object of +`iterator_traits::value_type`, shall be valid +expression and convertible to `reference`. `Iterator` shall +model the traversal concept indicated by `iterator_category`. +`Value`, `Reference`, and `Difference` shall be chosen so +that `value_type`, `reference`, and `difference_type` meet +the requirements indicated by `iterator_category`. + +[blurb Note: there are further requirements on the +`iterator_traits::value_type` if the `Value` +parameter is not `use_default`, as implied by the algorithm for +deducing the default for the `value_type` member.] + +[h3 Concepts] + +In addition to the concepts indicated by `iterator_category` +and by `iterator_traversal::type`, a +specialization of `indirect_iterator` models the following +concepts, Where `v` is an object of +`iterator_traits::value_type`: + +Readable Iterator if `reference(*v)` is convertible to +`value_type`. + +Writable Iterator if `reference(*v) = t` is a valid +expression (where `t` is an object of type +`indirect_iterator::value_type`) + +Lvalue Iterator if `reference` is a reference type. + +`indirect_iterator` is interoperable with +`indirect_iterator` if and only if `X` is +interoperable with `Y`. + +[h3 Operations] + +In addition to the operations required by the concepts described +above, specializations of `indirect_iterator` provide the +following operations: + + + indirect_iterator(); + +[*Requires: ] `Iterator` must be Default Constructible.[br] +[*Effects: ] Constructs an instance of `indirect_iterator` with + a default-constructed `m_iterator`. + + + indirect_iterator(Iterator x); + +[*Effects: ] Constructs an instance of `indirect_iterator` with + `m_iterator` copy constructed from `x`. + + + template < + class Iterator2, class Value2, unsigned Access, class Traversal + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Access, Traversal, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 // exposition + ); + +[*Requires: ] `Iterator2` is implicitly convertible to `Iterator`.[br] +[*Effects: ] Constructs an instance of `indirect_iterator` whose + `m_iterator` subobject is constructed from `y.base()`. + + + Iterator const& base() const; + +[*Returns: ] `m_iterator` + + + reference operator*() const; + +[*Returns: ] `**m_iterator` + + + indirect_iterator& operator++(); + +[*Effects: ] `++m_iterator`[br] +[*Returns: ] `*this` + + + indirect_iterator& operator--(); + +[*Effects: ] `--m_iterator`[br] +[*Returns: ] `*this` + +[endsect] diff --git a/libs/iterator/doc/quickbook/iterator.qbk b/libs/iterator/doc/quickbook/iterator.qbk new file mode 100644 index 00000000..a653d14f --- /dev/null +++ b/libs/iterator/doc/quickbook/iterator.qbk @@ -0,0 +1,307 @@ +[library Boost.Iterator + [/ version 1.0.1] + [quickbook 1.6] + [authors [Abrahams, David], [Siek, Jeremy], [Witt, Thomas]] + [copyright 2003 2005 David Abrahams Jeremy Siek Thomas Witt] + [category iterator] + [id iterator] + [dirname iterator] + [purpose + ] + [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 + ) + ] +] + +[/ QuickBook Document version 1.0 ] + +[/ Images ] + +[def _note_ [$images/note.png]] +[def _alert_ [$images/caution.png]] +[def _detail_ [$images/note.png]] +[def _tip_ [$images/tip.png]] + +[/ Links ] + +[def _iterator_ [@../../../iterator/doc/index.html Boost.Iterator]] +[def _concept_check_ [@../../../concept_check/index.html Boost.ConceptCheck]] +[template example_link[name descr]''''''[descr]''''''] + +[template sub[x]''''''[x]''''''] + +[section:intro Introduction] + +[def _concepts_ [@http://www.boost.org/more/generic_programming.html#concept concepts]] + +The Boost Iterator Library contains two parts. The first +is a system of _concepts_ which extend the C++ standard +iterator requirements. The second is a framework of +components for building iterators based on these +extended concepts and includes several useful iterator +adaptors. The extended iterator concepts have been +carefully designed so that old-style iterators +can fit in the new concepts and so that new-style +iterators will be compatible with old-style algorithms, +though algorithms may need to be updated if they want to +take full advantage of the new-style iterator +capabilities. Several components of this library have +been accepted into the C++ standard technical report. +The components of the Boost Iterator Library replace the +older Boost Iterator Adaptor Library. + + +[h2 New-Style Iterators] + +[def _N1185_ [@http://www.gotw.ca/publications/N1185.pdf N1185]] +[def _N1211_ [@http://www.gotw.ca/publications/N1211.pdf N1211]] +[def _GOTW_50_ [@http://www.gotw.ca/gotw/050.htm Guru of the Week]] + +The iterator categories defined in C++98 are extremely limiting +because they bind together two orthogonal concepts: traversal and +element access. For example, because a random access iterator is +required to return a reference (and not a proxy) when dereferenced, +it is impossible to capture the capabilities of +`vector::iterator` using the C++98 categories. This is the +infamous "`vector` is not a container, and its iterators +aren't random access iterators", debacle about which Herb Sutter +wrote two papers for the standards comittee (_N1185_ and _N1211_), +and a _GOTW_50_. New-style iterators go well beyond +patching up `vector`, though: there are lots of other +iterators already in use which can't be adequately represented by +the existing concepts. For details about the new iterator +concepts, see our [@../new-iter-concepts.html Standard Proposal for New-Style Iterators]. + +[h2 Iterator Facade and Adaptor] + +[/ +[def _facade_ [link iterator.generic.facade facade]] +[def _adaptor_ [link iterator.generic.adaptor adaptor]] +] +[def _facade_ [@../iterator_facade.html facade]] +[def _adaptor_ [@../iterator_adaptor.html adaptor]] + +Writing standard-conforming iterators is tricky, but the need comes +up often. In order to ease the implementation of new iterators, +the Boost.Iterator library provides the _facade_ class template, +which implements many useful defaults and compile-time checks +designed to help the iterator author ensure that his iterator is +correct. + +It is also common to define a new iterator that is similar to some +underlying iterator or iterator-like type, but that modifies some +aspect of the underlying type's behavior. For that purpose, the +library supplies the _adaptor_ class template, which is specially +designed to take advantage of as much of the underlying type's +behavior as possible. + +Both _facade_ and _adaptor_ as well as many of the [link iterator.specialized specialized +adaptors] mentioned below have been proposed for standardization +([@../facade-and-adaptor.html Standard Proposal For Iterator Facade and Adaptor]). + +[h2 Specialized Adaptors] + +The iterator library supplies a useful suite of standard-conforming +iterator templates based on the Boost [link +iterator.intro.iterator_facade_and_adaptor iterator facade and adaptor] +templates. + +[def _counting_ [link iterator.specialized.counting `counting_iterator`]] +[def _filter_ [link iterator.specialized.filter `filter_iterator`]] +[def _function_input_ [@../function_input_iterator.html `function_input_iterator`]] +[def _function_output_ [link iterator.specialized.function_output `function_output_iterator`]] +[def _generator_ [@../generator_iterator.htm `generator_iterator`]] +[def _indirect_ [link iterator.specialized.indirect `indirect_iterator`]] +[def _permutation_ [link iterator.specialized.permutation `permutation_iterator`]] +[def _reverse_ [link iterator.specialized.reverse `reverse_iterator`]] +[def _shared_ [link iterator.specialized.shared_container `shared_container_iterator`]] +[def _transform_ [link iterator.specialized.transform `transform_iterator`]] +[def _zip_ [link iterator.specialized.zip `zip_iterator`]] + +[def _shared_ptr_ [@../../smart_ptr/shared_ptr.htm `shared_ptr`]] + +* _counting_: an iterator over a sequence of consecutive values. + Implements a "lazy sequence" + +* _filter_: an iterator over the subset of elements of some + sequence which satisfy a given predicate + +* _function_input_: an input iterator wrapping a generator (nullary + function object); each time the iterator is dereferenced, the function object + is called to get the value to return. + +* _function_output_: an output iterator wrapping a unary function + object; each time an element is written into the dereferenced + iterator, it is passed as a parameter to the function object. + +* _generator_: an input iterator wrapping a generator (nullary + function object); each time the iterator is dereferenced, the function object + is called to get the value to return. An outdated analogue of _function_input_. + +* _indirect_: an iterator over the objects *pointed-to* by the + elements of some sequence. + +* _permutation_: an iterator over the elements of some random-access + sequence, rearranged according to some sequence of integer indices. + +* _reverse_: an iterator which traverses the elements of some + bidirectional sequence in reverse. Corrects many of the + shortcomings of C++98's `std::reverse_iterator`. + +* _shared_: an iterator over elements of a container whose + lifetime is maintained by a _shared_ptr_ stored in the iterator. + +* _transform_: an iterator over elements which are the result of + applying some functional transformation to the elements of an + underlying sequence. This component also replaces the old + `projection_iterator_adaptor`. + +* _zip_: an iterator over tuples of the elements at corresponding + positions of heterogeneous underlying iterators. + +[h2 Iterator Utilities] + +[h3 Traits] + +[def _pointee_ [link iterator.utilities.traits `pointee.hpp`]] +[def _iterator_traits_ [link iterator.utilities.iterator_traits `iterator_traits.hpp`]] +[def _interoperable_ [@../interoperable.html `interoperable.hpp`]] +[def _MPL_ [@../../mpl/doc/index.html [*MPL]]] + +* _pointee_: Provides the capability to deduce the referent types + of pointers, smart pointers and iterators in generic code. Used + in _indirect_. + +* _iterator_traits_: Provides _MPL_ compatible metafunctions which + retrieve an iterator's traits. Also corrects for the deficiencies + of broken implementations of `std::iterator_traits`. + +[/ +* _interoperable_: Provides an _MPL_ compatible metafunction for + testing iterator interoperability +] + +[h3 Testing and Concept Checking] + +[def _iterator_concepts_ [link iterator.concepts `iterator_concepts.hpp`]] +[def _iterator_archetypes_ [link iterator.utilities.archetypes `iterator_archetypes.hpp`]] + +* _iterator_concepts_: Concept checking classes for the new iterator concepts. + +* _iterator_archetypes_: Concept archetype classes for the new iterators concepts. + +[h2 Iterator Algorithms] + +The library provides a number of generic algorithms for use with iterators. These +algorithms take advantage of the new concepts defined by the library to provide +better performance and functionality. + +[def _advance_ [link iterator.algorithms.advance `advance.hpp`]] +[def _distance_ [link iterator.algorithms.distance `distance.hpp`]] +[def _next_prior_ [link iterator.algorithms.next_prior `next_prior.hpp`]] + +* _advance_: Provides `advance()` function for advancing an iterator a given number + of positions forward or backward. + +* _distance_: Provides `distance()` function for computing distance between two + iterators. + +* _next_prior_: Provides `next()` and `prior()` functions for obtaining + next and prior iterators to a given iterator. The functions are also compatible + with non-iterator types. + +[endsect] + +[include concepts.qbk] + +[section:generic Generic Iterators] + +[include facade.qbk] + +[include adaptor.qbk] + +[endsect] + +[include specialized_adaptors.qbk] + +[section:utilities Utilities] + +[include archetypes.qbk] + +[include concept_checking.qbk] + +[include iterator_traits.qbk] + +[include type_traits.qbk] + +[endsect] + +[include algorithms.qbk] + +[section:upgrading Upgrading from the old Boost Iterator Adaptor Library] + +[def _type_generator_ [@http://www.boost.org/more/generic_programming.html#type_generator type generator]] + +If you have been using the old Boost Iterator Adaptor library to +implement iterators, you probably wrote a `Policies` class which +captures the core operations of your iterator. In the new library +design, you'll move those same core operations into the body of the +iterator class itself. If you were writing a family of iterators, +you probably wrote a _type_generator_ to build the +`iterator_adaptor` specialization you needed; in the new library +design you don't need a type generator (though may want to keep it +around as a compatibility aid for older code) because, due to the +use of the Curiously Recurring Template Pattern (CRTP) [Cop95]_, +you can now define the iterator class yourself and acquire +functionality through inheritance from `iterator_facade` or +`iterator_adaptor`. As a result, you also get much finer control +over how your iterator works: you can add additional constructors, +or even override the iterator functionality provided by the +library. + + +If you're looking for the old `projection_iterator` component, +its functionality has been merged into _transform_iterator_: as +long as the function object's `result_type` (or the `Reference` +template argument, if explicitly specified) is a true reference +type, _transform_iterator_ will behave like +`projection_iterator` used to. + +[endsect] + +[section:history History] + +In 2000 Dave Abrahams was writing an iterator for a container of +pointers, which would access the pointed-to elements when +dereferenced. Naturally, being a library writer, he decided to +generalize the idea and the Boost Iterator Adaptor library was born. +Dave was inspired by some writings of Andrei Alexandrescu and chose a +policy based design (though he probably didn't capture Andrei's idea +very well - there was only one policy class for all the iterator's +orthogonal properties). Soon Jeremy Siek realized he would need the +library and they worked together to produce a "Boostified" version, +which was reviewed and accepted into the library. They wrote a paper +and made several important revisions of the code. + +Eventually, several shortcomings of the older library began to make +the need for a rewrite apparent. Dave and Jeremy started working +at the Santa Cruz C++ committee meeting in 2002, and had quickly +generated a working prototype. At the urging of Mat Marcus, they +decided to use the GenVoca/CRTP pattern approach, and moved the +policies into the iterator class itself. Thomas Witt expressed +interest and became the voice of strict compile-time checking for +the project, adding uses of the SFINAE technique to eliminate false +converting constructors and operators from the overload set. He +also recognized the need for a separate `iterator_facade`, and +factored it out of `iterator_adaptor`. Finally, after a +near-complete rewrite of the prototype, they came up with the +library you see today. + +[:\[Coplien, 1995\] Coplien, J., Curiously Recurring Template + Patterns, C++ Report, February 1995, pp. 24-27.] + +[endsect] diff --git a/libs/iterator/doc/quickbook/iterator_traits.qbk b/libs/iterator/doc/quickbook/iterator_traits.qbk new file mode 100644 index 00000000..90a48e89 --- /dev/null +++ b/libs/iterator/doc/quickbook/iterator_traits.qbk @@ -0,0 +1,54 @@ +[section:iterator_traits Iterator Traits] + +`std::iterator_traits` provides access to five associated types +of any iterator: its `value_type`, `reference`, `pointer`, +`iterator_category`, and `difference_type`. Unfortunately, +such a "multi-valued" traits template can be difficult to use in a +metaprogramming context. `` +provides access to these types using a standard metafunctions_. + +[h2 Synopsis] + +Header ``: + + template + struct iterator_value + { + typedef typename + std::iterator_traits::value_type + type; + }; + + template + struct iterator_reference + { + typedef typename + std::iterator_traits::reference + type; + }; + + template + struct iterator_pointer + { + typedef typename + std::iterator_traits::pointer + type; + }; + + template + struct iterator_difference + { + typedef typename + detail::iterator_traits::difference_type + type; + }; + + template + struct iterator_category + { + typedef typename + detail::iterator_traits::iterator_category + type; + }; + +[endsect] diff --git a/libs/iterator/doc/quickbook/permutation_iterator.qbk b/libs/iterator/doc/quickbook/permutation_iterator.qbk new file mode 100644 index 00000000..ce128180 --- /dev/null +++ b/libs/iterator/doc/quickbook/permutation_iterator.qbk @@ -0,0 +1,207 @@ +[section:permutation Permutation Iterator] + +The permutation iterator adaptor provides a permuted view of a given +range. That is, the view includes every element of the given range but +in a potentially different order. The adaptor takes two arguments: + +* an iterator to the range V on which the permutation + will be applied +* the reindexing scheme that defines how the + elements of V will be permuted. + +Note that the permutation iterator is not limited to strict +permutations of the given range V. The distance between begin and end +of the reindexing iterators is allowed to be smaller compared to the +size of the range V, in which case the permutation iterator only +provides a permutation of a subrange of V. The indexes neither need +to be unique. In this same context, it must be noted that the past the +end permutation iterator is completely defined by means of the +past-the-end iterator to the indices. + +[h2 Example] + + using namespace boost; + int i = 0; + + typedef std::vector< int > element_range_type; + typedef std::list< int > index_type; + + static const int element_range_size = 10; + static const int index_size = 4; + + element_range_type elements( element_range_size ); + for(element_range_type::iterator el_it = elements.begin() ; el_it != elements.end() ; ++el_it) + *el_it = std::distance(elements.begin(), el_it); + + index_type indices( index_size ); + for(index_type::iterator i_it = indices.begin() ; i_it != indices.end() ; ++i_it ) + *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it); + std::reverse( indices.begin(), indices.end() ); + + typedef permutation_iterator< element_range_type::iterator, index_type::iterator > permutation_type; + permutation_type begin = make_permutation_iterator( elements.begin(), indices.begin() ); + permutation_type it = begin; + permutation_type end = make_permutation_iterator( elements.begin(), indices.end() ); + + std::cout << "The original range is : "; + std::copy( elements.begin(), elements.end(), std::ostream_iterator< int >( std::cout, " " ) ); + std::cout << "\n"; + + std::cout << "The reindexing scheme is : "; + std::copy( indices.begin(), indices.end(), std::ostream_iterator< int >( std::cout, " " ) ); + std::cout << "\n"; + + std::cout << "The permutated range is : "; + std::copy( begin, end, std::ostream_iterator< int >( std::cout, " " ) ); + std::cout << "\n"; + + std::cout << "Elements at even indices in the permutation : "; + it = begin; + for(i = 0; i < index_size / 2 ; ++i, it+=2 ) std::cout << *it << " "; + std::cout << "\n"; + + std::cout << "Permutation backwards : "; + it = begin + (index_size); + assert( it != begin ); + for( ; it-- != begin ; ) std::cout << *it << " "; + std::cout << "\n"; + + std::cout << "Iterate backward with stride 2 : "; + it = begin + (index_size - 1); + for(i = 0 ; i < index_size / 2 ; ++i, it-=2 ) std::cout << *it << " "; + std::cout << "\n"; + + +The output is: + +[pre +The original range is : 0 1 2 3 4 5 6 7 8 9 +The reindexing scheme is : 9 8 7 6 +The permutated range is : 9 8 7 6 +Elements at even indices in the permutation : 9 7 +Permutation backwards : 6 7 8 9 +Iterate backward with stride 2 : 6 8 +] + +The source code for this example can be found +[example_link permutation_iter_example.cpp..here]. + +[h2 Reference] + +[h3 Synopsis] + + template< class ElementIterator + , class IndexIterator + , class ValueT = use_default + , class CategoryT = use_default + , class ReferenceT = use_default + , class DifferenceT = use_default > + class permutation_iterator + { + public: + permutation_iterator(); + explicit permutation_iterator(ElementIterator x, IndexIterator y); + + template< class OEIter, class OIIter, class V, class C, class R, class D > + permutation_iterator( + permutation_iterator const& r + , typename enable_if_convertible::type* = 0 + , typename enable_if_convertible::type* = 0 + ); + reference operator*() const; + permutation_iterator& operator++(); + ElementIterator const& base() const; + private: + ElementIterator m_elt; // exposition only + IndexIterator m_order; // exposition only + }; + + template + permutation_iterator + make_permutation_iterator( ElementIterator e, IndexIterator i); + + +[h3 Requirements] + +`ElementIterator` shall model Random Access Traversal Iterator. +`IndexIterator` shall model Readable Iterator. The value type of +the `IndexIterator` must be convertible to the difference type of +`ElementIterator`. + +[h3 Concepts] + +`permutation_iterator` models the same iterator traversal concepts +as `IndexIterator` and the same iterator access concepts as +`ElementIterator`. + +If `IndexIterator` models Single Pass Iterator and +`ElementIterator` models Readable Iterator then +`permutation_iterator` models Input Iterator. + +If `IndexIterator` models Forward Traversal Iterator and +`ElementIterator` models Readable Lvalue Iterator then +`permutation_iterator` models Forward Iterator. + +If `IndexIterator` models Bidirectional Traversal Iterator and +`ElementIterator` models Readable Lvalue Iterator then +`permutation_iterator` models Bidirectional Iterator. + +If `IndexIterator` models Random Access Traversal Iterator and +`ElementIterator` models Readable Lvalue Iterator then +`permutation_iterator` models Random Access Iterator. + +`permutation_iterator` is interoperable +with `permutation_iterator` if and only if +`X` is interoperable with `Y` and `E1` is convertible +to `E2`. + +[h3 Operations] + +In addition to those operations required by the concepts that +`permutation_iterator` models, `permutation_iterator` provides the +following operations. + + permutation_iterator(); + +[*Effects: ] Default constructs `m_elt` and `m_order`. + + + explicit permutation_iterator(ElementIterator x, IndexIterator y); + +[*Effects: ] Constructs `m_elt` from `x` and `m_order` from `y`. + + + template< class OEIter, class OIIter, class V, class C, class R, class D > + permutation_iterator( + permutation_iterator const& r + , typename enable_if_convertible::type* = 0 + , typename enable_if_convertible::type* = 0 + ); + +[*Effects: ] Constructs `m_elt` from `r.m_elt` and + `m_order` from `y.m_order`. + + + reference operator*() const; + +[*Returns: ] `*(m_elt + *m_order)` + + + permutation_iterator& operator++(); + +[*Effects: ] `++m_order`[br] +[*Returns: ] `*this` + + + ElementIterator const& base() const; + +[*Returns: ] `m_order` + + + template + permutation_iterator + make_permutation_iterator(ElementIterator e, IndexIterator i); + +[*Returns: ] `permutation_iterator(e, i)` + +[endsect] diff --git a/libs/iterator/doc/quickbook/reverse_iterator.qbk b/libs/iterator/doc/quickbook/reverse_iterator.qbk new file mode 100644 index 00000000..22257cdb --- /dev/null +++ b/libs/iterator/doc/quickbook/reverse_iterator.qbk @@ -0,0 +1,159 @@ +[section:reverse Reverse Iterator] + +The reverse iterator adaptor iterates through the adapted iterator +range in the opposite direction. + +[h2 Example] + +The following example prints an array of characters in reverse order +using `reverse_iterator`. + + char letters_[] = "hello world!"; + const int N = sizeof(letters_)/sizeof(char) - 1; + typedef char* base_iterator; + base_iterator letters(letters_); + std::cout << "original sequence of letters:\t\t\t" << letters_ << std::endl; + + boost::reverse_iterator + reverse_letters_first(letters + N), + reverse_letters_last(letters); + + std::cout << "sequence in reverse order:\t\t\t"; + std::copy(reverse_letters_first, reverse_letters_last, + std::ostream_iterator(std::cout)); + std::cout << std::endl; + + std::cout << "sequence in double-reversed (normal) order:\t"; + std::copy(boost::make_reverse_iterator(reverse_letters_last), + boost::make_reverse_iterator(reverse_letters_first), + std::ostream_iterator(std::cout)); + std::cout << std::endl; + + + +The output is: + +[pre +original sequence of letters: hello world! +sequence in reverse order: !dlrow olleh +sequence in double-reversed (normal) order: hello world! +] + +The source code for this example can be found +[example_link reverse_iterator_example.cpp..here]. + +[h2 Reference] + +[h3 Synopsis] + + template + class reverse_iterator + { + public: + typedef iterator_traits::value_type value_type; + typedef iterator_traits::reference reference; + typedef iterator_traits::pointer pointer; + typedef iterator_traits::difference_type difference_type; + typedef /* see below */ iterator_category; + + reverse_iterator() {} + explicit reverse_iterator(Iterator x) ; + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::type* = 0 // exposition + ); + Iterator const& base() const; + reference operator*() const; + reverse_iterator& operator++(); + reverse_iterator& operator--(); + private: + Iterator m_iterator; // exposition + }; + + +If `Iterator` models Random Access Traversal Iterator and Readable +Lvalue Iterator, then `iterator_category` is convertible to +`random_access_iterator_tag`. Otherwise, if +`Iterator` models Bidirectional Traversal Iterator and Readable +Lvalue Iterator, then `iterator_category` is convertible to +`bidirectional_iterator_tag`. Otherwise, `iterator_category` is +convertible to `input_iterator_tag`. + +[h3 Requirements] + +`Iterator` must be a model of Bidirectional Traversal Iterator. The +type `iterator_traits::reference` must be the type of +`*i`, where `i` is an object of type `Iterator`. + +[h3 Concepts] + +A specialization of `reverse_iterator` models the same iterator +traversal and iterator access concepts modeled by its `Iterator` +argument. In addition, it may model old iterator concepts +specified in the following table: + +[table Categories + [[If `I` models ][then `reverse_iterator` models]] + [[Readable Lvalue Iterator, Bidirectional Traversal Iterator][Bidirectional Iterator]] + [[Writable Lvalue Iterator, Bidirectional Traversal Iterator][Mutable Bidirectional Iterator]] + [[Readable Lvalue Iterator, Random Access Traversal Iterator][Random Access Iterator]] + [[Writable Lvalue Iterator, Random Access Traversal Iterator][Mutable Random Access Iterator]] +] + +`reverse_iterator` is interoperable with +`reverse_iterator` if and only if `X` is interoperable with +`Y`. + +[h3 Operations] + +In addition to the operations required by the concepts modeled by +`reverse_iterator`, `reverse_iterator` provides the following +operations. + + reverse_iterator(); + +[*Requires: ] `Iterator` must be Default Constructible.[br] +[*Effects: ] Constructs an instance of `reverse_iterator` with `m_iterator` + default constructed. + + explicit reverse_iterator(Iterator x); + +[*Effects: ] Constructs an instance of `reverse_iterator` with + `m_iterator` copy constructed from `x`. + + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::type* = 0 // exposition + ); + +[*Requires: ] `OtherIterator` is implicitly convertible to `Iterator`.[br] +[*Effects: ] Constructs instance of `reverse_iterator` whose + `m_iterator` subobject is constructed from `y.base()`. + + + + Iterator const& base() const; + +[*Returns: ] `m_iterator` + + + reference operator*() const; + +[*Effects: ] Iterator tmp = m_iterator; return *--tmp; + + + reverse_iterator& operator++(); + +[*Effects: ] `--m_iterator`[br] +[*Returns: ] `*this` + + reverse_iterator& operator--(); + +[*Effects: ] `++m_iterator`[br] +[*Returns: ] `*this` + +[endsect] diff --git a/libs/iterator/doc/quickbook/shared_container_iterator.qbk b/libs/iterator/doc/quickbook/shared_container_iterator.qbk new file mode 100644 index 00000000..b87678ab --- /dev/null +++ b/libs/iterator/doc/quickbook/shared_container_iterator.qbk @@ -0,0 +1,249 @@ +[section:shared_container Shared Container Iterator] + +Defined in header [@../../../boost/shared_container_iterator.hpp `boost/shared_container_iterator.hpp`]. + +The purpose of the shared container iterator is to attach the lifetime +of a container to the lifetime of its iterators. In other words, the +container will not be deleted until after all its iterators are +destroyed. The shared container iterator is typically used to +implement functions that return iterators over a range of objects that +only need to exist for the lifetime of the iterators. By returning a +pair of shared iterators from a function, the callee can return a +heap-allocated range of objects whose lifetime is automatically +managed. + +The shared container iterator augments an iterator over a shared +container. It maintains a reference count on the shared container. If +only shared container iterators hold references to the container, the +container's lifetime will end when the last shared container iterator +over it is destroyed. In any case, the shared container is guaranteed +to persist beyond the lifetime of all the iterators. In all other +ways, the shared container iterator behaves the same as its base +iterator. + +[h2 Synopsis] + + namespace boost { + template + class shared_container_iterator; + + template + shared_container_iterator + make_shared_container_iterator(typename Container::iterator base, + boost::shared_ptr const& container); + + std::pair< + typename shared_container_iterator, + typename shared_container_iterator + > + make_shared_container_range(boost::shared_ptr const& container); + } + +[section:shared_container_type The Shared Container Iterator Type] + + template class shared_container_iterator; + +The class template `shared_container_iterator` is the shared container +iterator type. The `Container` template type argument must model the +[@http://www.sgi.com/tech/stl/Container.html Container] concept. + +[h2 Example] + +The following example illustrates how to create an iterator that +regulates the lifetime of a reference counted `std::vector`. Though the +original shared pointer `ints` ceases to exist after `set_range()` +returns, the `shared_counter_iterator` objects maintain references to +the underlying vector and thereby extend the container's lifetime. + +[example_link shared_iterator_example1.cpp..`shared_iterator_example1.cpp`]: + + #include "shared_container_iterator.hpp" + #include "boost/shared_ptr.hpp" + #include + #include + #include + + typedef boost::shared_container_iterator< std::vector > iterator; + + + void set_range(iterator& i, iterator& end) { + + boost::shared_ptr< std::vector > ints(new std::vector()); + + ints->push_back(0); + ints->push_back(1); + ints->push_back(2); + ints->push_back(3); + ints->push_back(4); + ints->push_back(5); + + i = iterator(ints->begin(),ints); + end = iterator(ints->end(),ints); + } + + + int main() { + + iterator i,end; + + set_range(i,end); + + std::copy(i,end,std::ostream_iterator(std::cout,",")); + std::cout.put('\n'); + + return 0; + } + +The output from this part is: + +[pre +0,1,2,3,4,5, +] + +[table Template Parameters + [[Parameter][Description]] + [[Container][The type of the container that we wish to iterate over. It must be a model of the Container concept.]] +] + +[h2 Concepts] + +The `shared_container_iterator` type models the same iterator concept +as the base iterator (`Container::iterator`). + +[h2 Operations] + +The `shared_container_iterator` type implements the member functions +and operators required of the +[@http://www.sgi.com/tech/stl/RandomAccessIterator.html Random Access +Iterator] concept, though only operations defined for the base +iterator will be valid. In addition it has the following constructor: + + shared_container_iterator(Container::iterator const& it, + boost::shared_ptr const& container) + +[endsect] + +[section:shared_container_object_generator The Shared Container Iterator Object Generator] + + template + shared_container_iterator + make_shared_container_iterator(Container::iterator base, + boost::shared_ptr const& container) + +This function provides an alternative to directly constructing a +`shared_container_iterator`. Using the object generator, a +`shared_container_iterator` can be created and passed to a function without +explicitly specifying its type. + +[h2 Example] + +This example, similar to the previous, +uses `make_shared_container_iterator()` to create the iterators. + +[example_link shared_iterator_example2.cpp..`shared_iterator_example2.cpp`]: + + #include "shared_container_iterator.hpp" + #include "boost/shared_ptr.hpp" + #include + #include + #include + #include + + + template + void print_range_nl (Iterator begin, Iterator end) { + typedef typename std::iterator_traits::value_type val; + std::copy(begin,end,std::ostream_iterator(std::cout,",")); + std::cout.put('\n'); + } + + + int main() { + + typedef boost::shared_ptr< std::vector > ints_t; + { + ints_t ints(new std::vector()); + + ints->push_back(0); + ints->push_back(1); + ints->push_back(2); + ints->push_back(3); + ints->push_back(4); + ints->push_back(5); + + print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints), + boost::make_shared_container_iterator(ints->end(),ints)); + } + + + + return 0; + } + +Observe that the `shared_container_iterator` type is never explicitly +named. The output from this example is the same as the previous. + +[endsect] + +[section:shared_container_generator The Shared Container Iterator Range Generator] + + template + std::pair< + shared_container_iterator, + shared_container_iterator + > + make_shared_container_range(boost::shared_ptr const& container); + Class shared_container_iterator is meant primarily to return, using iterators, a range of values that we can guarantee will be alive as long as the iterators are. This is a convenience function to do just that. It is equivalent to + std::make_pair(make_shared_container_iterator(container->begin(),container), + make_shared_container_iterator(container->end(),container)); + +[h2 Example] + +In the following example, a range of values is returned as a pair of shared_container_iterator objects. + +[example_link shared_iterator_example3.cpp..`shared_iterator_example3.cpp`]: + + #include "shared_container_iterator.hpp" + #include "boost/shared_ptr.hpp" + #include "boost/tuple/tuple.hpp" // for boost::tie + #include // for std::copy + #include + #include + + + typedef boost::shared_container_iterator< std::vector > iterator; + + std::pair + return_range() { + boost::shared_ptr< std::vector > range(new std::vector()); + range->push_back(0); + range->push_back(1); + range->push_back(2); + range->push_back(3); + range->push_back(4); + range->push_back(5); + return boost::make_shared_container_range(range); + } + + + int main() { + + + iterator i,end; + + boost::tie(i,end) = return_range(); + + std::copy(i,end,std::ostream_iterator(std::cout,",")); + std::cout.put('\n'); + + return 0; + } + +Though the range object only lives for the duration of the +`return_range` call, the reference counted `std::vector` will live +until `i` and `end` are both destroyed. The output from this example is +the same as the previous two. + +[endsect] + +[endsect] diff --git a/libs/iterator/doc/quickbook/specialized_adaptors.qbk b/libs/iterator/doc/quickbook/specialized_adaptors.qbk new file mode 100644 index 00000000..4f3c67a7 --- /dev/null +++ b/libs/iterator/doc/quickbook/specialized_adaptors.qbk @@ -0,0 +1,21 @@ +[section:specialized Specialized Adaptors] + +[include ./counting_iterator.qbk] + +[include ./filter_iterator.qbk] + +[include ./function_output_iterator.qbk] + +[include ./indirect_iterator.qbk] + +[include ./permutation_iterator.qbk] + +[include ./reverse_iterator.qbk] + +[include ./shared_container_iterator.qbk] + +[include ./transform_iterator.qbk] + +[include ./zip_iterator.qbk] + +[endsect] diff --git a/libs/iterator/doc/quickbook/transform_iterator.qbk b/libs/iterator/doc/quickbook/transform_iterator.qbk new file mode 100644 index 00000000..e4a6a3ea --- /dev/null +++ b/libs/iterator/doc/quickbook/transform_iterator.qbk @@ -0,0 +1,216 @@ +[section:transform Transform Iterator] + +The transform iterator adapts an iterator by modifying the +`operator*` to apply a function object to the result of +dereferencing the iterator and returning the result. + + +[h2 Example] + + +This is a simple example of using the transform_iterators class to +generate iterators that multiply (or add to) the value returned by +dereferencing the iterator. It would be cooler to use lambda library +in this example. + + int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + const int N = sizeof(x)/sizeof(int); + + typedef boost::binder1st< std::multiplies > Function; + typedef boost::transform_iterator doubling_iterator; + + doubling_iterator i(x, boost::bind1st(std::multiplies(), 2)), + i_end(x + N, boost::bind1st(std::multiplies(), 2)); + + std::cout << "multiplying the array by 2:" << std::endl; + while (i != i_end) + std::cout << *i++ << " "; + std::cout << std::endl; + + std::cout << "adding 4 to each element in the array:" << std::endl; + std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus(), 4)), + boost::make_transform_iterator(x + N, boost::bind1st(std::plus(), 4)), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + +The output is: + +[pre +multiplying the array by 2: +2 4 6 8 10 12 14 16 +adding 4 to each element in the array: +5 6 7 8 9 10 11 12 +] + +The source code for this example can be found +[example_link transform_iterator_example.cpp..here]. + +[h2 Reference] + + +[h3 Synopsis] + + template + class transform_iterator + { + public: + typedef /* see below */ value_type; + typedef /* see below */ reference; + typedef /* see below */ pointer; + typedef iterator_traits::difference_type difference_type; + typedef /* see below */ iterator_category; + + transform_iterator(); + transform_iterator(Iterator const& x, UnaryFunction f); + + template + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition only + , typename enable_if_convertible::type* = 0 // exposition only + ); + UnaryFunction functor() const; + Iterator const& base() const; + reference operator*() const; + transform_iterator& operator++(); + transform_iterator& operator--(); + private: + Iterator m_iterator; // exposition only + UnaryFunction m_f; // exposition only + }; + + +If `Reference` is `use_default` then the `reference` member of +`transform_iterator` is[br] +`result_of::reference)>::type`. +Otherwise, `reference` is `Reference`. + + +If `Value` is `use_default` then the `value_type` member is +`remove_cv >::type`. Otherwise, +`value_type` is `Value`. + + +If `Iterator` models Readable Lvalue Iterator and if `Iterator` +models Random Access Traversal Iterator, then `iterator_category` is +convertible to `random_access_iterator_tag`. Otherwise, if +`Iterator` models Bidirectional Traversal Iterator, then +`iterator_category` is convertible to +`bidirectional_iterator_tag`. Otherwise `iterator_category` is +convertible to `forward_iterator_tag`. If `Iterator` does not +model Readable Lvalue Iterator then `iterator_category` is +convertible to `input_iterator_tag`. + + +[h3 Requirements] + + +The type `UnaryFunction` must be Assignable, Copy Constructible, and +the expression `f(*i)` must be valid where `f` is a const object of +type `UnaryFunction`, `i` is an object of type `Iterator`, and +where the type of `f(*i)` must be +`result_of::reference)>::type`. + + +The argument `Iterator` shall model Readable Iterator. + + +[h3 Concepts] + + +The resulting `transform_iterator` models the most refined of the +following that is also modeled by `Iterator`. + + +* Writable Lvalue Iterator if `transform_iterator::reference` is a non-const reference. + +* Readable Lvalue Iterator if `transform_iterator::reference` is a const reference. + +* Readable Iterator otherwise. + + +The `transform_iterator` models the most refined standard traversal +concept that is modeled by the `Iterator` argument. + + +If `transform_iterator` is a model of Readable Lvalue Iterator then +it models the following original iterator concepts depending on what +the `Iterator` argument models. + + +[table Category +[[If `Iterator` models][then `transform_iterator` models]] +[[Single Pass Iterator][Input Iterator]] +[[Forward Traversal Iterator][Forward Iterator]] +[[Bidirectional Traversal Iterator][Bidirectional Iterator]] +[[Random Access Traversal Iterator][Random Access Iterator]] +] + +If `transform_iterator` models Writable Lvalue Iterator then it is a +mutable iterator (as defined in the old iterator requirements). + + +`transform_iterator` is interoperable with +`transform_iterator` if and only if `X` is +interoperable with `Y`. + +[h3 Operations] + +In addition to the operations required by the [link iterator.specialized.transform.concepts concepts] modeled by +`transform_iterator`, `transform_iterator` provides the following +operations: + + transform_iterator(); + +[*Returns: ] An instance of `transform_iterator` with `m_f` + and `m_iterator` default constructed. + + transform_iterator(Iterator const& x, UnaryFunction f); + +[*Returns: ] An instance of `transform_iterator` with `m_f` + initialized to `f` and `m_iterator` initialized to `x`. + + template + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition only + , typename enable_if_convertible::type* = 0 // exposition only + ); + +[*Returns: ] An instance of `transform_iterator` with `m_f` + initialized to `t.functor()` and `m_iterator` initialized to + `t.base()`.[br] +[*Requires: ] `OtherIterator` is implicitly convertible to `Iterator`. + + + UnaryFunction functor() const; + +[*Returns: ] `m_f` + + + Iterator const& base() const; + +[*Returns: ] `m_iterator` + + + reference operator*() const; + +[*Returns: ] `m_f(*m_iterator)` + + + transform_iterator& operator++(); + +[*Effects: ] `++m_iterator`[br] +[*Returns: ] `*this` + + + transform_iterator& operator--(); + +[*Effects: ] `--m_iterator`[br] +[*Returns: ] `*this` + +[endsect] diff --git a/libs/iterator/doc/quickbook/type_traits.qbk b/libs/iterator/doc/quickbook/type_traits.qbk new file mode 100644 index 00000000..090d3578 --- /dev/null +++ b/libs/iterator/doc/quickbook/type_traits.qbk @@ -0,0 +1,211 @@ +[section:traits Type Traits] + +[h2 Overview] + +Have you ever wanted to write a generic function that can operate +on any kind of dereferenceable object? If you have, you've +probably run into the problem of how to determine the type that the +object "points at": + + template + void f(Dereferenceable p) + { + *what-goes-here?* value = \*p; + ... + } + + +[h2 `pointee`] + +It turns out to be impossible to come up with a fully-general +algorithm to do determine *what-goes-here* directly, but it is +possible to require that `pointee::type` is +correct. Naturally, `pointee` has the same difficulty: it can't +determine the appropriate `::type` reliably for all +`Dereferenceable`\ s, but it makes very good guesses (it works +for all pointers, standard and boost smart pointers, and +iterators), and when it guesses wrongly, it can be specialized as +necessary: + + namespace boost + { + template + struct pointee > + { + typedef T type; + }; + } + +[h2 `indirect_reference`] + +`indirect_reference::type` is rather more specialized than +`pointee`, and is meant to be used to forward the result of +dereferencing an object of its argument type. Most dereferenceable +types just return a reference to their pointee, but some return +proxy references or return the pointee by value. When that +information is needed, call on `indirect_reference`. + +Both of these templates are essential to the correct functioning of +[link iterator.specialized.indirect `indirect_iterator`]. + +[h2 `minimum_category`] + +`minimum_category` takes two iterator categories or two iterator traversal tags +and returns the one that is the weakest (i.e. least advanced). For example: + + static_assert( + is_same< + minimum_category< + std::forward_iterator_tag, + std::random_access_iterator_tag + >::type, + std::forward_iterator_tag + >::value, + "Unexpected minimum_category result" + ); + +[h2 Iterator category and traversal tags manipulation] + +The library provides several utilities to simplify conversions between iterator categories +and traversal tags: + +* `iterator_category_to_traversal::type` - the metafunction takes an iterator category `C` and returns +the corresponding traversal tag. +* `iterator_traversal::type` - a shorthand for `iterator_category_to_traversal::type>::type`. +* `pure_traversal_tag::type` - the metafunction takes a tag `T` which derives from one of the iterator traversal tags +and returns that traversal tag. `T` may also derive from other tags describing the iterator (e.g. whether this is a `const`-iterator +or not), these additional tags are not considered. +* `pure_iterator_traversal::type` - a shorthand for `pure_traversal_tag::type>::type`. + +[h2 Reference] + +[h3 `pointee`] + + template + struct pointee + { + typedef /* see below */ type; + }; + +[*Requires:] For an object `x` of type `Dereferenceable`, `*x` + is well-formed. If `++x` is ill-formed it shall neither be + ambiguous nor shall it violate access control, and + `Dereferenceable::element_type` shall be an accessible type. + Otherwise `iterator_traits::value_type` shall + be well formed. \[Note: These requirements need not apply to + explicit or partial specializations of `pointee`\] + +`type` is determined according to the following algorithm, where +`x` is an object of type `Dereferenceable`: + + if ( ++x is ill-formed ) + { + return Dereferenceable::element_type + } + else if (*x is a mutable reference to + std::iterator_traits::value_type) + { + return iterator_traits::value_type + } + else + { + return iterator_traits::value_type const + } + +[h3 `indirect_reference`] + + template + struct indirect_reference + { + typedef /* see below */ type; + }; + +[*Requires:] For an object `x` of type `Dereferenceable`, `*x` + is well-formed. If `++x` is ill-formed it shall neither be + ambiguous nor shall it violate access control, and + `pointee::type&` shall be well-formed. + Otherwise `iterator_traits::reference` shall + be well formed. \[Note: These requirements need not apply to + explicit or partial specializations of `indirect_reference`\] + +`type` is determined according to the following algorithm, where +`x` is an object of type `Dereferenceable`: + + if ( ++x is ill-formed ) + return pointee::type& + else + std::iterator_traits::reference + +[h3 `minimum_category`] + + template + struct minimum_category + { + typedef /* see below */ type; + }; + +[*Requires:] Both `C1` and `C2` shall be standard iterator categories or + iterator traversal tags. + +`type` is determined according to the following algorithm, where `c1` is an +object of type `C1` and `c2` is an object of type `C2`: + + if (c1 is convertible to c2) + return C2; + else + return C1; + +[note The above definition relies on the fact that the more restricting categories +and traversal tags are convertible to the less restricting ones.] + +[h3 `iterator_category_to_traversal`] + + template + struct iterator_category_to_traversal + { + typedef /* see below */ type; + }; + +[*Requires:] `C` shall be a standard iterator category or an + iterator traversal tag. + +If `C` is an iterator traversal tag or convertible to one, `type` equivalent to `C`. +Otherwise, `type` is defined to the closest iterator traversal tag matching `C`. + +[h3 `iterator_traversal`] + + template + struct iterator_traversal + { + typedef typename iterator_category_to_traversal< + typename iterator_category::type + >::type type; + }; + +[*Requires:] `Iterator` shall be an iterator. + +[h3 `pure_traversal_tag`] + + template + struct pure_traversal_tag + { + typedef /* see below */ type; + }; + +[*Requires:] `T` shall be convertible to an iterator traversal tag. + +`type` is defined to be the most advanced traversal tag `Tag` so that `T` is convertible to `Tag`. + +[h3 `pure_iterator_traversal`] + + template + struct pure_iterator_traversal + { + typedef typename pure_traversal_tag< + typename iterator_traversal::type + >::type type; + }; + +[*Requires:] `Iterator` shall be an iterator. + +[endsect] diff --git a/libs/iterator/doc/quickbook/zip_iterator.qbk b/libs/iterator/doc/quickbook/zip_iterator.qbk new file mode 100644 index 00000000..53daf812 --- /dev/null +++ b/libs/iterator/doc/quickbook/zip_iterator.qbk @@ -0,0 +1,265 @@ +[section:zip Zip Iterator] + +The zip iterator provides the ability to parallel-iterate +over several controlled sequences simultaneously. A zip +iterator is constructed from a tuple of iterators. Moving +the zip iterator moves all the iterators in parallel. +Dereferencing the zip iterator returns a tuple that contains +the results of dereferencing the individual iterators. + +The tuple of iterators is now implemented in terms of a Boost fusion sequence. +Because of this the 'tuple' may be any Boost fusion sequence and, for backwards +compatibility through a Boost fusion sequence adapter, a Boost tuple. Because the +'tuple' may be any boost::fusion sequence the 'tuple' may also be any type for which a +Boost fusion adapter exists. This includes, among others, a std::tuple and a std::pair. +Just remember to include the appropriate Boost fusion adapter header files for these +other Boost fusion adapters. The zip_iterator header file already includes the +Boost fusion adapter header file for Boost tuple, so you need not include it yourself +to use a Boost tuple as your 'tuple'. + +[section:zip_example Example] + +There are two main types of applications of the `zip_iterator`. The first +one concerns runtime efficiency: If one has several controlled sequences +of the same length that must be somehow processed, e.g., with the +`for_each` algorithm, then it is more efficient to perform just +one parallel-iteration rather than several individual iterations. For an +example, assume that `vect_of_doubles` and `vect_of_ints` +are two vectors of equal length containing doubles and ints, respectively, +and consider the following two iterations: + + std::vector::const_iterator beg1 = vect_of_doubles.begin(); + std::vector::const_iterator end1 = vect_of_doubles.end(); + std::vector::const_iterator beg2 = vect_of_ints.begin(); + std::vector::const_iterator end2 = vect_of_ints.end(); + + std::for_each(beg1, end1, func_0()); + std::for_each(beg2, end2, func_1()); + +These two iterations can now be replaced with a single one as follows: + + + std::for_each( + boost::make_zip_iterator( + boost::make_tuple(beg1, beg2) + ), + boost::make_zip_iterator( + boost::make_tuple(end1, end2) + ), + zip_func() + ); + +A non-generic implementation of `zip_func` could look as follows: + + + struct zip_func : + public std::unary_function&, void> + { + void operator()(const boost::tuple& t) const + { + m_f0(t.get<0>()); + m_f1(t.get<1>()); + } + + private: + func_0 m_f0; + func_1 m_f1; + }; + +The second important application of the `zip_iterator` is as a building block +to make combining iterators. A combining iterator is an iterator +that parallel-iterates over several controlled sequences and, upon +dereferencing, returns the result of applying a functor to the values of the +sequences at the respective positions. This can now be achieved by using the +`zip_iterator` in conjunction with the `transform_iterator`. + +Suppose, for example, that you have two vectors of doubles, say +`vect_1` and `vect_2`, and you need to expose to a client +a controlled sequence containing the products of the elements of +`vect_1` and `vect_2`. Rather than placing these products +in a third vector, you can use a combining iterator that calculates the +products on the fly. Let us assume that `tuple_multiplies` is a +functor that works like `std::multiplies`, except that it takes +its two arguments packaged in a tuple. Then the two iterators +`it_begin` and `it_end` defined below delimit a controlled +sequence containing the products of the elements of `vect_1` and +`vect_2`: + + typedef boost::tuple< + std::vector::const_iterator, + std::vector::const_iterator + > the_iterator_tuple; + + typedef boost::zip_iterator< + the_iterator_tuple + > the_zip_iterator; + + typedef boost::transform_iterator< + tuple_multiplies, + the_zip_iterator + > the_transform_iterator; + + the_transform_iterator it_begin( + the_zip_iterator( + the_iterator_tuple( + vect_1.begin(), + vect_2.begin() + ) + ), + tuple_multiplies() + ); + + the_transform_iterator it_end( + the_zip_iterator( + the_iterator_tuple( + vect_1.end(), + vect_2.end() + ) + ), + tuple_multiplies() + ); + +[endsect] + +[section:zip_reference Reference] + +[h2 Synopsis] + + template + class zip_iterator + { + + public: + typedef /* see below */ reference; + typedef reference value_type; + typedef value_type* pointer; + typedef /* see below */ difference_type; + typedef /* see below */ iterator_category; + + zip_iterator(); + zip_iterator(IteratorTuple iterator_tuple); + + template + zip_iterator( + const zip_iterator& other + , typename enable_if_convertible< + OtherIteratorTuple + , IteratorTuple>::type* = 0 // exposition only + ); + + const IteratorTuple& get_iterator_tuple() const; + + private: + IteratorTuple m_iterator_tuple; // exposition only + }; + + template + zip_iterator + make_zip_iterator(IteratorTuple t); + +The `reference` member of `zip_iterator` is the type of the tuple +made of the reference types of the iterator types in the `IteratorTuple` +argument. + +The `difference_type` member of `zip_iterator` is the `difference_type` +of the first of the iterator types in the `IteratorTuple` argument. + +The `iterator_category` member of `zip_iterator` is convertible to the +minimum of the traversal categories of the iterator types in the `IteratorTuple` +argument. For example, if the `zip_iterator` holds only vector +iterators, then `iterator_category` is convertible to +`boost::random_access_traversal_tag`. If you add a list iterator, then +`iterator_category` will be convertible to `boost::bidirectional_traversal_tag`, +but no longer to `boost::random_access_traversal_tag`. + +[h2 Requirements] + +All iterator types in the argument `IteratorTuple` shall model Readable Iterator. + +[h2 Concepts] + +The resulting `zip_iterator` models Readable Iterator. + +The fact that the `zip_iterator` models only Readable Iterator does not +prevent you from modifying the values that the individual iterators point +to. The tuple returned by the `zip_iterator`'s `operator*` is a tuple +constructed from the reference types of the individual iterators, not +their value types. For example, if `zip_it` is a `zip_iterator` whose +first member iterator is an `std::vector::iterator`, then the +following line will modify the value which the first member iterator of +`zip_it` currently points to: + + zip_it->get<0>() = 42.0; + + +Consider the set of standard traversal concepts obtained by taking +the most refined standard traversal concept modeled by each individual +iterator type in the `IteratorTuple` argument.The `zip_iterator` +models the least refined standard traversal concept in this set. + +`zip_iterator` is interoperable with +`zip_iterator` if and only if `IteratorTuple1` +is interoperable with `IteratorTuple2`. + +[h2 Operations] + +In addition to the operations required by the concepts modeled by +`zip_iterator`, `zip_iterator` provides the following +operations. + + zip_iterator(); + +[*Returns:] An instance of `zip_iterator` with `m_iterator_tuple` + default constructed. + + + zip_iterator(IteratorTuple iterator_tuple); + +[*Returns:] An instance of `zip_iterator` with `m_iterator_tuple` + initialized to `iterator_tuple`. + + + template + zip_iterator( + const zip_iterator& other + , typename enable_if_convertible< + OtherIteratorTuple + , IteratorTuple>::type* = 0 // exposition only + ); + +[*Returns:] An instance of `zip_iterator` that is a copy of `other`.[br] +[*Requires:] `OtherIteratorTuple` is implicitly convertible to `IteratorTuple`. + + + const IteratorTuple& get_iterator_tuple() const; + +[*Returns:] `m_iterator_tuple` + + + reference operator*() const; + +[*Returns:] A tuple consisting of the results of dereferencing all iterators in + `m_iterator_tuple`. + + + zip_iterator& operator++(); + +[*Effects:] Increments each iterator in `m_iterator_tuple`.[br] +[*Returns:] `*this` + + + zip_iterator& operator--(); + +[*Effects:] Decrements each iterator in `m_iterator_tuple`.[br] +[*Returns:] `*this` + + template + zip_iterator + make_zip_iterator(IteratorTuple t); + +[*Returns:] An instance of `zip_iterator` with `m_iterator_tuple` + initialized to `t`. + +[endsect] + +[endsect] diff --git a/libs/iterator/doc/ref_problem.rst b/libs/iterator/doc/ref_problem.rst new file mode 100644 index 00000000..8dead894 --- /dev/null +++ b/libs/iterator/doc/ref_problem.rst @@ -0,0 +1,63 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Problem with ``reference`` and old/new iterator category correspondance +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +.. _N1550: http://www.boost-consulting.com/writing/n1550.html +.. _N1530: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1530.html + +:Author: David Abrahams and Jeremy Siek +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu +:Organization: `Boost Consulting`_, Indiana University Bloomington +:date: $Date$ +:Copyright: Copyright David Abrahams, Jeremy Siek 2003. Use, modification and + distribution is subject to 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) + +.. _`Boost Consulting`: http://www.boost-consulting.com + +============== + Introduction +============== + +The new iterator categories are intended to correspond to the old +iterator categories, as specified in a diagram in N1550_. For example, +an iterator categorized as a mutable Forward Iterator under the old +scheme is now a Writable, Lvalue, and Foward Traversal iterator. +However, there is a problem with this correspondance, the new iterator +categories place requirements on the ``iterator_traits::reference`` +type whereas the standard iterator requirements say nothing about the +``reference`` type . In particular, the new Readable Iterator +requirements say that the return type of ``*a`` must be +``iterator_traits::reference`` and the Lvalue Iterator requirements +says that ``iterator_traits::reference`` must be ``T&`` or ``const +T&``. + + +==================== + Proposed Resolution +==================== + +Change the standard requirements to match the requirements of the new +iterators. (more details to come) + + +========== + Rationale +========== + +The lack of specification in the standard of the ``reference`` type is +certainly a defect. Without specification, it is entirely useless in a +generic function. The current practice in the community is generally +to assume there are requirements on the ``reference`` type, such as +those proposed in the new iterator categories. + +There is some danger in *adding* requirements to existing concepts. +This will mean that some existing iterator types will no longer meet +the iterator requirements. However, we feel that the impact of this is +small enough to warrant going ahead with this change. + +An alternative solution would be to leave the standard requirements as +is, and to remove the requirements for the ``reference`` type in the +new iterator concepts. We are not in favor of this approach because it +extends what we see as a defect further into the future. diff --git a/libs/iterator/doc/reverse_iterator.html b/libs/iterator/doc/reverse_iterator.html new file mode 100644 index 00000000..f635c1d1 --- /dev/null +++ b/libs/iterator/doc/reverse_iterator.html @@ -0,0 +1,297 @@ + + + + + + +Reverse Iterator + + + + + + + +

+

Reverse Iterator

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2006-09-11
Copyright:Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
+ + + + +++ + + + +
abstract: + + +The reverse iterator adaptor iterates through the adapted iterator +range in the opposite direction.
+
+
+

reverse_iterator synopsis

+ + + +
+template <class Iterator>
+class reverse_iterator
+{
+public:
+  typedef iterator_traits<Iterator>::value_type value_type;
+  typedef iterator_traits<Iterator>::reference reference;
+  typedef iterator_traits<Iterator>::pointer pointer;
+  typedef iterator_traits<Iterator>::difference_type difference_type;
+  typedef /* see below */ iterator_category;
+
+  reverse_iterator() {}
+  explicit reverse_iterator(Iterator x) ;
+
+  template<class OtherIterator>
+  reverse_iterator(
+      reverse_iterator<OtherIterator> const& r
+    , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+  );
+  Iterator const& base() const;
+  reference operator*() const;
+  reverse_iterator& operator++();
+  reverse_iterator& operator--();
+private:
+  Iterator m_iterator; // exposition
+};
+
+

If Iterator models Random Access Traversal Iterator and Readable +Lvalue Iterator, then iterator_category is convertible to +random_access_iterator_tag. Otherwise, if +Iterator models Bidirectional Traversal Iterator and Readable +Lvalue Iterator, then iterator_category is convertible to +bidirectional_iterator_tag. Otherwise, iterator_category is +convertible to input_iterator_tag.

+
+
+

reverse_iterator requirements

+

Iterator must be a model of Bidirectional Traversal Iterator. The +type iterator_traits<Iterator>::reference must be the type of +*i, where i is an object of type Iterator.

+
+
+

reverse_iterator models

+

A specialization of reverse_iterator models the same iterator +traversal and iterator access concepts modeled by its Iterator +argument. In addition, it may model old iterator concepts +specified in the following table:

+ ++++ + + + + + + + + + + + + + + + + + + + +
If I modelsthen reverse_iterator<I> models
Readable Lvalue Iterator, +Bidirectional Traversal IteratorBidirectional Iterator
Writable Lvalue Iterator, +Bidirectional Traversal IteratorMutable Bidirectional Iterator
Readable Lvalue Iterator, +Random Access Traversal IteratorRandom Access Iterator
Writable Lvalue Iterator, +Random Access Traversal IteratorMutable Random Access Iterator
+

reverse_iterator<X> is interoperable with +reverse_iterator<Y> if and only if X is interoperable with +Y.

+
+
+

reverse_iterator operations

+

In addition to the operations required by the concepts modeled by +reverse_iterator, reverse_iterator provides the following +operations.

+

reverse_iterator();

+ +++ + + + + + +
Requires:Iterator must be Default Constructible.
Effects:Constructs an instance of reverse_iterator with m_iterator +default constructed.
+

explicit reverse_iterator(Iterator x);

+ +++ + + + +
Effects:Constructs an instance of reverse_iterator with +m_iterator copy constructed from x.
+
+template<class OtherIterator>
+reverse_iterator(
+    reverse_iterator<OtherIterator> const& r
+  , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+);
+
+ +++ + + + + + +
Requires:OtherIterator is implicitly convertible to Iterator.
Effects:Constructs instance of reverse_iterator whose +m_iterator subobject is constructed from y.base().
+

Iterator const& base() const;

+ +++ + + + +
Returns:m_iterator
+

reference operator*() const;

+ +++ + + + +
Effects:
+
+Iterator tmp = m_iterator;
+return *--tmp;
+
+

reverse_iterator& operator++();

+ +++ + + + + + +
Effects:--m_iterator
Returns:*this
+

reverse_iterator& operator--();

+ +++ + + + + + +
Effects:++m_iterator
Returns:*this
+ + + +
+template <class BidirectionalIterator>
+reverse_iterator<BidirectionalIterator>n
+make_reverse_iterator(BidirectionalIterator x);
+
+ +++ + + + +
Returns:An instance of reverse_iterator<BidirectionalIterator> +with a current constructed from x.
+ + + +
+
+

Example

+

The following example prints an array of characters in reverse order +using reverse_iterator.

+
+char letters_[] = "hello world!";
+const int N = sizeof(letters_)/sizeof(char) - 1;
+typedef char* base_iterator;
+base_iterator letters(letters_);
+std::cout << "original sequence of letters:\t\t\t" << letters_ << std::endl;
+
+boost::reverse_iterator<base_iterator>
+  reverse_letters_first(letters + N),
+  reverse_letters_last(letters);
+
+std::cout << "sequence in reverse order:\t\t\t";
+std::copy(reverse_letters_first, reverse_letters_last,
+          std::ostream_iterator<char>(std::cout));
+std::cout << std::endl;
+
+std::cout << "sequence in double-reversed (normal) order:\t";
+std::copy(boost::make_reverse_iterator(reverse_letters_last),
+          boost::make_reverse_iterator(reverse_letters_first),
+          std::ostream_iterator<char>(std::cout));
+std::cout << std::endl;
+
+

The output is:

+
+original sequence of letters:                   hello world!
+sequence in reverse order:                      !dlrow olleh
+sequence in double-reversed (normal) order:     hello world!
+
+

The source code for this example can be found here.

+
+
+ + + diff --git a/libs/iterator/doc/reverse_iterator.pdf b/libs/iterator/doc/reverse_iterator.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8cfd92566619f5008db054ac29244e11a4630c3c GIT binary patch literal 61924 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 + reverse_letters_first(letters + N), + reverse_letters_last(letters); + + std::cout << "sequence in reverse order:\t\t\t"; + std::copy(reverse_letters_first, reverse_letters_last, + std::ostream_iterator(std::cout)); + std::cout << std::endl; + + std::cout << "sequence in double-reversed (normal) order:\t"; + std::copy(boost::make_reverse_iterator(reverse_letters_last), + boost::make_reverse_iterator(reverse_letters_first), + std::ostream_iterator(std::cout)); + std::cout << std::endl; + + + +The output is:: + + original sequence of letters: hello world! + sequence in reverse order: !dlrow olleh + sequence in double-reversed (normal) order: hello world! + + +The source code for this example can be found `here`__. + +__ ../example/reverse_iterator_example.cpp diff --git a/libs/iterator/doc/reverse_iterator_ref.rst b/libs/iterator/doc/reverse_iterator_ref.rst new file mode 100644 index 00000000..b239b266 --- /dev/null +++ b/libs/iterator/doc/reverse_iterator_ref.rst @@ -0,0 +1,141 @@ +.. Copyright David Abrahams 2006. 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) + +:: + + template + class reverse_iterator + { + public: + typedef iterator_traits::value_type value_type; + typedef iterator_traits::reference reference; + typedef iterator_traits::pointer pointer; + typedef iterator_traits::difference_type difference_type; + typedef /* see below */ iterator_category; + + reverse_iterator() {} + explicit reverse_iterator(Iterator x) ; + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::type* = 0 // exposition + ); + Iterator const& base() const; + reference operator*() const; + reverse_iterator& operator++(); + reverse_iterator& operator--(); + private: + Iterator m_iterator; // exposition + }; + + +If ``Iterator`` models Random Access Traversal Iterator and Readable +Lvalue Iterator, then ``iterator_category`` is convertible to +``random_access_iterator_tag``. Otherwise, if +``Iterator`` models Bidirectional Traversal Iterator and Readable +Lvalue Iterator, then ``iterator_category`` is convertible to +``bidirectional_iterator_tag``. Otherwise, ``iterator_category`` is +convertible to ``input_iterator_tag``. + + + +``reverse_iterator`` requirements +................................. + +``Iterator`` must be a model of Bidirectional Traversal Iterator. The +type ``iterator_traits::reference`` must be the type of +``*i``, where ``i`` is an object of type ``Iterator``. + + + +``reverse_iterator`` models +........................... + +A specialization of ``reverse_iterator`` models the same iterator +traversal and iterator access concepts modeled by its ``Iterator`` +argument. In addition, it may model old iterator concepts +specified in the following table: + ++---------------------------------------+-----------------------------------+ +| If ``I`` models |then ``reverse_iterator`` models| ++=======================================+===================================+ +| Readable Lvalue Iterator, | Bidirectional Iterator | +| Bidirectional Traversal Iterator | | ++---------------------------------------+-----------------------------------+ +| Writable Lvalue Iterator, | Mutable Bidirectional Iterator | +| Bidirectional Traversal Iterator | | ++---------------------------------------+-----------------------------------+ +| Readable Lvalue Iterator, | Random Access Iterator | +| Random Access Traversal Iterator | | ++---------------------------------------+-----------------------------------+ +| Writable Lvalue Iterator, | Mutable Random Access Iterator | +| Random Access Traversal Iterator | | ++---------------------------------------+-----------------------------------+ + + +``reverse_iterator`` is interoperable with +``reverse_iterator`` if and only if ``X`` is interoperable with +``Y``. + +``reverse_iterator`` operations +............................... + +In addition to the operations required by the concepts modeled by +``reverse_iterator``, ``reverse_iterator`` provides the following +operations. + + + +``reverse_iterator();`` + +:Requires: ``Iterator`` must be Default Constructible. +:Effects: Constructs an instance of ``reverse_iterator`` with ``m_iterator`` + default constructed. + +``explicit reverse_iterator(Iterator x);`` + +:Effects: Constructs an instance of ``reverse_iterator`` with + ``m_iterator`` copy constructed from ``x``. + + +:: + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::type* = 0 // exposition + ); + +:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. +:Effects: Constructs instance of ``reverse_iterator`` whose + ``m_iterator`` subobject is constructed from ``y.base()``. + + + +``Iterator const& base() const;`` + +:Returns: ``m_iterator`` + + +``reference operator*() const;`` + +:Effects: + +:: + + Iterator tmp = m_iterator; + return *--tmp; + + +``reverse_iterator& operator++();`` + +:Effects: ``--m_iterator`` +:Returns: ``*this`` + + +``reverse_iterator& operator--();`` + +:Effects: ``++m_iterator`` +:Returns: ``*this`` diff --git a/libs/iterator/doc/rst2html.sh b/libs/iterator/doc/rst2html.sh new file mode 100644 index 00000000..9b5f63f5 --- /dev/null +++ b/libs/iterator/doc/rst2html.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# Copyright David Abrahams 2006. 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) +PYTHONPATH="c:/src/docutils;c:/src/docutils/extras" +export PYTHONPATH +rst2html.py -gs --link-stylesheet --traceback --trim-footnote-reference-space --footnote-references=superscript --stylesheet=../../../rst.css $1 `echo $1 | sed 's/\(.*\)\..*/\1.html/'` + + + diff --git a/libs/iterator/doc/rst2latex.sh b/libs/iterator/doc/rst2latex.sh new file mode 100644 index 00000000..f3c1d0e3 --- /dev/null +++ b/libs/iterator/doc/rst2latex.sh @@ -0,0 +1,7 @@ +#!/bin/sh +# Copyright David Abrahams 2006. 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) +PYTHONPATH="c:/src/docutils;c:/src/docutils/extras" +export PYTHONPATH +python c:/src/docutils/tools/rst2latex.py --documentoptions pdftex --stylesheet=docutils.sty $1 `echo $1 | sed 's/\(.*\)\..*/\1.tex/'` diff --git a/libs/iterator/doc/scanrst.py b/libs/iterator/doc/scanrst.py new file mode 100644 index 00000000..484d8792 --- /dev/null +++ b/libs/iterator/doc/scanrst.py @@ -0,0 +1,29 @@ +# Copyright David Abrahams 2004. Use, modification and distribution is +# subject to 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) + +# This script accepts a list of .rst files to be processed and +# generates Makefile dependencies for .html and .rst files to stdout. +import os,sys +import re + +include = re.compile(r' *\.\. +(include|image):: +(.*)', re.MULTILINE) + +def deps(path, found): + dir = os.path.split(path)[0] + for m in re.findall(include, open(path).read()): + + dependency = os.path.normpath(os.path.join(dir,m[1])) + if dependency not in found: + found[dependency] = 1 + + if m[0] == 'include': + deps(dependency, found) + + return found + +for file in sys.argv[1:]: + found = deps(file, {}) + if found: + base = os.path.splitext(os.path.basename(file))[0] + print '%s.tex %s.html: %s' % (base, base, ' '.join(found.keys())) diff --git a/libs/iterator/doc/sources.py b/libs/iterator/doc/sources.py new file mode 100644 index 00000000..86249cc8 --- /dev/null +++ b/libs/iterator/doc/sources.py @@ -0,0 +1,25 @@ +# Copyright David Abrahams 2004. Use, modification and distribution is +# subject to 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) + +sources = [ +'counting_iterator.rst', +'facade-and-adaptor.rst', +'filter_iterator.rst', +'function_input_iterator.rst', +'function_output_iterator.rst', +'index.rst', +'indirect_iterator.rst', +'pointee.rst', +'iterator_adaptor.rst', +'iterator_facade.rst', +'new-iter-concepts.rst', +'permutation_iterator.rst', +'reverse_iterator.rst', +'transform_iterator.rst', +'zip_iterator.rst', +'iterator_archetypes.rst', +'iterator_concepts.rst', +'iterator_traits.rst' + ] + diff --git a/libs/iterator/doc/syscmd.py b/libs/iterator/doc/syscmd.py new file mode 100644 index 00000000..e6a8dcaa --- /dev/null +++ b/libs/iterator/doc/syscmd.py @@ -0,0 +1,14 @@ +# Copyright David Abrahams 2004. Use, modification and distribution is +# subject to 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) + +import os +import sys + +def syscmd(s): + print 'executing: ', repr(s) + sys.stdout.flush() + err = os.system(s) + if err: + raise SystemError, 'command: %s returned %s' % ( + repr(s), err) diff --git a/libs/iterator/doc/transform_iterator.html b/libs/iterator/doc/transform_iterator.html new file mode 100644 index 00000000..22817379 --- /dev/null +++ b/libs/iterator/doc/transform_iterator.html @@ -0,0 +1,346 @@ + + + + + + +Transform Iterator + + + + + + + +
+

Transform Iterator

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2006-09-11
Copyright:Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
+ + + + +++ + + + +
abstract: + + +The transform iterator adapts an iterator by modifying the +operator* to apply a function object to the result of +dereferencing the iterator and returning the result.
+ +
+

transform_iterator synopsis

+ + + + +
+template <class UnaryFunction,
+          class Iterator,
+          class Reference = use_default,
+          class Value = use_default>
+class transform_iterator
+{
+public:
+  typedef /* see below */ value_type;
+  typedef /* see below */ reference;
+  typedef /* see below */ pointer;
+  typedef iterator_traits<Iterator>::difference_type difference_type;
+  typedef /* see below */ iterator_category;
+
+  transform_iterator();
+  transform_iterator(Iterator const& x, UnaryFunction f);
+
+  template<class F2, class I2, class R2, class V2>
+  transform_iterator(
+        transform_iterator<F2, I2, R2, V2> const& t
+      , typename enable_if_convertible<I2, Iterator>::type* = 0      // exposition only
+      , typename enable_if_convertible<F2, UnaryFunction>::type* = 0 // exposition only
+  );
+  UnaryFunction functor() const;
+  Iterator const& base() const;
+  reference operator*() const;
+  transform_iterator& operator++();
+  transform_iterator& operator--();
+private:
+  Iterator m_iterator; // exposition only
+  UnaryFunction m_f;   // exposition only
+};
+
+

If Reference is use_default then the reference member of +transform_iterator is +result_of<const UnaryFunction(iterator_traits<Iterator>::reference)>::type. +Otherwise, reference is Reference.

+

If Value is use_default then the value_type member is +remove_cv<remove_reference<reference> >::type. Otherwise, +value_type is Value.

+

If Iterator models Readable Lvalue Iterator and if Iterator +models Random Access Traversal Iterator, then iterator_category is +convertible to random_access_iterator_tag. Otherwise, if +Iterator models Bidirectional Traversal Iterator, then +iterator_category is convertible to +bidirectional_iterator_tag. Otherwise iterator_category is +convertible to forward_iterator_tag. If Iterator does not +model Readable Lvalue Iterator then iterator_category is +convertible to input_iterator_tag.

+
+
+

transform_iterator requirements

+

The type UnaryFunction must be Assignable, Copy Constructible, and +the expression f(*i) must be valid where f is a const object of +type UnaryFunction, i is an object of type Iterator, and +where the type of f(*i) must be +result_of<const UnaryFunction(iterator_traits<Iterator>::reference)>::type.

+

The argument Iterator shall model Readable Iterator.

+
+
+

transform_iterator models

+

The resulting transform_iterator models the most refined of the +following that is also modeled by Iterator.

+
+
    +
  • Writable Lvalue Iterator if transform_iterator::reference is a non-const reference.
  • +
  • Readable Lvalue Iterator if transform_iterator::reference is a const reference.
  • +
  • Readable Iterator otherwise.
  • +
+
+

The transform_iterator models the most refined standard traversal +concept that is modeled by the Iterator argument.

+

If transform_iterator is a model of Readable Lvalue Iterator then +it models the following original iterator concepts depending on what +the Iterator argument models.

+ ++++ + + + + + + + + + + + + + + + + + + + +
If Iterator modelsthen transform_iterator models
Single Pass IteratorInput Iterator
Forward Traversal IteratorForward Iterator
Bidirectional Traversal IteratorBidirectional Iterator
Random Access Traversal IteratorRandom Access Iterator
+

If transform_iterator models Writable Lvalue Iterator then it is a +mutable iterator (as defined in the old iterator requirements).

+

transform_iterator<F1, X, R1, V1> is interoperable with +transform_iterator<F2, Y, R2, V2> if and only if X is +interoperable with Y.

+
+
+

transform_iterator operations

+

In addition to the operations required by the concepts modeled by +transform_iterator, transform_iterator provides the following +operations.

+

transform_iterator();

+ +++ + + + +
Returns:An instance of transform_iterator with m_f +and m_iterator default constructed.
+

transform_iterator(Iterator const& x, UnaryFunction f);

+ +++ + + + +
Returns:An instance of transform_iterator with m_f +initialized to f and m_iterator initialized to x.
+
+template<class F2, class I2, class R2, class V2>
+transform_iterator(
+      transform_iterator<F2, I2, R2, V2> const& t
+    , typename enable_if_convertible<I2, Iterator>::type* = 0      // exposition only
+    , typename enable_if_convertible<F2, UnaryFunction>::type* = 0 // exposition only
+);
+
+ +++ + + + + + +
Returns:An instance of transform_iterator with m_f +initialized to t.functor() and m_iterator initialized to +t.base().
Requires:OtherIterator is implicitly convertible to Iterator.
+

UnaryFunction functor() const;

+ +++ + + + +
Returns:m_f
+

Iterator const& base() const;

+ +++ + + + +
Returns:m_iterator
+

reference operator*() const;

+ +++ + + + +
Returns:m_f(*m_iterator)
+

transform_iterator& operator++();

+ +++ + + + + + +
Effects:++m_iterator
Returns:*this
+

transform_iterator& operator--();

+ +++ + + + + + +
Effects:--m_iterator
Returns:*this
+ + + +
+template <class UnaryFunction, class Iterator>
+transform_iterator<UnaryFunction, Iterator>
+make_transform_iterator(Iterator it, UnaryFunction fun);
+
+ +++ + + + +
Returns:An instance of transform_iterator<UnaryFunction, Iterator> with m_f +initialized to f and m_iterator initialized to x.
+
+template <class UnaryFunction, class Iterator>
+transform_iterator<UnaryFunction, Iterator>
+make_transform_iterator(Iterator it);
+
+ +++ + + + +
Returns:An instance of transform_iterator<UnaryFunction, Iterator> with m_f +default constructed and m_iterator initialized to x.
+ + + +
+
+

Example

+

This is a simple example of using the transform_iterators class to +generate iterators that multiply (or add to) the value returned by +dereferencing the iterator. It would be cooler to use lambda library +in this example.

+
+int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+const int N = sizeof(x)/sizeof(int);
+
+typedef boost::binder1st< std::multiplies<int> > Function;
+typedef boost::transform_iterator<Function, int*> doubling_iterator;
+
+doubling_iterator i(x, boost::bind1st(std::multiplies<int>(), 2)),
+  i_end(x + N, boost::bind1st(std::multiplies<int>(), 2));
+
+std::cout << "multiplying the array by 2:" << std::endl;
+while (i != i_end)
+  std::cout << *i++ << " ";
+std::cout << std::endl;
+
+std::cout << "adding 4 to each element in the array:" << std::endl;
+std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)),
+          boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
+          std::ostream_iterator<int>(std::cout, " "));
+std::cout << std::endl;
+
+

The output is:

+
+multiplying the array by 2:
+2 4 6 8 10 12 14 16
+adding 4 to each element in the array:
+5 6 7 8 9 10 11 12
+
+

The source code for this example can be found here.

+
+
+ + + diff --git a/libs/iterator/doc/transform_iterator.pdf b/libs/iterator/doc/transform_iterator.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2af10ab194957cb7230202e014295c1ca9c20e0c GIT binary patch literal 67596 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 literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/transform_iterator.rst b/libs/iterator/doc/transform_iterator.rst new file mode 100644 index 00000000..4f81cca9 --- /dev/null +++ b/libs/iterator/doc/transform_iterator.rst @@ -0,0 +1,32 @@ +.. 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) + +++++++++++++++++++++ + Transform Iterator +++++++++++++++++++++ + +:Author: David Abrahams, Jeremy Siek, Thomas Witt +:Contact: dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de +:organization: `Boost Consulting`_, Indiana University `Open Systems + Lab`_, University of Hanover `Institute for Transport + Railway Operation and Construction`_ +:date: $Date$ +:copyright: Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Open Systems Lab`: http://www.osl.iu.edu +.. _`Institute for Transport Railway Operation and Construction`: http://www.ive.uni-hannover.de + +:abstract: + + .. include:: transform_iterator_abstract.rst + +.. contents:: Table of Contents + +``transform_iterator`` synopsis +............................... + +.. include:: transform_iterator_ref.rst +.. include:: make_transform_iterator.rst +.. include:: transform_iterator_eg.rst diff --git a/libs/iterator/doc/transform_iterator_abstract.rst b/libs/iterator/doc/transform_iterator_abstract.rst new file mode 100644 index 00000000..5fdcf530 --- /dev/null +++ b/libs/iterator/doc/transform_iterator_abstract.rst @@ -0,0 +1,7 @@ +.. Copyright David Abrahams 2006. 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 transform iterator adapts an iterator by modifying the +``operator*`` to apply a function object to the result of +dereferencing the iterator and returning the result. diff --git a/libs/iterator/doc/transform_iterator_eg.rst b/libs/iterator/doc/transform_iterator_eg.rst new file mode 100644 index 00000000..1406d2b5 --- /dev/null +++ b/libs/iterator/doc/transform_iterator_eg.rst @@ -0,0 +1,46 @@ +.. Copyright David Abrahams 2006. 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) + +Example +....... + +This is a simple example of using the transform_iterators class to +generate iterators that multiply (or add to) the value returned by +dereferencing the iterator. It would be cooler to use lambda library +in this example. + +:: + + int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + const int N = sizeof(x)/sizeof(int); + + typedef boost::binder1st< std::multiplies > Function; + typedef boost::transform_iterator doubling_iterator; + + doubling_iterator i(x, boost::bind1st(std::multiplies(), 2)), + i_end(x + N, boost::bind1st(std::multiplies(), 2)); + + std::cout << "multiplying the array by 2:" << std::endl; + while (i != i_end) + std::cout << *i++ << " "; + std::cout << std::endl; + + std::cout << "adding 4 to each element in the array:" << std::endl; + std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus(), 4)), + boost::make_transform_iterator(x + N, boost::bind1st(std::plus(), 4)), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + +The output is:: + + multiplying the array by 2: + 2 4 6 8 10 12 14 16 + adding 4 to each element in the array: + 5 6 7 8 9 10 11 12 + + +The source code for this example can be found `here`__. + +__ ../example/transform_iterator_example.cpp diff --git a/libs/iterator/doc/transform_iterator_ref.rst b/libs/iterator/doc/transform_iterator_ref.rst new file mode 100644 index 00000000..70becc5d --- /dev/null +++ b/libs/iterator/doc/transform_iterator_ref.rst @@ -0,0 +1,175 @@ +.. Copyright David Abrahams 2006. 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) + +.. Version 1.3 of this document was accepted for TR1 + +:: + + template + class transform_iterator + { + public: + typedef /* see below */ value_type; + typedef /* see below */ reference; + typedef /* see below */ pointer; + typedef iterator_traits::difference_type difference_type; + typedef /* see below */ iterator_category; + + transform_iterator(); + transform_iterator(Iterator const& x, UnaryFunction f); + + template + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition only + , typename enable_if_convertible::type* = 0 // exposition only + ); + UnaryFunction functor() const; + Iterator const& base() const; + reference operator*() const; + transform_iterator& operator++(); + transform_iterator& operator--(); + private: + Iterator m_iterator; // exposition only + UnaryFunction m_f; // exposition only + }; + + +If ``Reference`` is ``use_default`` then the ``reference`` member of +``transform_iterator`` is +``result_of::reference)>::type``. +Otherwise, ``reference`` is ``Reference``. + +If ``Value`` is ``use_default`` then the ``value_type`` member is +``remove_cv >::type``. Otherwise, +``value_type`` is ``Value``. + + +If ``Iterator`` models Readable Lvalue Iterator and if ``Iterator`` +models Random Access Traversal Iterator, then ``iterator_category`` is +convertible to ``random_access_iterator_tag``. Otherwise, if +``Iterator`` models Bidirectional Traversal Iterator, then +``iterator_category`` is convertible to +``bidirectional_iterator_tag``. Otherwise ``iterator_category`` is +convertible to ``forward_iterator_tag``. If ``Iterator`` does not +model Readable Lvalue Iterator then ``iterator_category`` is +convertible to ``input_iterator_tag``. + + +``transform_iterator`` requirements +................................... + +The type ``UnaryFunction`` must be Assignable, Copy Constructible, and +the expression ``f(*i)`` must be valid where ``f`` is a const object of +type ``UnaryFunction``, ``i`` is an object of type ``Iterator``, and +where the type of ``f(*i)`` must be +``result_of::reference)>::type``. + +The argument ``Iterator`` shall model Readable Iterator. + + +``transform_iterator`` models +............................. + +The resulting ``transform_iterator`` models the most refined of the +following that is also modeled by ``Iterator``. + + * Writable Lvalue Iterator if ``transform_iterator::reference`` is a non-const reference. + + * Readable Lvalue Iterator if ``transform_iterator::reference`` is a const reference. + + * Readable Iterator otherwise. + +The ``transform_iterator`` models the most refined standard traversal +concept that is modeled by the ``Iterator`` argument. + +If ``transform_iterator`` is a model of Readable Lvalue Iterator then +it models the following original iterator concepts depending on what +the ``Iterator`` argument models. + ++-----------------------------------+---------------------------------------+ +| If ``Iterator`` models | then ``transform_iterator`` models | ++===================================+=======================================+ +| Single Pass Iterator | Input Iterator | ++-----------------------------------+---------------------------------------+ +| Forward Traversal Iterator | Forward Iterator | ++-----------------------------------+---------------------------------------+ +| Bidirectional Traversal Iterator | Bidirectional Iterator | ++-----------------------------------+---------------------------------------+ +| Random Access Traversal Iterator | Random Access Iterator | ++-----------------------------------+---------------------------------------+ + +If ``transform_iterator`` models Writable Lvalue Iterator then it is a +mutable iterator (as defined in the old iterator requirements). + +``transform_iterator`` is interoperable with +``transform_iterator`` if and only if ``X`` is +interoperable with ``Y``. + + + +``transform_iterator`` operations +................................. + +In addition to the operations required by the concepts modeled by +``transform_iterator``, ``transform_iterator`` provides the following +operations. + + +``transform_iterator();`` + +:Returns: An instance of ``transform_iterator`` with ``m_f`` + and ``m_iterator`` default constructed. + + +``transform_iterator(Iterator const& x, UnaryFunction f);`` + +:Returns: An instance of ``transform_iterator`` with ``m_f`` + initialized to ``f`` and ``m_iterator`` initialized to ``x``. + + +:: + + template + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 // exposition only + , typename enable_if_convertible::type* = 0 // exposition only + ); + +:Returns: An instance of ``transform_iterator`` with ``m_f`` + initialized to ``t.functor()`` and ``m_iterator`` initialized to + ``t.base()``. +:Requires: ``OtherIterator`` is implicitly convertible to ``Iterator``. + + +``UnaryFunction functor() const;`` + +:Returns: ``m_f`` + + +``Iterator const& base() const;`` + +:Returns: ``m_iterator`` + + +``reference operator*() const;`` + +:Returns: ``m_f(*m_iterator)`` + + +``transform_iterator& operator++();`` + +:Effects: ``++m_iterator`` +:Returns: ``*this`` + + +``transform_iterator& operator--();`` + +:Effects: ``--m_iterator`` +:Returns: ``*this`` + diff --git a/libs/iterator/doc/traversal.png b/libs/iterator/doc/traversal.png new file mode 100644 index 0000000000000000000000000000000000000000..a9bbe981a1c3b6492afdbb0786018aec326433c1 GIT binary patch literal 9112 zcmZ{K2RxSV+xJC6D7TDk8QE0!mOCq(ls&R#%bpEnkF4yUB&jIbJ0W{h_MT-coBKWV z|2@z9e4h97-k<7@x?JaZUdQoW#~r4jrf`vfngBtNi+2=dwcz~~{I12vhCl03H_zU1 ztYuVX5aeU4@cHl+1i6abk(JT*N?*(HymeP+szn_?2qnbB@s#?Nip+)EI5>vxWLM}! zoEr%BOT(Y(m;T(bVHg$rX_L*1>cgiP|L4BU7cH{OA=vjX5PX&miNry(Fdozfrk8u~ zphm?=N7H&t_D)^bH;yZ&e7hxCgr{N=#CAU~CwCoN;4OAkXV5KXe#YKb6?_3c(*OA- zZfqysC0a#wbsbM~f0Bsiz~B9IEivWxBmHbIQ&Li5V>dnQe7xa*ReNqEwORZuoUONU zbQHRIb7gI9ZEq+|*y;P=;O`5pY;5IaWpyY0#?eohcH-I8Go}2+tU6zom6d({`ZXyj zDIp;tGLp#q+2P?~P*6~3r;1;{w}i2(s;ZovoQum%wBl9N>o;dF4|n&O-I0-zjEoGp zzp&$YtWxg1d-uY^!uHlD;@LiY_@JVs)ZWq2Slxc&;pW!V(n3tdhr@6!PSJ6qDls8} zB{`{aCX!xKjEn2n{??qkySqs1f~%yYBncXcO-oCA`SPtF$6G8)%5>?#$#36q5i@gh z*b1z;#ypooYL%yAC}`O=xf&!+P7iv{0DlX_zfjT?UZ zo72;#tns1`2idbVh9@W0nBrJfQ^{y)?M+Q@xc}5h)dg5uUPCIXs>H;^aB*>~ zs;W{`Qc6oo+}zzY*%Q{+9pe-QTxMlWOs4Yh=4s^*8k9Tc@62Npk)0hEB`qxxqMXco zk%%ZkDHqvnW6L_;Y$P@-@@fht+3!qBPVPw;B}JCq4$BE>bsi6ql9F2L$=X<7XN_;WbLWmoab@K}FyR$fS64$rL&OxG zBaM*#m$hUbgEGenv3r>+mL)@yX~ztPyuvqbpqy66%GH&X2^j}_d*Qg}W@mM|zkhnr zh(hn~?&jy`mzI`Z4zuV;;$gYWaqZf|Oyl#Le_#07a5B_UNhv9!fv0{nG&DiIjn9d5 zUcEx0Vc`PQUH$#8-RYua1lPE^i5Lg_`ebtY4q^2bhU;<63Me$Qd?Y(BZzjLBn!mrl zu`zu_Gbb;vhqLobVJCXDqOx+wmoHxi2NN1+rjNRXr~LQ>j`!svC>Vp3l$EW!Qgbs0 zI2CGjsN^{lsVOPv7ZxrAqX~kU$Oy1*aZ}vQAB4(=hZV3l;aRZ&4Msyvt)->)MlB

)uMijb**qppUA?DBG9c6Qhkub^OJgDHE` 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 literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/zip_iterator.html b/libs/iterator/doc/zip_iterator.html new file mode 100644 index 00000000..a85ba131 --- /dev/null +++ b/libs/iterator/doc/zip_iterator.html @@ -0,0 +1,367 @@ + + + + + + +Zip Iterator + + + + + + + +

+

Zip Iterator

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Thomas Becker
Contact:dave@boost-consulting.com, thomas@styleadvisor.com
Organization:Boost Consulting, Zephyr Associates, Inc.
Date:2006-09-11
Copyright:Copyright David Abrahams and Thomas Becker 2003.
+ + + + +++ + + + +
abstract: + + +The zip iterator provides the ability to parallel-iterate +over several controlled sequences simultaneously. A zip +iterator is constructed from a tuple of iterators. Moving +the zip iterator moves all the iterators in parallel. +Dereferencing the zip iterator returns a tuple that contains +the results of dereferencing the individual iterators.
+ +
+

zip_iterator synopsis

+ + + +
+template<typename IteratorTuple>
+class zip_iterator
+{
+
+public:
+  typedef /* see below */ reference;
+  typedef reference value_type;
+  typedef value_type* pointer;
+  typedef /* see below */ difference_type;
+  typedef /* see below */ iterator_category;
+
+  zip_iterator();
+  zip_iterator(IteratorTuple iterator_tuple);
+
+  template<typename OtherIteratorTuple>
+  zip_iterator(
+        const zip_iterator<OtherIteratorTuple>& other
+      , typename enable_if_convertible<
+              OtherIteratorTuple
+            , IteratorTuple>::type* = 0     // exposition only
+  );
+
+  const IteratorTuple& get_iterator_tuple() const;
+
+private:
+  IteratorTuple m_iterator_tuple;     // exposition only
+};
+
+template<typename IteratorTuple>
+zip_iterator<IteratorTuple>
+make_zip_iterator(IteratorTuple t);
+
+

The reference member of zip_iterator is the type of the tuple +made of the reference types of the iterator types in the IteratorTuple +argument.

+

The difference_type member of zip_iterator is the difference_type +of the first of the iterator types in the IteratorTuple argument.

+

The iterator_category member of zip_iterator is convertible to the +minimum of the traversal categories of the iterator types in the IteratorTuple +argument. For example, if the zip_iterator holds only vector +iterators, then iterator_category is convertible to +boost::random_access_traversal_tag. If you add a list iterator, then +iterator_category will be convertible to boost::bidirectional_traversal_tag, +but no longer to boost::random_access_traversal_tag.

+
+
+

zip_iterator requirements

+

All iterator types in the argument IteratorTuple shall model Readable Iterator.

+
+
+

zip_iterator models

+

The resulting zip_iterator models Readable Iterator.

+

The fact that the zip_iterator models only Readable Iterator does not +prevent you from modifying the values that the individual iterators point +to. The tuple returned by the zip_iterator's operator* is a tuple +constructed from the reference types of the individual iterators, not +their value types. For example, if zip_it is a zip_iterator whose +first member iterator is an std::vector<double>::iterator, then the +following line will modify the value which the first member iterator of +zip_it currently points to:

+
+zip_it->get<0>() = 42.0;
+
+

Consider the set of standard traversal concepts obtained by taking +the most refined standard traversal concept modeled by each individual +iterator type in the IteratorTuple argument.The zip_iterator +models the least refined standard traversal concept in this set.

+

zip_iterator<IteratorTuple1> is interoperable with +zip_iterator<IteratorTuple2> if and only if IteratorTuple1 +is interoperable with IteratorTuple2.

+
+
+

zip_iterator operations

+

In addition to the operations required by the concepts modeled by +zip_iterator, zip_iterator provides the following +operations.

+

zip_iterator();

+ +++ + + + +
Returns:An instance of zip_iterator with m_iterator_tuple +default constructed.
+

zip_iterator(IteratorTuple iterator_tuple);

+ +++ + + + +
Returns:An instance of zip_iterator with m_iterator_tuple +initialized to iterator_tuple.
+
+template<typename OtherIteratorTuple>
+zip_iterator(
+      const zip_iterator<OtherIteratorTuple>& other
+    , typename enable_if_convertible<
+            OtherIteratorTuple
+          , IteratorTuple>::type* = 0     // exposition only
+);
+
+ +++ + + + + + +
Returns:An instance of zip_iterator that is a copy of other.
Requires:OtherIteratorTuple is implicitly convertible to IteratorTuple.
+

const IteratorTuple& get_iterator_tuple() const;

+ +++ + + + +
Returns:m_iterator_tuple
+

reference operator*() const;

+ +++ + + + +
Returns:A tuple consisting of the results of dereferencing all iterators in +m_iterator_tuple.
+

zip_iterator& operator++();

+ +++ + + + + + +
Effects:Increments each iterator in m_iterator_tuple.
Returns:*this
+

zip_iterator& operator--();

+ +++ + + + + + +
Effects:Decrements each iterator in m_iterator_tuple.
Returns:*this
+
+template<typename IteratorTuple>
+zip_iterator<IteratorTuple>
+make_zip_iterator(IteratorTuple t);
+
+ +++ + + + +
Returns:An instance of zip_iterator<IteratorTuple> with m_iterator_tuple +initialized to t.
+ + + +
+template<typename IteratorTuple>
+zip_iterator<IteratorTuple>
+make_zip_iterator(IteratorTuple t);
+
+ +++ + + + +
Returns:An instance of zip_iterator<IteratorTuple> with m_iterator_tuple +initialized to t.
+ + + +
+
+

Examples

+

There are two main types of applications of the zip_iterator. The first +one concerns runtime efficiency: If one has several controlled sequences +of the same length that must be somehow processed, e.g., with the +for_each algorithm, then it is more efficient to perform just +one parallel-iteration rather than several individual iterations. For an +example, assume that vect_of_doubles and vect_of_ints +are two vectors of equal length containing doubles and ints, respectively, +and consider the following two iterations:

+
+std::vector<double>::const_iterator beg1 = vect_of_doubles.begin();
+std::vector<double>::const_iterator end1 = vect_of_doubles.end();
+std::vector<int>::const_iterator beg2 = vect_of_ints.begin();
+std::vector<int>::const_iterator end2 = vect_of_ints.end();
+
+std::for_each(beg1, end1, func_0());
+std::for_each(beg2, end2, func_1());
+
+

These two iterations can now be replaced with a single one as follows:

+
+std::for_each(
+  boost::make_zip_iterator(
+    boost::make_tuple(beg1, beg2)
+    ),
+  boost::make_zip_iterator(
+    boost::make_tuple(end1, end2)
+    ),
+  zip_func()
+  );
+
+

A non-generic implementation of zip_func could look as follows:

+
+struct zip_func :
+  public std::unary_function<const boost::tuple<const double&, const int&>&, void>
+{
+  void operator()(const boost::tuple<const double&, const int&>& t) const
+  {
+    m_f0(t.get<0>());
+    m_f1(t.get<1>());
+  }
+
+private:
+  func_0 m_f0;
+  func_1 m_f1;
+};
+
+

The second important application of the zip_iterator is as a building block +to make combining iterators. A combining iterator is an iterator +that parallel-iterates over several controlled sequences and, upon +dereferencing, returns the result of applying a functor to the values of the +sequences at the respective positions. This can now be achieved by using the +zip_iterator in conjunction with the transform_iterator.

+

Suppose, for example, that you have two vectors of doubles, say +vect_1 and vect_2, and you need to expose to a client +a controlled sequence containing the products of the elements of +vect_1 and vect_2. Rather than placing these products +in a third vector, you can use a combining iterator that calculates the +products on the fly. Let us assume that tuple_multiplies is a +functor that works like std::multiplies, except that it takes +its two arguments packaged in a tuple. Then the two iterators +it_begin and it_end defined below delimit a controlled +sequence containing the products of the elements of vect_1 and +vect_2:

+
+typedef boost::tuple<
+  std::vector<double>::const_iterator,
+  std::vector<double>::const_iterator
+  > the_iterator_tuple;
+
+typedef boost::zip_iterator<
+  the_iterator_tuple
+  > the_zip_iterator;
+
+typedef boost::transform_iterator<
+  tuple_multiplies<double>,
+  the_zip_iterator
+  > the_transform_iterator;
+
+the_transform_iterator it_begin(
+  the_zip_iterator(
+    the_iterator_tuple(
+      vect_1.begin(),
+      vect_2.begin()
+      )
+    ),
+  tuple_multiplies<double>()
+  );
+
+the_transform_iterator it_end(
+  the_zip_iterator(
+    the_iterator_tuple(
+      vect_1.end(),
+      vect_2.end()
+      )
+    ),
+  tuple_multiplies<double>()
+  );
+
+
+
+ + + diff --git a/libs/iterator/doc/zip_iterator.pdf b/libs/iterator/doc/zip_iterator.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c5a6f21cfe23aeb2ce534098232cdeaa2a6a2561 GIT binary patch literal 62372 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 AYybcN literal 0 HcmV?d00001 diff --git a/libs/iterator/doc/zip_iterator.rst b/libs/iterator/doc/zip_iterator.rst new file mode 100644 index 00000000..4e360c34 --- /dev/null +++ b/libs/iterator/doc/zip_iterator.rst @@ -0,0 +1,29 @@ +.. 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) + ++++++++++++++ + Zip Iterator ++++++++++++++ + +:Author: David Abrahams, Thomas Becker +:Contact: dave@boost-consulting.com, thomas@styleadvisor.com +:organization: `Boost Consulting`_, `Zephyr Associates, Inc.`_ +:date: $Date$ +:copyright: Copyright David Abrahams and Thomas Becker 2003. + +.. _`Boost Consulting`: http://www.boost-consulting.com +.. _`Zephyr Associates, Inc.`: http://www.styleadvisor.com + +:abstract: + + .. include:: zip_iterator_abstract.rst + +.. contents:: Table of Contents + +``zip_iterator`` synopsis +............................... + +.. include:: zip_iterator_ref.rst +.. include:: make_zip_iterator.rst +.. include:: zip_iterator_eg.rst diff --git a/libs/iterator/doc/zip_iterator_abstract.rst b/libs/iterator/doc/zip_iterator_abstract.rst new file mode 100644 index 00000000..524c2b1a --- /dev/null +++ b/libs/iterator/doc/zip_iterator_abstract.rst @@ -0,0 +1,20 @@ +.. Copyright David Abrahams 2006. 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 zip iterator provides the ability to parallel-iterate +over several controlled sequences simultaneously. A zip +iterator is constructed from a tuple of iterators. Moving +the zip iterator moves all the iterators in parallel. +Dereferencing the zip iterator returns a tuple that contains +the results of dereferencing the individual iterators. + +The tuple of iterators is now implemented in terms of a Boost fusion sequence. +Because of this the 'tuple' may be any Boost fusion sequence and, for backwards +compatibility through a Boost fusion sequence adapter, a Boost tuple. Because the +'tuple' may be any boost::fusion sequence the 'tuple' may also be any type for which a +Boost fusion adapter exists. This includes, among others, a std::tuple and a std::pair. +Just remember to include the appropriate Boost fusion adapter header files for these +other Boost fusion adapters. The zip_iterator header file already includes the +Boost fusion adapter header file for Boost tuple, so you need not include it yourself +to use a Boost tuple as your 'tuple'. diff --git a/libs/iterator/doc/zip_iterator_eg.rst b/libs/iterator/doc/zip_iterator_eg.rst new file mode 100644 index 00000000..5fb7a7b7 --- /dev/null +++ b/libs/iterator/doc/zip_iterator_eg.rst @@ -0,0 +1,115 @@ +.. Copyright David Abrahams 2006. 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) + +Examples +........ + +There are two main types of applications of the ``zip_iterator``. The first +one concerns runtime efficiency: If one has several controlled sequences +of the same length that must be somehow processed, e.g., with the +``for_each`` algorithm, then it is more efficient to perform just +one parallel-iteration rather than several individual iterations. For an +example, assume that ``vect_of_doubles`` and ``vect_of_ints`` +are two vectors of equal length containing doubles and ints, respectively, +and consider the following two iterations: + +:: + + + std::vector::const_iterator beg1 = vect_of_doubles.begin(); + std::vector::const_iterator end1 = vect_of_doubles.end(); + std::vector::const_iterator beg2 = vect_of_ints.begin(); + std::vector::const_iterator end2 = vect_of_ints.end(); + + std::for_each(beg1, end1, func_0()); + std::for_each(beg2, end2, func_1()); + +These two iterations can now be replaced with a single one as follows: + +:: + + + std::for_each( + boost::make_zip_iterator( + boost::make_tuple(beg1, beg2) + ), + boost::make_zip_iterator( + boost::make_tuple(end1, end2) + ), + zip_func() + ); + +A non-generic implementation of ``zip_func`` could look as follows: + +:: + + + struct zip_func + { + void operator()(const boost::tuple& t) const + { + m_f0(t.get<0>()); + m_f1(t.get<1>()); + } + + private: + func_0 m_f0; + func_1 m_f1; + }; + +The second important application of the ``zip_iterator`` is as a building block +to make combining iterators. A combining iterator is an iterator +that parallel-iterates over several controlled sequences and, upon +dereferencing, returns the result of applying a functor to the values of the +sequences at the respective positions. This can now be achieved by using the +``zip_iterator`` in conjunction with the ``transform_iterator``. + +Suppose, for example, that you have two vectors of doubles, say +``vect_1`` and ``vect_2``, and you need to expose to a client +a controlled sequence containing the products of the elements of +``vect_1`` and ``vect_2``. Rather than placing these products +in a third vector, you can use a combining iterator that calculates the +products on the fly. Let us assume that ``tuple_multiplies`` is a +functor that works like ``std::multiplies``, except that it takes +its two arguments packaged in a tuple. Then the two iterators +``it_begin`` and ``it_end`` defined below delimit a controlled +sequence containing the products of the elements of ``vect_1`` and +``vect_2``: + +:: + + + typedef boost::tuple< + std::vector::const_iterator, + std::vector::const_iterator + > the_iterator_tuple; + + typedef boost::zip_iterator< + the_iterator_tuple + > the_zip_iterator; + + typedef boost::transform_iterator< + tuple_multiplies, + the_zip_iterator + > the_transform_iterator; + + the_transform_iterator it_begin( + the_zip_iterator( + the_iterator_tuple( + vect_1.begin(), + vect_2.begin() + ) + ), + tuple_multiplies() + ); + + the_transform_iterator it_end( + the_zip_iterator( + the_iterator_tuple( + vect_1.end(), + vect_2.end() + ) + ), + tuple_multiplies() + ); diff --git a/libs/iterator/doc/zip_iterator_ref.rst b/libs/iterator/doc/zip_iterator_ref.rst new file mode 100644 index 00000000..f81ccd21 --- /dev/null +++ b/libs/iterator/doc/zip_iterator_ref.rst @@ -0,0 +1,155 @@ +.. Copyright David Abrahams 2006. 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) + +:: + + template + class zip_iterator + { + + public: + typedef /* see below */ reference; + typedef reference value_type; + typedef value_type* pointer; + typedef /* see below */ difference_type; + typedef /* see below */ iterator_category; + + zip_iterator(); + zip_iterator(IteratorTuple iterator_tuple); + + template + zip_iterator( + const zip_iterator& other + , typename enable_if_convertible< + OtherIteratorTuple + , IteratorTuple>::type* = 0 // exposition only + ); + + const IteratorTuple& get_iterator_tuple() const; + + private: + IteratorTuple m_iterator_tuple; // exposition only + }; + + template + zip_iterator + make_zip_iterator(IteratorTuple t); + + +The ``reference`` member of ``zip_iterator`` is the type of the tuple +made of the reference types of the iterator types in the ``IteratorTuple`` +argument. + +The ``difference_type`` member of ``zip_iterator`` is the ``difference_type`` +of the first of the iterator types in the ``IteratorTuple`` argument. + +The ``iterator_category`` member of ``zip_iterator`` is convertible to the +minimum of the traversal categories of the iterator types in the ``IteratorTuple`` +argument. For example, if the ``zip_iterator`` holds only vector +iterators, then ``iterator_category`` is convertible to +``boost::random_access_traversal_tag``. If you add a list iterator, then +``iterator_category`` will be convertible to ``boost::bidirectional_traversal_tag``, +but no longer to ``boost::random_access_traversal_tag``. + + +``zip_iterator`` requirements +................................... + +All iterator types in the argument ``IteratorTuple`` shall model Readable Iterator. + + +``zip_iterator`` models +............................. + +The resulting ``zip_iterator`` models Readable Iterator. + +The fact that the ``zip_iterator`` models only Readable Iterator does not +prevent you from modifying the values that the individual iterators point +to. The tuple returned by the ``zip_iterator``'s ``operator*`` is a tuple +constructed from the reference types of the individual iterators, not +their value types. For example, if ``zip_it`` is a ``zip_iterator`` whose +first member iterator is an ``std::vector::iterator``, then the +following line will modify the value which the first member iterator of +``zip_it`` currently points to: + +:: + + zip_it->get<0>() = 42.0; + + +Consider the set of standard traversal concepts obtained by taking +the most refined standard traversal concept modeled by each individual +iterator type in the ``IteratorTuple`` argument.The ``zip_iterator`` +models the least refined standard traversal concept in this set. + +``zip_iterator`` is interoperable with +``zip_iterator`` if and only if ``IteratorTuple1`` +is interoperable with ``IteratorTuple2``. + + + +``zip_iterator`` operations +................................. + +In addition to the operations required by the concepts modeled by +``zip_iterator``, ``zip_iterator`` provides the following +operations. + + +``zip_iterator();`` + +:Returns: An instance of ``zip_iterator`` with ``m_iterator_tuple`` + default constructed. + + +``zip_iterator(IteratorTuple iterator_tuple);`` + +:Returns: An instance of ``zip_iterator`` with ``m_iterator_tuple`` + initialized to ``iterator_tuple``. + + +:: + + template + zip_iterator( + const zip_iterator& other + , typename enable_if_convertible< + OtherIteratorTuple + , IteratorTuple>::type* = 0 // exposition only + ); + +:Returns: An instance of ``zip_iterator`` that is a copy of ``other``. +:Requires: ``OtherIteratorTuple`` is implicitly convertible to ``IteratorTuple``. + + +``const IteratorTuple& get_iterator_tuple() const;`` + +:Returns: ``m_iterator_tuple`` + + +``reference operator*() const;`` + +:Returns: A tuple consisting of the results of dereferencing all iterators in + ``m_iterator_tuple``. + + +``zip_iterator& operator++();`` + +:Effects: Increments each iterator in ``m_iterator_tuple``. +:Returns: ``*this`` + + +``zip_iterator& operator--();`` + +:Effects: Decrements each iterator in ``m_iterator_tuple``. +:Returns: ``*this`` + +:: + + template + zip_iterator + make_zip_iterator(IteratorTuple t); + +:Returns: An instance of ``zip_iterator`` with ``m_iterator_tuple`` + initialized to ``t``. diff --git a/libs/iterator/example/counting_iterator_example.cpp b/libs/iterator/example/counting_iterator_example.cpp new file mode 100644 index 00000000..de454872 --- /dev/null +++ b/libs/iterator/example/counting_iterator_example.cpp @@ -0,0 +1,52 @@ +// (C) Copyright Jeremy Siek 2000-2004. +// 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) + + +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int, char*[]) +{ + // Example of using counting_iterator + std::cout << "counting from 0 to 4:" << std::endl; + boost::counting_iterator first(0), last(4); + std::copy(first, last, std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + // Example of using counting iterator to create an array of pointers. + int N = 7; + std::vector numbers; + typedef std::vector::iterator n_iter; + // Fill "numbers" array with [0,N) + std::copy( + boost::counting_iterator(0) + , boost::counting_iterator(N) + , std::back_inserter(numbers)); + + std::vector::iterator> pointers; + + // Use counting iterator to fill in the array of pointers. + // causes an ICE with MSVC6 + std::copy(boost::make_counting_iterator(numbers.begin()), + boost::make_counting_iterator(numbers.end()), + std::back_inserter(pointers)); + + // Use indirect iterator to print out numbers by accessing + // them through the array of pointers. + std::cout << "indirectly printing out the numbers from 0 to " + << N << std::endl; + std::copy(boost::make_indirect_iterator(pointers.begin()), + boost::make_indirect_iterator(pointers.end()), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + return boost::exit_success; +} diff --git a/libs/iterator/example/filter_iterator_example.cpp b/libs/iterator/example/filter_iterator_example.cpp new file mode 100644 index 00000000..b427dea4 --- /dev/null +++ b/libs/iterator/example/filter_iterator_example.cpp @@ -0,0 +1,59 @@ +// (C) Copyright Jeremy Siek 1999-2004. +// 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) + +#include +#include +#include +#include +#include +#include +#include // for exit_success + +struct is_positive_number { + bool operator()(int x) { return 0 < x; } +}; + +int main() +{ + int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 }; + const int N = sizeof(numbers_)/sizeof(int); + + typedef int* base_iterator; + base_iterator numbers(numbers_); + + // Example using make_filter_iterator() + std::copy(boost::make_filter_iterator(numbers, numbers + N), + boost::make_filter_iterator(numbers + N, numbers + N), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + // Example using filter_iterator + typedef boost::filter_iterator + FilterIter; + + is_positive_number predicate; + FilterIter filter_iter_first(predicate, numbers, numbers + N); + FilterIter filter_iter_last(predicate, numbers + N, numbers + N); + + std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + // Another example using make_filter_iterator() + std::copy( + boost::make_filter_iterator( + boost::bind(std::greater(), boost::placeholders::_1, -2) + , numbers, numbers + N) + + , boost::make_filter_iterator( + boost::bind(std::greater(), boost::placeholders::_1, -2) + , numbers + N, numbers + N) + + , std::ostream_iterator(std::cout, " ") + ); + + std::cout << std::endl; + + return boost::exit_success; +} diff --git a/libs/iterator/example/func_output_iter_example.cpp b/libs/iterator/example/func_output_iter_example.cpp new file mode 100644 index 00000000..47a989a8 --- /dev/null +++ b/libs/iterator/example/func_output_iter_example.cpp @@ -0,0 +1,46 @@ +// (C) Copyright Jeremy Siek 2001-2004. +// 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) + +// Revision History: + +// 27 Feb 2001 Jeremy Siek +// Initial checkin. + +#include +#include +#include + +#include + +struct string_appender +{ + string_appender(std::string& s) + : m_str(&s) + {} + + void operator()(const std::string& x) const + { + *m_str += x; + } + + std::string* m_str; +}; + +int main(int, char*[]) +{ + std::vector x; + x.push_back("hello"); + x.push_back(" "); + x.push_back("world"); + x.push_back("!"); + + std::string s = ""; + std::copy(x.begin(), x.end(), + boost::make_function_output_iterator(string_appender(s))); + + std::cout << s << std::endl; + + return 0; +} diff --git a/libs/iterator/example/indirect_iterator_example.cpp b/libs/iterator/example/indirect_iterator_example.cpp new file mode 100644 index 00000000..74de3178 --- /dev/null +++ b/libs/iterator/example/indirect_iterator_example.cpp @@ -0,0 +1,60 @@ +// (C) Copyright Jeremy Siek 2000-2004. +// 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) + +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int, char*[]) +{ + char characters[] = "abcdefg"; + const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char + char* pointers_to_chars[N]; // at the end. + for (int i = 0; i < N; ++i) + pointers_to_chars[i] = &characters[i]; + + // Example of using indirect_iterator + + boost::indirect_iterator + indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N); + + std::copy(indirect_first, indirect_last, std::ostream_iterator(std::cout, ",")); + std::cout << std::endl; + + + // Example of making mutable and constant indirect iterators + + char mutable_characters[N]; + char* pointers_to_mutable_chars[N]; + for (int j = 0; j < N; ++j) + pointers_to_mutable_chars[j] = &mutable_characters[j]; + + boost::indirect_iterator mutable_indirect_first(pointers_to_mutable_chars), + mutable_indirect_last(pointers_to_mutable_chars + N); + boost::indirect_iterator const_indirect_first(pointers_to_chars), + const_indirect_last(pointers_to_chars + N); + + std::transform(const_indirect_first, const_indirect_last, + mutable_indirect_first, boost::bind(std::plus(), 1, boost::placeholders::_1)); + + std::copy(mutable_indirect_first, mutable_indirect_last, + std::ostream_iterator(std::cout, ",")); + std::cout << std::endl; + + + // Example of using make_indirect_iterator() + + std::copy(boost::make_indirect_iterator(pointers_to_chars), + boost::make_indirect_iterator(pointers_to_chars + N), + std::ostream_iterator(std::cout, ",")); + std::cout << std::endl; + + return 0; +} diff --git a/libs/iterator/example/node.hpp b/libs/iterator/example/node.hpp new file mode 100644 index 00000000..de5ec8d1 --- /dev/null +++ b/libs/iterator/example/node.hpp @@ -0,0 +1,60 @@ +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to 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) +#ifndef NODE_DWA2004110_HPP +# define NODE_DWA2004110_HPP + +# include + +// Polymorphic list node base class + +struct node_base +{ + node_base() : m_next(0) {} + + virtual ~node_base() + { + delete m_next; + } + + node_base* next() const + { + return m_next; + } + + virtual void print(std::ostream& s) const = 0; + virtual void double_me() = 0; + + void append(node_base* p) + { + if (m_next) + m_next->append(p); + else + m_next = p; + } + + private: + node_base* m_next; +}; + +inline std::ostream& operator<<(std::ostream& s, node_base const& n) +{ + n.print(s); + return s; +} + +template +struct node : node_base +{ + node(T x) + : m_value(x) + {} + + void print(std::ostream& s) const { s << this->m_value; } + void double_me() { m_value += m_value; } + + private: + T m_value; +}; + +#endif // NODE_DWA2004110_HPP diff --git a/libs/iterator/example/node_iterator1.cpp b/libs/iterator/example/node_iterator1.cpp new file mode 100644 index 00000000..722a28fd --- /dev/null +++ b/libs/iterator/example/node_iterator1.cpp @@ -0,0 +1,44 @@ +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to 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) + +#include "node_iterator1.hpp" +#include +#include +#include +#include +#include + +int main() +{ + +#if defined(BOOST_NO_CXX11_SMART_PTR) + + std::auto_ptr > nodes(new node(42)); + +#else + + std::unique_ptr > nodes(new node(42)); + +#endif + + nodes->append(new node(" is greater than ")); + nodes->append(new node(13)); + + std::copy( + node_iterator(nodes.get()), node_iterator() + , std::ostream_iterator(std::cout, " ") + ); + std::cout << std::endl; + + std::for_each( + node_iterator(nodes.get()), node_iterator() + , std::mem_fun_ref(&node_base::double_me) + ); + + std::copy( + node_iterator(nodes.get()), node_iterator() + , std::ostream_iterator(std::cout, "/") + ); + std::cout << std::endl; +} diff --git a/libs/iterator/example/node_iterator1.hpp b/libs/iterator/example/node_iterator1.hpp new file mode 100644 index 00000000..9a1ed51e --- /dev/null +++ b/libs/iterator/example/node_iterator1.hpp @@ -0,0 +1,42 @@ +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to 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) +#ifndef NODE_ITERATOR1_DWA2004110_HPP +# define NODE_ITERATOR1_DWA2004110_HPP + +# include "node.hpp" +# include + +class node_iterator + : public boost::iterator_facade< + node_iterator + , node_base + , boost::forward_traversal_tag + > +{ + public: + node_iterator() + : m_node(0) + {} + + explicit node_iterator(node_base* p) + : m_node(p) + {} + + private: + friend class boost::iterator_core_access; + + void increment() + { m_node = m_node->next(); } + + bool equal(node_iterator const& other) const + { return this->m_node == other.m_node; } + + node_base& dereference() const + { return *m_node; } + + node_base* m_node; +}; + + +#endif // NODE_ITERATOR1_DWA2004110_HPP diff --git a/libs/iterator/example/node_iterator2.cpp b/libs/iterator/example/node_iterator2.cpp new file mode 100644 index 00000000..5ab71b67 --- /dev/null +++ b/libs/iterator/example/node_iterator2.cpp @@ -0,0 +1,53 @@ +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to 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) + +#include "node_iterator2.hpp" +#include +#include +#include +#include +#include +#include + +int main() +{ + +#if defined(BOOST_NO_CXX11_SMART_PTR) + + std::auto_ptr > nodes(new node(42)); + +#else + + std::unique_ptr > nodes(new node(42)); + +#endif + + nodes->append(new node(" is greater than ")); + nodes->append(new node(13)); + + // Check interoperability + assert(node_iterator(nodes.get()) == node_const_iterator(nodes.get())); + assert(node_const_iterator(nodes.get()) == node_iterator(nodes.get())); + + assert(node_iterator(nodes.get()) != node_const_iterator()); + assert(node_const_iterator(nodes.get()) != node_iterator()); + + std::copy( + node_iterator(nodes.get()), node_iterator() + , std::ostream_iterator(std::cout, " ") + ); + std::cout << std::endl; + + std::for_each( + node_iterator(nodes.get()), node_iterator() + , boost::mem_fn(&node_base::double_me) + ); + + std::copy( + node_const_iterator(nodes.get()), node_const_iterator() + , std::ostream_iterator(std::cout, "/") + ); + std::cout << std::endl; + return 0; +} diff --git a/libs/iterator/example/node_iterator2.hpp b/libs/iterator/example/node_iterator2.hpp new file mode 100644 index 00000000..1f5d834a --- /dev/null +++ b/libs/iterator/example/node_iterator2.hpp @@ -0,0 +1,73 @@ +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to 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) +#ifndef NODE_ITERATOR2_DWA2004110_HPP +# define NODE_ITERATOR2_DWA2004110_HPP + +# include "node.hpp" +# include + +# ifndef BOOST_NO_SFINAE +# include +# include +# endif + +template +class node_iter + : public boost::iterator_facade< + node_iter + , Value + , boost::forward_traversal_tag + > +{ + private: + struct enabler {}; // a private type avoids misuse + + public: + node_iter() + : m_node(0) {} + + explicit node_iter(Value* p) + : m_node(p) {} + + template + node_iter( + node_iter const& other +# ifndef BOOST_NO_SFINAE + , typename boost::enable_if< + boost::is_convertible + , enabler + >::type = enabler() +# endif + ) + : m_node(other.m_node) {} + + +# if !BOOST_WORKAROUND(__GNUC__, == 2) + private: // GCC2 can't grant friendship to template member functions + friend class boost::iterator_core_access; +# endif + + template + bool equal(node_iter const& other) const + { + return this->m_node == other.m_node; + } + + void increment() { m_node = m_node->next(); } + + Value& dereference() const { return *m_node; } + +# ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + public: +# else + private: + template friend class node_iter; +# endif + Value* m_node; +}; + +typedef node_iter node_iterator; +typedef node_iter node_const_iterator; + +#endif // NODE_ITERATOR2_DWA2004110_HPP diff --git a/libs/iterator/example/node_iterator3.cpp b/libs/iterator/example/node_iterator3.cpp new file mode 100644 index 00000000..551f2187 --- /dev/null +++ b/libs/iterator/example/node_iterator3.cpp @@ -0,0 +1,53 @@ +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to 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) + +#include "node_iterator3.hpp" +#include +#include +#include +#include +#include +#include + +int main() +{ + +#if defined(BOOST_NO_CXX11_SMART_PTR) + + std::auto_ptr > nodes(new node(42)); + +#else + + std::unique_ptr > nodes(new node(42)); + +#endif + + nodes->append(new node(" is greater than ")); + nodes->append(new node(13)); + + // Check interoperability + assert(node_iterator(nodes.get()) == node_const_iterator(nodes.get())); + assert(node_const_iterator(nodes.get()) == node_iterator(nodes.get())); + + assert(node_iterator(nodes.get()) != node_const_iterator()); + assert(node_const_iterator(nodes.get()) != node_iterator()); + + std::copy( + node_iterator(nodes.get()), node_iterator() + , std::ostream_iterator(std::cout, " ") + ); + std::cout << std::endl; + + std::for_each( + node_iterator(nodes.get()), node_iterator() + , boost::mem_fn(&node_base::double_me) + ); + + std::copy( + node_const_iterator(nodes.get()), node_const_iterator() + , std::ostream_iterator(std::cout, "/") + ); + std::cout << std::endl; + return 0; +} diff --git a/libs/iterator/example/node_iterator3.hpp b/libs/iterator/example/node_iterator3.hpp new file mode 100644 index 00000000..3ae7bec5 --- /dev/null +++ b/libs/iterator/example/node_iterator3.hpp @@ -0,0 +1,60 @@ +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to 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) +#ifndef NODE_ITERATOR3_DWA2004110_HPP +# define NODE_ITERATOR3_DWA2004110_HPP + +# include "node.hpp" +# include + +# ifndef BOOST_NO_SFINAE +# include +# include +# endif + +template +class node_iter + : public boost::iterator_adaptor< + node_iter // Derived + , Value* // Base + , boost::use_default // Value + , boost::forward_traversal_tag // CategoryOrTraversal + > +{ + private: + struct enabler {}; // a private type avoids misuse + + typedef boost::iterator_adaptor< + node_iter, Value*, boost::use_default, boost::forward_traversal_tag + > super_t; + + public: + node_iter() + : super_t(0) {} + + explicit node_iter(Value* p) + : super_t(p) {} + + template + node_iter( + node_iter const& other +# ifndef BOOST_NO_SFINAE + , typename boost::enable_if< + boost::is_convertible + , enabler + >::type = enabler() +# endif + ) + : super_t(other.base()) {} + +# if !BOOST_WORKAROUND(__GNUC__, == 2) + private: // GCC2 can't grant friendship to template member functions + friend class boost::iterator_core_access; +# endif + void increment() { this->base_reference() = this->base()->next(); } +}; + +typedef node_iter node_iterator; +typedef node_iter node_const_iterator; + +#endif // NODE_ITERATOR3_DWA2004110_HPP diff --git a/libs/iterator/example/permutation_iter_example.cpp b/libs/iterator/example/permutation_iter_example.cpp new file mode 100644 index 00000000..5089d643 --- /dev/null +++ b/libs/iterator/example/permutation_iter_example.cpp @@ -0,0 +1,68 @@ +// Copyright (C) 2004 Jeremy Siek +// 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) + +#include +#include +#include +#include +#include +#include +#include + + +int main() { + using namespace boost; + int i = 0; + + typedef std::vector< int > element_range_type; + typedef std::deque< int > index_type; + + static const int element_range_size = 10; + static const int index_size = 4; + + element_range_type elements( element_range_size ); + for(element_range_type::iterator el_it = elements.begin() ; el_it != elements.end() ; ++el_it) + *el_it = std::distance(elements.begin(), el_it); + + index_type indices( index_size ); + for(index_type::iterator i_it = indices.begin() ; i_it != indices.end() ; ++i_it ) + *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it); + std::reverse( indices.begin(), indices.end() ); + + typedef permutation_iterator< element_range_type::iterator, index_type::iterator > permutation_type; + permutation_type begin = make_permutation_iterator( elements.begin(), indices.begin() ); + permutation_type it = begin; + permutation_type end = make_permutation_iterator( elements.begin(), indices.end() ); + + std::cout << "The original range is : "; + std::copy( elements.begin(), elements.end(), std::ostream_iterator< int >( std::cout, " " ) ); + std::cout << "\n"; + + std::cout << "The reindexing scheme is : "; + std::copy( indices.begin(), indices.end(), std::ostream_iterator< int >( std::cout, " " ) ); + std::cout << "\n"; + + std::cout << "The permutated range is : "; + std::copy( begin, end, std::ostream_iterator< int >( std::cout, " " ) ); + std::cout << "\n"; + + std::cout << "Elements at even indices in the permutation : "; + it = begin; + for(i = 0; i < index_size / 2 ; ++i, it+=2 ) std::cout << *it << " "; + std::cout << "\n"; + + std::cout << "Permutation backwards : "; + it = begin + (index_size); + assert( it != begin ); + for( ; it-- != begin ; ) std::cout << *it << " "; + std::cout << "\n"; + + std::cout << "Iterate backward with stride 2 : "; + it = begin + (index_size - 1); + for(i = 0 ; i < index_size / 2 ; ++i, it-=2 ) std::cout << *it << " "; + std::cout << "\n"; + + return boost::exit_success; +} diff --git a/libs/iterator/example/reverse_iterator.cpp b/libs/iterator/example/reverse_iterator.cpp new file mode 100644 index 00000000..b5f10f76 --- /dev/null +++ b/libs/iterator/example/reverse_iterator.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2004 Jeremy Siek +// 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) + +#include +#include +#include +#include +#include + +int main() +{ + int x[] = { 1, 2, 3, 4 }; + boost::reverse_iterator first(x + 4), last(x); + std::copy(first, last, std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + return 0; +} diff --git a/libs/iterator/example/reverse_iterator_example.cpp b/libs/iterator/example/reverse_iterator_example.cpp new file mode 100644 index 00000000..0baa0ff0 --- /dev/null +++ b/libs/iterator/example/reverse_iterator_example.cpp @@ -0,0 +1,41 @@ +// (C) Copyright Jeremy Siek 2000-2004. +// 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) + +#include +#include +#include +#include +#include + +int main(int, char*[]) +{ + char letters_[] = "hello world!"; + const int N = sizeof(letters_)/sizeof(char) - 1; + typedef char* base_iterator; + base_iterator letters(letters_); + + std::cout << "original sequence of letters:\t\t\t" + << letters_ << std::endl; + + // Use reverse_iterator to print a sequence of letters in reverse + // order. + + boost::reverse_iterator + reverse_letters_first(letters + N), + reverse_letters_last(letters); + + std::cout << "sequence in reverse order:\t\t\t"; + std::copy(reverse_letters_first, reverse_letters_last, + std::ostream_iterator(std::cout)); + std::cout << std::endl; + + std::cout << "sequence in double-reversed (normal) order:\t"; + std::copy(boost::make_reverse_iterator(reverse_letters_last), + boost::make_reverse_iterator(reverse_letters_first), + std::ostream_iterator(std::cout)); + std::cout << std::endl; + + return boost::exit_success; +} diff --git a/libs/iterator/example/shared_iterator_example1.cpp b/libs/iterator/example/shared_iterator_example1.cpp new file mode 100644 index 00000000..0ca61199 --- /dev/null +++ b/libs/iterator/example/shared_iterator_example1.cpp @@ -0,0 +1,42 @@ +// Copyright 2003 The Trustees of Indiana University. + +// Use, modification and distribution is subject to 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) + +#include "boost/shared_container_iterator.hpp" +#include "boost/shared_ptr.hpp" +#include +#include +#include + +typedef boost::shared_container_iterator< std::vector > iterator; + + +void set_range(iterator& i, iterator& end) { + + boost::shared_ptr< std::vector > ints(new std::vector()); + + ints->push_back(0); + ints->push_back(1); + ints->push_back(2); + ints->push_back(3); + ints->push_back(4); + ints->push_back(5); + + i = iterator(ints->begin(),ints); + end = iterator(ints->end(),ints); +} + + +int main() { + + iterator i,end; + + set_range(i,end); + + std::copy(i,end,std::ostream_iterator(std::cout,",")); + std::cout.put('\n'); + + return 0; +} diff --git a/libs/iterator/example/shared_iterator_example2.cpp b/libs/iterator/example/shared_iterator_example2.cpp new file mode 100644 index 00000000..e8b0dc6e --- /dev/null +++ b/libs/iterator/example/shared_iterator_example2.cpp @@ -0,0 +1,43 @@ +// Copyright 2003 The Trustees of Indiana University. + +// Use, modification and distribution is subject to 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) + +#include "boost/shared_container_iterator.hpp" +#include "boost/shared_ptr.hpp" +#include +#include +#include +#include + + +template +void print_range_nl (Iterator begin, Iterator end) { + typedef typename std::iterator_traits::value_type val; + std::copy(begin,end,std::ostream_iterator(std::cout,",")); + std::cout.put('\n'); +} + + +int main() { + + typedef boost::shared_ptr< std::vector > ints_t; + { + ints_t ints(new std::vector()); + + ints->push_back(0); + ints->push_back(1); + ints->push_back(2); + ints->push_back(3); + ints->push_back(4); + ints->push_back(5); + + print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints), + boost::make_shared_container_iterator(ints->end(),ints)); + } + + + + return 0; +} diff --git a/libs/iterator/example/shared_iterator_example3.cpp b/libs/iterator/example/shared_iterator_example3.cpp new file mode 100644 index 00000000..971b01f8 --- /dev/null +++ b/libs/iterator/example/shared_iterator_example3.cpp @@ -0,0 +1,41 @@ +// Copyright 2003 The Trustees of Indiana University. + +// Use, modification and distribution is subject to 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) + +#include "boost/shared_container_iterator.hpp" +#include "boost/shared_ptr.hpp" +#include "boost/tuple/tuple.hpp" // for boost::tie +#include // for std::copy +#include +#include + + +typedef boost::shared_container_iterator< std::vector > iterator; + +std::pair +return_range() { + boost::shared_ptr< std::vector > range(new std::vector()); + range->push_back(0); + range->push_back(1); + range->push_back(2); + range->push_back(3); + range->push_back(4); + range->push_back(5); + return boost::make_shared_container_range(range); +} + + +int main() { + + + iterator i,end; + + boost::tie(i,end) = return_range(); + + std::copy(i,end,std::ostream_iterator(std::cout,",")); + std::cout.put('\n'); + + return 0; +} diff --git a/libs/iterator/example/transform_iterator_example.cpp b/libs/iterator/example/transform_iterator_example.cpp new file mode 100644 index 00000000..a684ebf2 --- /dev/null +++ b/libs/iterator/example/transform_iterator_example.cpp @@ -0,0 +1,75 @@ +// (C) Copyright Jeremy Siek 2000-2004. +// 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) + + +#include +#include +#include +#include + +// What a bummer. We can't use std::binder1st with transform iterator +// because it does not have a default constructor. Here's a version +// that does. + +namespace boost { + + template + class binder1st { + public: + typedef typename Operation::result_type result_type; + typedef typename Operation::second_argument_type argument_type; + protected: + Operation op; + typename Operation::first_argument_type value; + public: + binder1st() { } // this had to be added! + binder1st(const Operation& x, + const typename Operation::first_argument_type& y) + : op(x), value(y) {} + typename Operation::result_type + operator()(const typename Operation::second_argument_type& x) const { + return op(value, x); + } + }; + + template + inline binder1st bind1st(const Operation& op, const T& x) { + typedef typename Operation::first_argument_type arg1_type; + return binder1st(op, arg1_type(x)); + } + +} // namespace boost + +int +main(int, char*[]) +{ + // This is a simple example of using the transform_iterators class to + // generate iterators that multiply the value returned by dereferencing + // the iterator. In this case we are multiplying by 2. + // Would be cooler to use lambda library in this example. + + int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + const int N = sizeof(x)/sizeof(int); + + typedef boost::binder1st< std::multiplies > Function; + typedef boost::transform_iterator doubling_iterator; + + doubling_iterator i(x, boost::bind1st(std::multiplies(), 2)), + i_end(x + N, boost::bind1st(std::multiplies(), 2)); + + std::cout << "multiplying the array by 2:" << std::endl; + while (i != i_end) + std::cout << *i++ << " "; + std::cout << std::endl; + + std::cout << "adding 4 to each element in the array:" << std::endl; + + std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus(), 4)), + boost::make_transform_iterator(x + N, boost::bind1st(std::plus(), 4)), + std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + + return 0; +} diff --git a/libs/iterator/include/boost/function_output_iterator.hpp b/libs/iterator/include/boost/function_output_iterator.hpp new file mode 100644 index 00000000..1584d9c8 --- /dev/null +++ b/libs/iterator/include/boost/function_output_iterator.hpp @@ -0,0 +1,18 @@ +// (C) Copyright Andrey Semashev 2017. +// 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) + +#ifndef BOOST_FUNCTION_OUTPUT_ITERATOR_HPP +#define BOOST_FUNCTION_OUTPUT_ITERATOR_HPP + +// This is a deprecated header left for backward compatibility. +// Use boost/iterator/function_output_iterator.hpp instead. + +#include + +BOOST_HEADER_DEPRECATED("") + +#include + +#endif // BOOST_FUNCTION_OUTPUT_ITERATOR_HPP diff --git a/libs/iterator/include/boost/generator_iterator.hpp b/libs/iterator/include/boost/generator_iterator.hpp new file mode 100644 index 00000000..0fe1569c --- /dev/null +++ b/libs/iterator/include/boost/generator_iterator.hpp @@ -0,0 +1,85 @@ +// (C) Copyright Jens Maurer 2001. +// 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) +// +// Revision History: + +// 15 Nov 2001 Jens Maurer +// created. + +// See http://www.boost.org/libs/utility/iterator_adaptors.htm for documentation. + +#ifndef BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP +#define BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP + +#include +#include + +namespace boost { +namespace iterators { + +template +class generator_iterator + : public iterator_facade< + generator_iterator + , typename Generator::result_type + , single_pass_traversal_tag + , typename Generator::result_type const& + > +{ + typedef iterator_facade< + generator_iterator + , typename Generator::result_type + , single_pass_traversal_tag + , typename Generator::result_type const& + > super_t; + + public: + generator_iterator() {} + generator_iterator(Generator* g) : m_g(g), m_value((*m_g)()) {} + + void increment() + { + m_value = (*m_g)(); + } + + const typename Generator::result_type& + dereference() const + { + return m_value; + } + + bool equal(generator_iterator const& y) const + { + return this->m_g == y.m_g && this->m_value == y.m_value; + } + + private: + Generator* m_g; + typename Generator::result_type m_value; +}; + +template +struct generator_iterator_generator +{ + typedef generator_iterator type; +}; + +template +inline generator_iterator +make_generator_iterator(Generator & gen) +{ + typedef generator_iterator result_t; + return result_t(&gen); +} + +} // namespace iterators + +using iterators::generator_iterator; +using iterators::generator_iterator_generator; +using iterators::make_generator_iterator; + +} // namespace boost + +#endif // BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP diff --git a/libs/iterator/include/boost/indirect_reference.hpp b/libs/iterator/include/boost/indirect_reference.hpp new file mode 100644 index 00000000..3279cd05 --- /dev/null +++ b/libs/iterator/include/boost/indirect_reference.hpp @@ -0,0 +1,43 @@ +#ifndef INDIRECT_REFERENCE_DWA200415_HPP +# define INDIRECT_REFERENCE_DWA200415_HPP + +// +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to 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) +// +// typename indirect_reference

::type provides the type of *p. +// +// http://www.boost.org/libs/iterator/doc/pointee.html +// + +# include +# include +# include +# include +# include + +namespace boost { + +namespace detail +{ + template + struct smart_ptr_reference + { + typedef typename boost::pointee

::type& type; + }; +} + +template +struct indirect_reference + : mpl::eval_if< + detail::is_incrementable

+ , iterator_reference

+ , detail::smart_ptr_reference

+ > +{ +}; + +} // namespace boost + +#endif // INDIRECT_REFERENCE_DWA200415_HPP diff --git a/libs/iterator/include/boost/iterator/advance.hpp b/libs/iterator/include/boost/iterator/advance.hpp new file mode 100644 index 00000000..2b742565 --- /dev/null +++ b/libs/iterator/include/boost/iterator/advance.hpp @@ -0,0 +1,95 @@ +// Copyright (C) 2017 Michel Morin. +// +// 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) + +#ifndef BOOST_ITERATOR_ADVANCE_HPP +#define BOOST_ITERATOR_ADVANCE_HPP + +#include +#include +#include + +namespace boost { +namespace iterators { + + namespace detail { + template + inline BOOST_CXX14_CONSTEXPR void + advance_impl( + InputIterator& it + , Distance n + , incrementable_traversal_tag + ) + { + while (n > 0) { + ++it; + --n; + } + } + +#if BOOST_WORKAROUND(BOOST_GCC_VERSION, >= 40600) +// type-limits warning issued below when n is an unsigned integral +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wtype-limits" +#endif + + template + inline BOOST_CXX14_CONSTEXPR void + advance_impl( + BidirectionalIterator& it + , Distance n + , bidirectional_traversal_tag + ) + { + if (n >= 0) { + while (n > 0) { + ++it; + --n; + } + } + else { + while (n < 0) { + --it; + ++n; + } + } + } + +#if BOOST_WORKAROUND(BOOST_GCC_VERSION, >= 40600) +#pragma GCC diagnostic pop +#endif + + template + inline BOOST_CXX14_CONSTEXPR void + advance_impl( + RandomAccessIterator& it + , Distance n + , random_access_traversal_tag + ) + { + it += n; + } + } + + namespace advance_adl_barrier { + template + inline BOOST_CXX14_CONSTEXPR void + advance(InputIterator& it, Distance n) + { + detail::advance_impl( + it, n, typename iterator_traversal::type() + ); + } + } + + using namespace advance_adl_barrier; + +} // namespace iterators + +using namespace iterators::advance_adl_barrier; + +} // namespace boost + +#endif diff --git a/libs/iterator/include/boost/iterator/counting_iterator.hpp b/libs/iterator/include/boost/iterator/counting_iterator.hpp new file mode 100644 index 00000000..65c11e94 --- /dev/null +++ b/libs/iterator/include/boost/iterator/counting_iterator.hpp @@ -0,0 +1,254 @@ +// Copyright David Abrahams 2003. +// 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) +#ifndef COUNTING_ITERATOR_DWA200348_HPP +# define COUNTING_ITERATOR_DWA200348_HPP + +# include +# include +# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +# include +# elif !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) +# include +# else +# include +# endif +# include +# include +# include +# include +# include +# include + +namespace boost { +namespace iterators { + +template < + class Incrementable + , class CategoryOrTraversal + , class Difference +> +class counting_iterator; + +namespace detail +{ + // Try to detect numeric types at compile time in ways compatible + // with the limitations of the compiler and library. + template + struct is_numeric_impl + { + // For a while, this wasn't true, but we rely on it below. This is a regression assert. + BOOST_STATIC_ASSERT(::boost::is_integral::value); + +# ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + + BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_specialized); + +# else + +# if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) + BOOST_STATIC_CONSTANT( + bool, value = ( + boost::is_convertible::value + && boost::is_convertible::value + )); +# else + BOOST_STATIC_CONSTANT(bool, value = ::boost::is_arithmetic::value); +# endif + +# endif + }; + + template + struct is_numeric + : boost::integral_constant::value> + {}; + +# if defined(BOOST_HAS_LONG_LONG) + template <> + struct is_numeric + : boost::true_type {}; + + template <> + struct is_numeric + : boost::true_type {}; +# endif + +# if defined(BOOST_HAS_INT128) + template <> + struct is_numeric + : boost::true_type {}; + + template <> + struct is_numeric + : boost::true_type {}; +# endif + + // Some compilers fail to have a numeric_limits specialization + template <> + struct is_numeric + : true_type {}; + + template + struct numeric_difference + { + typedef typename boost::detail::numeric_traits::difference_type type; + }; + +# if defined(BOOST_HAS_INT128) + // std::numeric_limits, which is used by numeric_traits, is not specialized for __int128 in some standard libraries + template <> + struct numeric_difference + { + typedef boost::int128_type type; + }; + + template <> + struct numeric_difference + { + typedef boost::int128_type type; + }; +# endif + + template + struct counting_iterator_base + { + typedef typename detail::ia_dflt_help< + CategoryOrTraversal + , typename boost::conditional< + is_numeric::value + , boost::type_identity + , iterator_traversal + >::type + >::type traversal; + + typedef typename detail::ia_dflt_help< + Difference + , typename boost::conditional< + is_numeric::value + , numeric_difference + , iterator_difference + >::type + >::type difference; + + typedef iterator_adaptor< + counting_iterator // self + , Incrementable // Base + , Incrementable // Value +# ifndef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY + const // MSVC won't strip this. Instead we enable Thomas' + // criterion (see boost/iterator/detail/facade_iterator_category.hpp) +# endif + , traversal + , Incrementable const& // reference + , difference + > type; + }; + + // Template class distance_policy_select -- choose a policy for computing the + // distance between counting_iterators at compile-time based on whether or not + // the iterator wraps an integer or an iterator, using "poor man's partial + // specialization". + + template struct distance_policy_select; + + // A policy for wrapped iterators + template + struct iterator_distance + { + static Difference distance(Incrementable1 x, Incrementable2 y) + { + return y - x; + } + }; + + // A policy for wrapped numbers + template + struct number_distance + { + static Difference distance(Incrementable1 x, Incrementable2 y) + { + return boost::detail::numeric_distance(x, y); + } + }; +} + +template < + class Incrementable + , class CategoryOrTraversal = use_default + , class Difference = use_default +> +class counting_iterator + : public detail::counting_iterator_base< + Incrementable, CategoryOrTraversal, Difference + >::type +{ + typedef typename detail::counting_iterator_base< + Incrementable, CategoryOrTraversal, Difference + >::type super_t; + + friend class iterator_core_access; + + public: + typedef typename super_t::difference_type difference_type; + + BOOST_DEFAULTED_FUNCTION(counting_iterator(), {}) + + BOOST_DEFAULTED_FUNCTION(counting_iterator(counting_iterator const& rhs), : super_t(rhs.base()) {}) + + counting_iterator(Incrementable x) + : super_t(x) + { + } + +# if 0 + template + counting_iterator( + counting_iterator const& t + , typename enable_if_convertible::type* = 0 + ) + : super_t(t.base()) + {} +# endif + + BOOST_DEFAULTED_FUNCTION(counting_iterator& operator=(counting_iterator const& rhs), { *static_cast< super_t* >(this) = static_cast< super_t const& >(rhs); return *this; }) + + private: + + typename super_t::reference dereference() const + { + return this->base_reference(); + } + + template + difference_type + distance_to(counting_iterator const& y) const + { + typedef typename boost::conditional< + detail::is_numeric::value + , detail::number_distance + , detail::iterator_distance + >::type d; + + return d::distance(this->base(), y.base()); + } +}; + +// Manufacture a counting iterator for an arbitrary incrementable type +template +inline counting_iterator +make_counting_iterator(Incrementable x) +{ + typedef counting_iterator result_t; + return result_t(x); +} + +} // namespace iterators + +using iterators::counting_iterator; +using iterators::make_counting_iterator; + +} // namespace boost + +#endif // COUNTING_ITERATOR_DWA200348_HPP diff --git a/libs/iterator/include/boost/iterator/detail/any_conversion_eater.hpp b/libs/iterator/include/boost/iterator/detail/any_conversion_eater.hpp new file mode 100644 index 00000000..429421fd --- /dev/null +++ b/libs/iterator/include/boost/iterator/detail/any_conversion_eater.hpp @@ -0,0 +1,21 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to 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) +#ifndef ANY_CONVERSION_EATER_DWA20031117_HPP +# define ANY_CONVERSION_EATER_DWA20031117_HPP + +namespace boost { +namespace iterators { +namespace detail { + +// This type can be used in traits to "eat" up the one user-defined +// implicit conversion allowed. +struct any_conversion_eater +{ + template + any_conversion_eater(T const&); +}; + +}}} // namespace boost::iterators::detail + +#endif // ANY_CONVERSION_EATER_DWA20031117_HPP diff --git a/libs/iterator/include/boost/iterator/detail/config_def.hpp b/libs/iterator/include/boost/iterator/detail/config_def.hpp new file mode 100644 index 00000000..bd04b75d --- /dev/null +++ b/libs/iterator/include/boost/iterator/detail/config_def.hpp @@ -0,0 +1,128 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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) + +// no include guard multiple inclusion intended + +// +// This is a temporary workaround until the bulk of this is +// available in boost config. +// 23/02/03 thw +// + +#include // for prior +#include + +#ifdef BOOST_ITERATOR_CONFIG_DEF +# error you have nested config_def #inclusion. +#else +# define BOOST_ITERATOR_CONFIG_DEF +#endif + +// We enable this always now. Otherwise, the simple case in +// libs/iterator/test/constant_iterator_arrow.cpp fails to compile +// because the operator-> return is improperly deduced as a non-const +// pointer. +#if 1 || defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + || BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x531)) + +// Recall that in general, compilers without partial specialization +// can't strip constness. Consider counting_iterator, which normally +// passes a const Value to iterator_facade. As a result, any code +// which makes a std::vector of the iterator's value_type will fail +// when its allocator declares functions overloaded on reference and +// const_reference (the same type). +// +// Furthermore, Borland 5.5.1 drops constness in enough ways that we +// end up using a proxy for operator[] when we otherwise shouldn't. +// Using reference constness gives it an extra hint that it can +// return the value_type from operator[] directly, but is not +// strictly necessary. Not sure how best to resolve this one. + +# define BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY 1 + +#endif + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x5A0)) \ + || (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER)) \ + || BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) \ + || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) + +# define BOOST_NO_LVALUE_RETURN_DETECTION + +# if 0 // test code + struct v {}; + + typedef char (&no)[3]; + + template + no foo(T const&, ...); + + template + char foo(T&, int); + + + struct value_iterator + { + v operator*() const; + }; + + template + struct lvalue_deref_helper + { + static T& x; + enum { value = (sizeof(foo(*x,0)) == 1) }; + }; + + int z2[(lvalue_deref_helper::value == 1) ? 1 : -1]; + int z[(lvalue_deref_helper::value) == 1 ? -1 : 1 ]; +# endif + +#endif + +#if BOOST_WORKAROUND(__MWERKS__, <=0x2407) +# define BOOST_NO_IS_CONVERTIBLE // "is_convertible doesn't work for simple types" +#endif + +#if BOOST_WORKAROUND(__GNUC__, == 3) && BOOST_WORKAROUND(__GNUC_MINOR__, < 4) && !defined(__EDG_VERSION__) \ + || BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) +# define BOOST_NO_IS_CONVERTIBLE_TEMPLATE // The following program fails to compile: + +# if 0 // test code + #include + template + struct foo + { + foo(T); + + template + foo(foo const& other) : p(other.p) { } + + T p; + }; + + bool x = boost::is_convertible, foo >::value; +# endif + +#endif + + +#if !defined(BOOST_MSVC) && (defined(BOOST_NO_SFINAE) || defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_IS_CONVERTIBLE_TEMPLATE)) +# define BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY +#endif + +# if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) + +// GCC-2.95 (obsolete) eagerly instantiates templated constructors and conversion +// operators in convertibility checks, causing premature errors. +// +// Borland's problems are harder to diagnose due to lack of an +// instantiation stack backtrace. They may be due in part to the fact +// that it drops cv-qualification willy-nilly in templates. +# define BOOST_NO_ONE_WAY_ITERATOR_INTEROP +# endif + +// no include guard; multiple inclusion intended diff --git a/libs/iterator/include/boost/iterator/detail/config_undef.hpp b/libs/iterator/include/boost/iterator/detail/config_undef.hpp new file mode 100644 index 00000000..a32529c0 --- /dev/null +++ b/libs/iterator/include/boost/iterator/detail/config_undef.hpp @@ -0,0 +1,24 @@ +// (C) Copyright Thomas Witt 2002. +// 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) + +// no include guard multiple inclusion intended + +// +// This is a temporary workaround until the bulk of this is +// available in boost config. +// 23/02/03 thw +// + +#undef BOOST_NO_IS_CONVERTIBLE +#undef BOOST_NO_IS_CONVERTIBLE_TEMPLATE +#undef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY +#undef BOOST_NO_LVALUE_RETURN_DETECTION +#undef BOOST_NO_ONE_WAY_ITERATOR_INTEROP + +#ifdef BOOST_ITERATOR_CONFIG_DEF +# undef BOOST_ITERATOR_CONFIG_DEF +#else +# error missing or nested #include config_def +#endif diff --git a/libs/iterator/include/boost/iterator/detail/enable_if.hpp b/libs/iterator/include/boost/iterator/detail/enable_if.hpp new file mode 100644 index 00000000..dcc9adb7 --- /dev/null +++ b/libs/iterator/include/boost/iterator/detail/enable_if.hpp @@ -0,0 +1,83 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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) +#ifndef BOOST_ENABLE_IF_23022003THW_HPP +#define BOOST_ENABLE_IF_23022003THW_HPP + +#include +#include +#if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_IS_CONVERTIBLE) +#include +#endif + +// +// Boost iterators uses its own enable_if cause we need +// special semantics for deficient compilers. +// 23/02/03 thw +// + +namespace boost +{ + + namespace iterators + { + // + // Base machinery for all kinds of enable if + // + template + struct enabled + { + template + struct base + { + typedef T type; + }; + }; + + // + // For compilers that don't support "Substitution Failure Is Not An Error" + // enable_if falls back to always enabled. See comments + // on operator implementation for consequences. + // + template<> + struct enabled + { + template + struct base + { +#ifdef BOOST_NO_SFINAE + typedef T type; + + // This way to do it would give a nice error message containing + // invalid overload, but has the big disadvantage that + // there is no reference to user code in the error message. + // + // struct invalid_overload; + // typedef invalid_overload type; + // +#endif + }; + }; + + + template + struct enable_if +# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE) + : enabled<(Cond::value)>::template base +# else + : boost::type_identity +# endif + { + }; + + } // namespace iterators + +} // namespace boost + +#include + +#endif // BOOST_ENABLE_IF_23022003THW_HPP diff --git a/libs/iterator/include/boost/iterator/detail/facade_iterator_category.hpp b/libs/iterator/include/boost/iterator/detail/facade_iterator_category.hpp new file mode 100644 index 00000000..9d41320f --- /dev/null +++ b/libs/iterator/include/boost/iterator/detail/facade_iterator_category.hpp @@ -0,0 +1,193 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to 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) +#ifndef FACADE_ITERATOR_CATEGORY_DWA20031118_HPP +# define FACADE_ITERATOR_CATEGORY_DWA20031118_HPP + +# include + +# include + +# include // used in iterator_tag inheritance logic +# include +# include +# include +# include + +# include + +# include +# include +# include +# include + +# include // try to keep this last + +# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY +# include +# endif + +// +// iterator_category deduction for iterator_facade +// + +namespace boost { +namespace iterators { + +using boost::use_default; + +namespace detail { + +struct input_output_iterator_tag + : std::input_iterator_tag +{ + // Using inheritance for only input_iterator_tag helps to avoid + // ambiguities when a stdlib implementation dispatches on a + // function which is overloaded on both input_iterator_tag and + // output_iterator_tag, as STLPort does, in its __valid_range + // function. I claim it's better to avoid the ambiguity in these + // cases. + operator std::output_iterator_tag() const + { + return std::output_iterator_tag(); + } +}; + +// +// True iff the user has explicitly disabled writability of this +// iterator. Pass the iterator_facade's Value parameter and its +// nested ::reference type. +// +template +struct iterator_writability_disabled +# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic? + : mpl::or_< + is_const + , boost::detail::indirect_traits::is_reference_to_const + , is_const + > +# else + : is_const +# endif +{}; + + +// +// Convert an iterator_facade's traversal category, Value parameter, +// and ::reference type to an appropriate old-style category. +// +// Due to changeset 21683, this now never results in a category convertible +// to output_iterator_tag. +// +// Change at: https://svn.boost.org/trac/boost/changeset/21683 +template +struct iterator_facade_default_category + : mpl::eval_if< + mpl::and_< + is_reference + , is_convertible + > + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::if_< + is_convertible + , std::bidirectional_iterator_tag + , std::forward_iterator_tag + > + > + , typename mpl::eval_if< + mpl::and_< + is_convertible + + // check for readability + , is_convertible + > + , mpl::identity + , mpl::identity + > + > +{ +}; + +// True iff T is convertible to an old-style iterator category. +template +struct is_iterator_category + : mpl::or_< + is_convertible + , is_convertible + > +{ +}; + +template +struct is_iterator_traversal + : is_convertible +{}; + +// +// A composite iterator_category tag convertible to Category (a pure +// old-style category) and Traversal (a pure traversal tag). +// Traversal must be a strict increase of the traversal power given by +// Category. +// +template +struct iterator_category_with_traversal + : Category, Traversal +{ + // Make sure this isn't used to build any categories where + // convertibility to Traversal is redundant. Should just use the + // Category element in that case. + BOOST_STATIC_ASSERT(( + !is_convertible< + typename iterator_category_to_traversal::type + , Traversal + >::value)); + + BOOST_STATIC_ASSERT(is_iterator_category::value); + BOOST_STATIC_ASSERT(!is_iterator_category::value); + BOOST_STATIC_ASSERT(!is_iterator_traversal::value); +# if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) + BOOST_STATIC_ASSERT(is_iterator_traversal::value); +# endif +}; + +// Computes an iterator_category tag whose traversal is Traversal and +// which is appropriate for an iterator +template +struct facade_iterator_category_impl +{ + BOOST_STATIC_ASSERT(!is_iterator_category::value); + + typedef typename iterator_facade_default_category< + Traversal,ValueParam,Reference + >::type category; + + typedef typename mpl::if_< + is_same< + Traversal + , typename iterator_category_to_traversal::type + > + , category + , iterator_category_with_traversal + >::type type; +}; + +// +// Compute an iterator_category for iterator_facade +// +template +struct facade_iterator_category + : mpl::eval_if< + is_iterator_category + , mpl::identity // old-style categories are fine as-is + , facade_iterator_category_impl + > +{ +}; + +}}} // namespace boost::iterators::detail + +# include + +#endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP diff --git a/libs/iterator/include/boost/iterator/detail/minimum_category.hpp b/libs/iterator/include/boost/iterator/detail/minimum_category.hpp new file mode 100644 index 00000000..748c0d3e --- /dev/null +++ b/libs/iterator/include/boost/iterator/detail/minimum_category.hpp @@ -0,0 +1,19 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to 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) +#ifndef MINIMUM_CATEGORY_DWA20031119_HPP +# define MINIMUM_CATEGORY_DWA20031119_HPP + +# include + +namespace boost { + +// This import below (as well as the whole header) is for backward compatibility +// with boost/token_iterator.hpp. It should be removed as soon as that header is fixed. +namespace detail { +using iterators::minimum_category; +} // namespace detail + +} // namespace boost + +#endif // MINIMUM_CATEGORY_DWA20031119_HPP diff --git a/libs/iterator/include/boost/iterator/distance.hpp b/libs/iterator/include/boost/iterator/distance.hpp new file mode 100644 index 00000000..bef650b2 --- /dev/null +++ b/libs/iterator/include/boost/iterator/distance.hpp @@ -0,0 +1,65 @@ +// Copyright (C) 2017 Michel Morin. +// +// 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) + +#ifndef BOOST_ITERATOR_DISTANCE_HPP +#define BOOST_ITERATOR_DISTANCE_HPP + +#include +#include +#include + +namespace boost { +namespace iterators { + + namespace detail { + template + inline BOOST_CXX14_CONSTEXPR typename iterator_difference::type + distance_impl( + SinglePassIterator first + , SinglePassIterator last + , single_pass_traversal_tag + ) + { + typename iterator_difference::type n = 0; + while (first != last) { + ++first; + ++n; + } + return n; + } + + template + inline BOOST_CXX14_CONSTEXPR typename iterator_difference::type + distance_impl( + RandomAccessIterator first + , RandomAccessIterator last + , random_access_traversal_tag + ) + { + return last - first; + } + } + + namespace distance_adl_barrier { + template + inline BOOST_CXX14_CONSTEXPR typename iterator_difference::type + distance(SinglePassIterator first, SinglePassIterator last) + { + return detail::distance_impl( + first, last, typename iterator_traversal::type() + ); + } + } + + using namespace distance_adl_barrier; + +} // namespace iterators + +using namespace iterators::distance_adl_barrier; + +} // namespace boost + +#endif diff --git a/libs/iterator/include/boost/iterator/filter_iterator.hpp b/libs/iterator/include/boost/iterator/filter_iterator.hpp new file mode 100644 index 00000000..18c6186a --- /dev/null +++ b/libs/iterator/include/boost/iterator/filter_iterator.hpp @@ -0,0 +1,146 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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) +#ifndef BOOST_FILTER_ITERATOR_23022003THW_HPP +#define BOOST_FILTER_ITERATOR_23022003THW_HPP + +#include +#include + +#include +#include +#include +#include + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_ITERATOR_DETAIL_MOVE(_type, _value) static_cast< _type&& >(_value) +#else +#define BOOST_ITERATOR_DETAIL_MOVE(_type, _value) _value +#endif + +namespace boost { +namespace iterators { + + template + class filter_iterator; + + namespace detail + { + template + struct filter_iterator_base + { + typedef iterator_adaptor< + filter_iterator + , Iterator + , use_default + , typename mpl::if_< + is_convertible< + typename iterator_traversal::type + , random_access_traversal_tag + > + , bidirectional_traversal_tag + , use_default + >::type + > type; + }; + } + + template + class filter_iterator + : public detail::filter_iterator_base::type + { + typedef typename detail::filter_iterator_base< + Predicate, Iterator + >::type super_t; + + friend class iterator_core_access; + + public: + filter_iterator() { } + + filter_iterator(Predicate f, Iterator x, Iterator end_ = Iterator()) + : super_t(BOOST_ITERATOR_DETAIL_MOVE(Iterator, x)), m_predicate(BOOST_ITERATOR_DETAIL_MOVE(Predicate, f)), m_end(BOOST_ITERATOR_DETAIL_MOVE(Iterator, end_)) + { + satisfy_predicate(); + } + + filter_iterator(Iterator x, Iterator end_ = Iterator()) + : super_t(BOOST_ITERATOR_DETAIL_MOVE(Iterator, x)), m_predicate(), m_end(BOOST_ITERATOR_DETAIL_MOVE(Iterator, end_)) + { + // Pro8 is a little too aggressive about instantiating the + // body of this function. +#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + // Don't allow use of this constructor if Predicate is a + // function pointer type, since it will be 0. + BOOST_STATIC_ASSERT(is_class::value); +#endif + satisfy_predicate(); + } + + template + filter_iterator( + filter_iterator const& t + , typename enable_if_convertible::type* = 0 + ) + : super_t(t.base()), m_predicate(t.predicate()), m_end(t.end()) {} + + Predicate predicate() const { return m_predicate; } + + Iterator end() const { return m_end; } + + private: + void increment() + { + ++(this->base_reference()); + satisfy_predicate(); + } + + void decrement() + { + while(!this->m_predicate(*--(this->base_reference()))){}; + } + + void satisfy_predicate() + { + while (this->base() != this->m_end && !this->m_predicate(*this->base())) + ++(this->base_reference()); + } + + // Probably should be the initial base class so it can be + // optimized away via EBO if it is an empty class. + Predicate m_predicate; + Iterator m_end; + }; + + template + inline filter_iterator + make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()) + { + return filter_iterator(BOOST_ITERATOR_DETAIL_MOVE(Predicate, f), BOOST_ITERATOR_DETAIL_MOVE(Iterator, x), BOOST_ITERATOR_DETAIL_MOVE(Iterator, end)); + } + + template + inline filter_iterator + make_filter_iterator( + typename iterators::enable_if< + is_class + , Iterator + >::type x + , Iterator end = Iterator()) + { + return filter_iterator(BOOST_ITERATOR_DETAIL_MOVE(Iterator, x), BOOST_ITERATOR_DETAIL_MOVE(Iterator, end)); + } + +} // namespace iterators + +using iterators::filter_iterator; +using iterators::make_filter_iterator; + +} // namespace boost + +#undef BOOST_ITERATOR_DETAIL_MOVE + +#endif // BOOST_FILTER_ITERATOR_23022003THW_HPP diff --git a/libs/iterator/include/boost/iterator/function_input_iterator.hpp b/libs/iterator/include/boost/iterator/function_input_iterator.hpp new file mode 100644 index 00000000..610c1338 --- /dev/null +++ b/libs/iterator/include/boost/iterator/function_input_iterator.hpp @@ -0,0 +1,180 @@ +// Copyright 2009 (C) Dean Michael Berris +// Copyright 2012 (C) Google, Inc. +// Copyright 2012 (C) Jeffrey Lee Hellrung, Jr. +// 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) +// + +#ifndef BOOST_FUNCTION_INPUT_ITERATOR +#define BOOST_FUNCTION_INPUT_ITERATOR + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_RESULT_OF_USE_TR1 +#include +#endif + +namespace boost { + +namespace iterators { + + template + class function_input_iterator; + + namespace impl { + + // Computes the return type of an lvalue-call with an empty argument, + // i.e. decltype(declval()()). F should be a nullary lvalue-callable + // or function. + template + struct result_of_nullary_lvalue_call + { + typedef typename result_of< +#ifdef BOOST_RESULT_OF_USE_TR1 + typename boost::conditional::value, F&, F>::type() +#else + F&() +#endif + >::type type; + }; + + template + class function_object_input_iterator : + public iterator_facade< + iterators::function_input_iterator, + typename result_of_nullary_lvalue_call::type, + single_pass_traversal_tag, + typename result_of_nullary_lvalue_call::type const & + > + { + public: + function_object_input_iterator() {} + function_object_input_iterator(Function & f_, Input state_ = Input()) + : f(boost::addressof(f_)), state(state_) {} + + void increment() { + if (value) + value = none; + else + (*f)(); + ++state; + } + + typename result_of_nullary_lvalue_call::type const & + dereference() const { + if (!value) + value = (*f)(); + return value.get(); + } + + bool equal(function_object_input_iterator const & other) const { + return f == other.f && state == other.state; + } + + private: + Function * f; + Input state; + mutable optional::type> value; + }; + + template + class function_pointer_input_iterator : + public iterator_facade< + iterators::function_input_iterator, + typename function_types::result_type::type, + single_pass_traversal_tag, + typename function_types::result_type::type const & + > + { + public: + function_pointer_input_iterator() {} + function_pointer_input_iterator(Function &f_, Input state_ = Input()) + : f(f_), state(state_) {} + + void increment() { + if (value) + value = none; + else + (*f)(); + ++state; + } + + typename function_types::result_type::type const & + dereference() const { + if (!value) + value = (*f)(); + return value.get(); + } + + bool equal(function_pointer_input_iterator const & other) const { + return f == other.f && state == other.state; + } + + private: + Function f; + Input state; + mutable optional::type> value; + }; + + } // namespace impl + + template + class function_input_iterator : + public boost::conditional< + function_types::is_function_pointer::value, + impl::function_pointer_input_iterator, + impl::function_object_input_iterator + >::type + { + typedef typename boost::conditional< + function_types::is_function_pointer::value, + impl::function_pointer_input_iterator, + impl::function_object_input_iterator + >::type base_type; + public: + function_input_iterator(Function & f, Input i) + : base_type(f, i) {} + }; + + template + inline function_input_iterator + make_function_input_iterator(Function & f, Input state) { + typedef function_input_iterator result_t; + return result_t(f, state); + } + + template + inline function_input_iterator + make_function_input_iterator(Function * f, Input state) { + typedef function_input_iterator result_t; + return result_t(f, state); + } + + struct infinite + { + infinite & operator++() { return *this; } + infinite & operator++(int) { return *this; } + bool operator==(infinite &) const { return false; }; + bool operator==(infinite const &) const { return false; }; + }; + +} // namespace iterators + +using iterators::function_input_iterator; +using iterators::make_function_input_iterator; +using iterators::infinite; + +} // namespace boost + +#endif + diff --git a/libs/iterator/include/boost/iterator/function_output_iterator.hpp b/libs/iterator/include/boost/iterator/function_output_iterator.hpp new file mode 100644 index 00000000..b59cbc91 --- /dev/null +++ b/libs/iterator/include/boost/iterator/function_output_iterator.hpp @@ -0,0 +1,95 @@ +// (C) Copyright Jeremy Siek 2001. +// 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) + +// Revision History: + +// 27 Feb 2001 Jeremy Siek +// Initial checkin. + +#ifndef BOOST_ITERATOR_FUNCTION_OUTPUT_ITERATOR_HPP +#define BOOST_ITERATOR_FUNCTION_OUTPUT_ITERATOR_HPP + +#include +#include +#include +#include +#include +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#include +#endif + +namespace boost { +namespace iterators { + + template + class function_output_iterator { + private: + typedef function_output_iterator self; + + class output_proxy { + public: + explicit output_proxy(UnaryFunction& f) BOOST_NOEXCEPT : m_f(f) { } + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + template + typename boost::disable_if_c< + boost::is_same< typename boost::remove_cv< T >::type, output_proxy >::value, + output_proxy& + >::type operator=(const T& value) { + m_f(value); + return *this; + } +#else + template + typename boost::disable_if_c< + boost::is_same< typename boost::remove_cv< typename boost::remove_reference< T >::type >::type, output_proxy >::value, + output_proxy& + >::type operator=(T&& value) { + m_f(static_cast< T&& >(value)); + return *this; + } +#endif + + BOOST_DEFAULTED_FUNCTION(output_proxy(output_proxy const& that), BOOST_NOEXCEPT : m_f(that.m_f) {}) + BOOST_DELETED_FUNCTION(output_proxy& operator=(output_proxy const&)) + + private: + UnaryFunction& m_f; + }; + + public: + typedef std::output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + explicit function_output_iterator() {} + + explicit function_output_iterator(const UnaryFunction& f) + : m_f(f) {} + + output_proxy operator*() { return output_proxy(m_f); } + self& operator++() { return *this; } + self& operator++(int) { return *this; } + + private: + UnaryFunction m_f; + }; + + template + inline function_output_iterator + make_function_output_iterator(const UnaryFunction& f = UnaryFunction()) { + return function_output_iterator(f); + } + +} // namespace iterators + +using iterators::function_output_iterator; +using iterators::make_function_output_iterator; + +} // namespace boost + +#endif // BOOST_ITERATOR_FUNCTION_OUTPUT_ITERATOR_HPP diff --git a/libs/iterator/include/boost/iterator/indirect_iterator.hpp b/libs/iterator/include/boost/iterator/indirect_iterator.hpp new file mode 100644 index 00000000..e15ac87e --- /dev/null +++ b/libs/iterator/include/boost/iterator/indirect_iterator.hpp @@ -0,0 +1,145 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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) +#ifndef BOOST_INDIRECT_ITERATOR_23022003THW_HPP +#define BOOST_INDIRECT_ITERATOR_23022003THW_HPP + +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef BOOST_MPL_CFG_NO_HAS_XXX +# include +# include +# include +# include +#endif + +#include // must be last #include + +namespace boost { +namespace iterators { + + template + class indirect_iterator; + + namespace detail + { + template + struct indirect_base + { + typedef typename std::iterator_traits::value_type dereferenceable; + + typedef iterator_adaptor< + indirect_iterator + , Iter + , typename ia_dflt_help< + Value, pointee + >::type + , Category + , typename ia_dflt_help< + Reference + , mpl::eval_if< + is_same + , indirect_reference + , add_reference + > + >::type + , Difference + > type; + }; + + template <> + struct indirect_base {}; + } // namespace detail + + + template < + class Iterator + , class Value = use_default + , class Category = use_default + , class Reference = use_default + , class Difference = use_default + > + class indirect_iterator + : public detail::indirect_base< + Iterator, Value, Category, Reference, Difference + >::type + { + typedef typename detail::indirect_base< + Iterator, Value, Category, Reference, Difference + >::type super_t; + + friend class iterator_core_access; + + public: + indirect_iterator() {} + + indirect_iterator(Iterator iter) + : super_t(iter) {} + + template < + class Iterator2, class Value2, class Category2 + , class Reference2, class Difference2 + > + indirect_iterator( + indirect_iterator< + Iterator2, Value2, Category2, Reference2, Difference2 + > const& y + , typename enable_if_convertible::type* = 0 + ) + : super_t(y.base()) + {} + + private: + typename super_t::reference dereference() const + { +# if BOOST_WORKAROUND(BOOST_BORLANDC, < 0x5A0 ) + return const_cast(**this->base()); +# else + return **this->base(); +# endif + } + }; + + template + inline + indirect_iterator make_indirect_iterator(Iter x) + { + return indirect_iterator(x); + } + + template + inline + indirect_iterator make_indirect_iterator(Iter x, Traits* = 0) + { + return indirect_iterator(x); + } + +} // namespace iterators + +using iterators::indirect_iterator; +using iterators::make_indirect_iterator; + +} // namespace boost + +#include + +#endif // BOOST_INDIRECT_ITERATOR_23022003THW_HPP diff --git a/libs/iterator/include/boost/iterator/interoperable.hpp b/libs/iterator/include/boost/iterator/interoperable.hpp new file mode 100644 index 00000000..6f3c872a --- /dev/null +++ b/libs/iterator/include/boost/iterator/interoperable.hpp @@ -0,0 +1,54 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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) +#ifndef BOOST_INTEROPERABLE_23022003THW_HPP +# define BOOST_INTEROPERABLE_23022003THW_HPP + +# include +# include + +# include + +# include // must appear last + +namespace boost { +namespace iterators { + + // + // Meta function that determines whether two + // iterator types are considered interoperable. + // + // Two iterator types A,B are considered interoperable if either + // A is convertible to B or vice versa. + // This interoperability definition is in sync with the + // standards requirements on constant/mutable container + // iterators (23.1 [lib.container.requirements]). + // + // For compilers that don't support is_convertible + // is_interoperable gives false positives. See comments + // on operator implementation for consequences. + // + template + struct is_interoperable +# ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY + : mpl::true_ +# else + : mpl::or_< + is_convertible< A, B > + , is_convertible< B, A > > +# endif + { + }; + +} // namespace iterators + +using iterators::is_interoperable; + +} // namespace boost + +# include + +#endif // BOOST_INTEROPERABLE_23022003THW_HPP diff --git a/libs/iterator/include/boost/iterator/is_iterator.hpp b/libs/iterator/include/boost/iterator/is_iterator.hpp new file mode 100644 index 00000000..5740b19e --- /dev/null +++ b/libs/iterator/include/boost/iterator/is_iterator.hpp @@ -0,0 +1,148 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * https://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2023 Andrey Semashev + */ +/*! + * \file iterator/is_iterator.hpp + * + * This header contains definition of the \c is_iterator type trait. + */ + +#ifndef BOOST_ITERATOR_IS_ITERATOR_HPP_INCLUDED_ +#define BOOST_ITERATOR_IS_ITERATOR_HPP_INCLUDED_ + +#include +#include +#include +#include +#include +#include +#include +#if !defined(BOOST_NO_CXX17_ITERATOR_TRAITS) +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace iterators { +namespace detail { + +// The trait attempts to detect if the T type is an iterator class. Class-type iterators are assumed +// to have the nested type iterator_category. Strictly speaking, this is not required to be the +// case (e.g. a user can specialize iterator_traits for T without defining T::iterator_category). +// Still, this is a good heuristic in practice, and we can't do anything better anyway. +// Since C++17 we can test for iterator_traits::iterator_category presence instead as it is +// required to be only present for iterators. +namespace has_iterator_category_detail { + +typedef char yes_type; +struct no_type { char padding[2]; }; + +template< typename T > +yes_type check( +#if !defined(BOOST_NO_CXX17_ITERATOR_TRAITS) + typename std::iterator_traits< T >::iterator_category* +#else + typename T::iterator_category* +#endif +); +template< typename > +no_type check(...); + +} // namespace has_iterator_category_detail + +template< typename T > +struct is_iterator_impl : + public boost::integral_constant< + bool, + sizeof(has_iterator_category_detail::check< T >(0)) == sizeof(has_iterator_category_detail::yes_type) + > +{ +}; + +template< typename T > +struct is_iterator_impl< T* > : + public boost::conjunction< + boost::is_complete< T >, + boost::negation< boost::is_function< T > > + >::type +{ +}; + +template< typename T, typename U > +struct is_iterator_impl< T U::* > : + public boost::false_type +{ +}; + +template< typename T > +struct is_iterator_impl< T& > : + public boost::false_type +{ +}; + +template< typename T, std::size_t N > +struct is_iterator_impl< T[N] > : + public boost::false_type +{ +}; + +#if !defined(BOOST_TT_HAS_WORKING_IS_COMPLETE) +template< typename T > +struct is_iterator_impl< T[] > : + public boost::false_type +{ +}; + +template< > +struct is_iterator_impl< void > : + public boost::false_type +{ +}; + +template< > +struct is_iterator_impl< void* > : + public boost::false_type +{ +}; +#endif // !defined(BOOST_TT_HAS_WORKING_IS_COMPLETE) + +} // namespace detail + +/*! + * \brief The type trait detects whether the type \c T is an iterator type. + * + * The type trait yields \c true if its argument type \c T, after stripping top level + * cv qualifiers, is one of the following: + * + * - A pointer type, other than a pointer to function, a pointer to a class member, + * or a pointer to an incomplete type, including `void`. + * - A class type for which an iterator category is obtainable. Prior to C++17, + * the iterator category must be defined as a public `T::iterator_category` type. + * Since C++17, the expression `std::iterator_traits< T >::iterator_category` must + * be valid and produce the iterator category type. + * + * Otherwise, the type trait yields \c false. + */ +template< typename T > +struct is_iterator : public detail::is_iterator_impl< T >::type {}; +template< typename T > +struct is_iterator< const T > : public detail::is_iterator_impl< T >::type {}; +template< typename T > +struct is_iterator< volatile T > : public detail::is_iterator_impl< T >::type {}; +template< typename T > +struct is_iterator< const volatile T > : public detail::is_iterator_impl< T >::type {}; + +} // namespace iterators + +using iterators::is_iterator; + +} // namespace boost + +#endif // BOOST_ITERATOR_IS_ITERATOR_HPP_INCLUDED_ diff --git a/libs/iterator/include/boost/iterator/is_lvalue_iterator.hpp b/libs/iterator/include/boost/iterator/is_lvalue_iterator.hpp new file mode 100644 index 00000000..46f0483e --- /dev/null +++ b/libs/iterator/include/boost/iterator/is_lvalue_iterator.hpp @@ -0,0 +1,164 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to 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) +#ifndef IS_LVALUE_ITERATOR_DWA2003112_HPP +# define IS_LVALUE_ITERATOR_DWA2003112_HPP + +#include + +#include +#include +#include +#include + +#include + +// should be the last #includes +#include +#include + +#ifndef BOOST_NO_IS_CONVERTIBLE + +namespace boost { + +namespace iterators { + +namespace detail +{ +#ifndef BOOST_NO_LVALUE_RETURN_DETECTION + // Calling lvalue_preserver( , 0 ) returns a reference + // to the expression's result if is an lvalue, or + // not_an_lvalue() otherwise. + struct not_an_lvalue {}; + + template + T& lvalue_preserver(T&, int); + + template + not_an_lvalue lvalue_preserver(U const&, ...); + +# define BOOST_LVALUE_PRESERVER(expr) detail::lvalue_preserver(expr,0) + +#else + +# define BOOST_LVALUE_PRESERVER(expr) expr + +#endif + + // Guts of is_lvalue_iterator. Value is the iterator's value_type + // and the result is computed in the nested rebind template. + template + struct is_lvalue_iterator_impl + { + // Eat implicit conversions so we don't report true for things + // convertible to Value const& + struct conversion_eater + { + conversion_eater(typename add_lvalue_reference::type); + }; + + static char tester(conversion_eater, int); + static char (& tester(any_conversion_eater, ...) )[2]; + + template + struct rebind + { + static It& x; + + BOOST_STATIC_CONSTANT( + bool + , value = ( + sizeof( + is_lvalue_iterator_impl::tester( + BOOST_LVALUE_PRESERVER(*x), 0 + ) + ) == 1 + ) + ); + }; + }; + +#undef BOOST_LVALUE_PRESERVER + + // + // void specializations to handle std input and output iterators + // + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_lvalue_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; +#endif + + // + // This level of dispatching is required for Borland. We might save + // an instantiation by removing it for others. + // + template + struct is_readable_lvalue_iterator_impl + : is_lvalue_iterator_impl< + BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type const + >::template rebind + {}; + + template + struct is_non_const_lvalue_iterator_impl + : is_lvalue_iterator_impl< + BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type + >::template rebind + {}; +} // namespace detail + +template< typename T > struct is_lvalue_iterator +: public ::boost::integral_constant::value> +{ +public: + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_lvalue_iterator,(T)) +}; + +template< typename T > struct is_non_const_lvalue_iterator +: public ::boost::integral_constant::value> +{ +public: + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_non_const_lvalue_iterator,(T)) +}; + +} // namespace iterators + +using iterators::is_lvalue_iterator; +using iterators::is_non_const_lvalue_iterator; + +} // namespace boost + +#endif + +#include + +#endif // IS_LVALUE_ITERATOR_DWA2003112_HPP diff --git a/libs/iterator/include/boost/iterator/is_readable_iterator.hpp b/libs/iterator/include/boost/iterator/is_readable_iterator.hpp new file mode 100644 index 00000000..26827c4c --- /dev/null +++ b/libs/iterator/include/boost/iterator/is_readable_iterator.hpp @@ -0,0 +1,119 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to 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) +#ifndef IS_READABLE_ITERATOR_DWA2003112_HPP +# define IS_READABLE_ITERATOR_DWA2003112_HPP + +#include +#include +#include + +#include + +#include + +// should be the last #include +#include +#include + +#ifndef BOOST_NO_IS_CONVERTIBLE + +namespace boost { + +namespace iterators { + +namespace detail +{ + // Guts of is_readable_iterator. Value is the iterator's value_type + // and the result is computed in the nested rebind template. + template + struct is_readable_iterator_impl + { + static char tester(typename add_lvalue_reference::type, int); + static char (& tester(any_conversion_eater, ...) )[2]; + + template + struct rebind + { + static It& x; + + BOOST_STATIC_CONSTANT( + bool + , value = ( + sizeof( + is_readable_iterator_impl::tester(*x, 1) + ) == 1 + ) + ); + }; + }; + +#undef BOOST_READABLE_PRESERVER + + // + // void specializations to handle std input and output iterators + // + template <> + struct is_readable_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS + template <> + struct is_readable_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_readable_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; + + template <> + struct is_readable_iterator_impl + { + template + struct rebind : boost::mpl::false_ + {}; + }; +#endif + + // + // This level of dispatching is required for Borland. We might save + // an instantiation by removing it for others. + // + template + struct is_readable_iterator_impl2 + : is_readable_iterator_impl< + BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type const + >::template rebind + {}; +} // namespace detail + +template< typename T > struct is_readable_iterator +: public ::boost::integral_constant::value> +{ +public: + BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_readable_iterator,(T)) +}; + +} // namespace iterators + +using iterators::is_readable_iterator; + +} // namespace boost + +#endif + +#include + +#endif // IS_READABLE_ITERATOR_DWA2003112_HPP diff --git a/libs/iterator/include/boost/iterator/iterator_adaptor.hpp b/libs/iterator/include/boost/iterator/iterator_adaptor.hpp new file mode 100644 index 00000000..db1c4daa --- /dev/null +++ b/libs/iterator/include/boost/iterator/iterator_adaptor.hpp @@ -0,0 +1,358 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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) +#ifndef BOOST_ITERATOR_ADAPTOR_23022003THW_HPP +#define BOOST_ITERATOR_ADAPTOR_23022003THW_HPP + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY +# include +#endif + +#include +#include + +#include + +namespace boost { +namespace iterators { + + // Used as a default template argument internally, merely to + // indicate "use the default", this can also be passed by users + // explicitly in order to specify that the default should be used. + using boost::use_default; + +} // namespace iterators + +// the incompleteness of use_default causes massive problems for +// is_convertible (naturally). This workaround is fortunately not +// needed for vc6/vc7. +template +struct is_convertible + : mpl::false_ {}; + +namespace iterators { + + namespace detail + { + + // + // Result type used in enable_if_convertible meta function. + // This can be an incomplete type, as only pointers to + // enable_if_convertible< ... >::type are used. + // We could have used void for this, but conversion to + // void* is just to easy. + // + struct enable_type; + } + + + // + // enable_if for use in adapted iterators constructors. + // + // In order to provide interoperability between adapted constant and + // mutable iterators, adapted iterators will usually provide templated + // conversion constructors of the following form + // + // template + // class adapted_iterator : + // public iterator_adaptor< adapted_iterator, Iterator > + // { + // public: + // + // ... + // + // template + // adapted_iterator( + // OtherIterator const& it + // , typename enable_if_convertible::type* = 0); + // + // ... + // }; + // + // enable_if_convertible is used to remove those overloads from the overload + // set that cannot be instantiated. For all practical purposes only overloads + // for constant/mutable interaction will remain. This has the advantage that + // meta functions like boost::is_convertible do not return false positives, + // as they can only look at the signature of the conversion constructor + // and not at the actual instantiation. + // + // enable_if_interoperable can be safely used in user code. It falls back to + // always enabled for compilers that don't support enable_if or is_convertible. + // There is no need for compiler specific workarounds in user code. + // + // The operators implementation relies on boost::is_convertible not returning + // false positives for user/library defined iterator types. See comments + // on operator implementation for consequences. + // +# if defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_SFINAE) + + template + struct enable_if_convertible + { + typedef boost::iterators::detail::enable_type type; + }; + +# elif BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) + + // For some reason vc7.1 needs us to "cut off" instantiation + // of is_convertible in a few cases. + template + struct enable_if_convertible + : iterators::enable_if< + mpl::or_< + is_same + , is_convertible + > + , boost::iterators::detail::enable_type + > + {}; + +# else + + template + struct enable_if_convertible + : iterators::enable_if< + is_convertible + , boost::iterators::detail::enable_type + > + {}; + +# endif + + // + // Default template argument handling for iterator_adaptor + // + namespace detail + { + // If T is use_default, return the result of invoking + // DefaultNullaryFn, otherwise return T. + template + struct ia_dflt_help + : mpl::eval_if< + is_same + , DefaultNullaryFn + , mpl::identity + > + { + }; + + // A metafunction which computes an iterator_adaptor's base class, + // a specialization of iterator_facade. + template < + class Derived + , class Base + , class Value + , class Traversal + , class Reference + , class Difference + > + struct iterator_adaptor_base + { + typedef iterator_facade< + Derived + +# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY + , typename boost::iterators::detail::ia_dflt_help< + Value + , mpl::eval_if< + is_same + , iterator_value + , remove_reference + > + >::type +# else + , typename boost::iterators::detail::ia_dflt_help< + Value, iterator_value + >::type +# endif + + , typename boost::iterators::detail::ia_dflt_help< + Traversal + , iterator_traversal + >::type + + , typename boost::iterators::detail::ia_dflt_help< + Reference + , mpl::eval_if< + is_same + , iterator_reference + , add_reference + > + >::type + + , typename boost::iterators::detail::ia_dflt_help< + Difference, iterator_difference + >::type + > + type; + }; + + // workaround for aC++ CR JAGaf33512 + template + inline void iterator_adaptor_assert_traversal () + { + BOOST_STATIC_ASSERT((is_convertible::value)); + } + } + + // + // Iterator Adaptor + // + // The parameter ordering changed slightly with respect to former + // versions of iterator_adaptor The idea is that when the user needs + // to fiddle with the reference type it is highly likely that the + // iterator category has to be adjusted as well. Any of the + // following four template arguments may be ommitted or explicitly + // replaced by use_default. + // + // Value - if supplied, the value_type of the resulting iterator, unless + // const. If const, a conforming compiler strips constness for the + // value_type. If not supplied, iterator_traits::value_type is used + // + // Category - the traversal category of the resulting iterator. If not + // supplied, iterator_traversal::type is used. + // + // Reference - the reference type of the resulting iterator, and in + // particular, the result type of operator*(). If not supplied but + // Value is supplied, Value& is used. Otherwise + // iterator_traits::reference is used. + // + // Difference - the difference_type of the resulting iterator. If not + // supplied, iterator_traits::difference_type is used. + // + template < + class Derived + , class Base + , class Value = use_default + , class Traversal = use_default + , class Reference = use_default + , class Difference = use_default + > + class iterator_adaptor + : public boost::iterators::detail::iterator_adaptor_base< + Derived, Base, Value, Traversal, Reference, Difference + >::type + { + friend class iterator_core_access; + + protected: + typedef typename boost::iterators::detail::iterator_adaptor_base< + Derived, Base, Value, Traversal, Reference, Difference + >::type super_t; + public: + iterator_adaptor() {} + + explicit iterator_adaptor(Base const &iter) + : m_iterator(iter) + { + } + + typedef Base base_type; + + Base const& base() const + { return m_iterator; } + + protected: + // for convenience in derived classes + typedef iterator_adaptor iterator_adaptor_; + + // + // lvalue access to the Base object for Derived + // + Base const& base_reference() const + { return m_iterator; } + + Base& base_reference() + { return m_iterator; } + + private: + // + // Core iterator interface for iterator_facade. This is private + // to prevent temptation for Derived classes to use it, which + // will often result in an error. Derived classes should use + // base_reference(), above, to get direct access to m_iterator. + // + typename super_t::reference dereference() const + { return *m_iterator; } + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + bool equal(iterator_adaptor const& x) const + { + // Maybe readd with same_distance + // BOOST_STATIC_ASSERT( + // (detail::same_category_and_difference::value) + // ); + return m_iterator == x.base(); + } + + typedef typename iterator_category_to_traversal< + typename super_t::iterator_category + >::type my_traversal; + +# define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \ + boost::iterators::detail::iterator_adaptor_assert_traversal(); + + void advance(typename super_t::difference_type n) + { + BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) + m_iterator += n; + } + + void increment() { ++m_iterator; } + + void decrement() + { + BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag) + --m_iterator; + } + + template < + class OtherDerived, class OtherIterator, class V, class C, class R, class D + > + typename super_t::difference_type distance_to( + iterator_adaptor const& y) const + { + BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag) + // Maybe readd with same_distance + // BOOST_STATIC_ASSERT( + // (detail::same_category_and_difference::value) + // ); + return y.base() - m_iterator; + } + +# undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL + + private: // data members + Base m_iterator; + }; + +} // namespace iterators + +using iterators::iterator_adaptor; +using iterators::enable_if_convertible; + +} // namespace boost + +#include + +#endif // BOOST_ITERATOR_ADAPTOR_23022003THW_HPP diff --git a/libs/iterator/include/boost/iterator/iterator_archetypes.hpp b/libs/iterator/include/boost/iterator/iterator_archetypes.hpp new file mode 100644 index 00000000..1d259152 --- /dev/null +++ b/libs/iterator/include/boost/iterator/iterator_archetypes.hpp @@ -0,0 +1,509 @@ +// (C) Copyright Jeremy Siek 2002. +// 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) + +#ifndef BOOST_ITERATOR_ARCHETYPES_HPP +#define BOOST_ITERATOR_ARCHETYPES_HPP + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace iterators { + +template +struct access_archetype; + +template +struct traversal_archetype; + +namespace archetypes +{ + enum { + readable_iterator_bit = 1 + , writable_iterator_bit = 2 + , swappable_iterator_bit = 4 + , lvalue_iterator_bit = 8 + }; + + // Not quite tags, since dispatching wouldn't work. + typedef mpl::int_::type readable_iterator_t; + typedef mpl::int_::type writable_iterator_t; + + typedef mpl::int_< + (readable_iterator_bit|writable_iterator_bit) + >::type readable_writable_iterator_t; + + typedef mpl::int_< + (readable_iterator_bit|lvalue_iterator_bit) + >::type readable_lvalue_iterator_t; + + typedef mpl::int_< + (lvalue_iterator_bit|writable_iterator_bit) + >::type writable_lvalue_iterator_t; + + typedef mpl::int_::type swappable_iterator_t; + typedef mpl::int_::type lvalue_iterator_t; + + template + struct has_access + : mpl::equal_to< + mpl::bitand_ + , Base + > + {}; +} + +namespace detail +{ + template + struct assign_proxy + { + assign_proxy& operator=(T) { return *this; } + }; + + template + struct read_proxy + { + operator T() { return static_object::get(); } + }; + + template + struct read_write_proxy + : read_proxy // Use to inherit from assign_proxy, but that doesn't work. -JGS + { + read_write_proxy& operator=(T) { return *this; } + }; + + template + struct arrow_proxy + { + T const* operator->() const { return 0; } + }; + + struct no_operator_brackets {}; + + template + struct readable_operator_brackets + { + read_proxy operator[](std::ptrdiff_t n) const { return read_proxy(); } + }; + + template + struct writable_operator_brackets + { + read_write_proxy operator[](std::ptrdiff_t n) const { return read_write_proxy(); } + }; + + template + struct operator_brackets + : mpl::eval_if< + is_convertible + , mpl::eval_if< + archetypes::has_access< + AccessCategory + , archetypes::writable_iterator_t + > + , mpl::identity > + , mpl::if_< + archetypes::has_access< + AccessCategory + , archetypes::readable_iterator_t + > + , readable_operator_brackets + , no_operator_brackets + > + > + , mpl::identity + >::type + {}; + + template + struct traversal_archetype_impl + { + template struct archetype; + }; + + // Constructor argument for those iterators that + // are not default constructible + struct ctor_arg {}; + + template + struct traversal_archetype_ + : traversal_archetype_impl::template archetype + { + typedef typename + traversal_archetype_impl::template archetype + base; + + traversal_archetype_() {} + + traversal_archetype_(ctor_arg arg) + : base(arg) + {} + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + { + explicit archetype(ctor_arg) {} + + struct bogus { }; // This use to be void, but that causes trouble for iterator_facade. Need more research. -JGS + typedef bogus difference_type; + + Derived& operator++() { return (Derived&)static_object::get(); } + Derived operator++(int) const { return (Derived&)static_object::get(); } + }; + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public equality_comparable< traversal_archetype_ >, + public traversal_archetype_ + { + explicit archetype(ctor_arg arg) + : traversal_archetype_(arg) + {} + + typedef std::ptrdiff_t difference_type; + }; + }; + + template + bool operator==(traversal_archetype_ const&, + traversal_archetype_ const&) { return true; } + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + archetype() + : traversal_archetype_(ctor_arg()) + {} + }; + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + Derived& operator--() { return static_object::get(); } + Derived operator--(int) const { return static_object::get(); } + }; + }; + + template <> + struct traversal_archetype_impl + { + template + struct archetype + : public traversal_archetype_ + { + Derived& operator+=(std::ptrdiff_t) { return static_object::get(); } + Derived& operator-=(std::ptrdiff_t) { return static_object::get(); } + }; + }; + + template + Derived& operator+(traversal_archetype_ const&, + std::ptrdiff_t) { return static_object::get(); } + + template + Derived& operator+(std::ptrdiff_t, + traversal_archetype_ const&) + { return static_object::get(); } + + template + Derived& operator-(traversal_archetype_ const&, + std::ptrdiff_t) + { return static_object::get(); } + + template + std::ptrdiff_t operator-(traversal_archetype_ const&, + traversal_archetype_ const&) + { return 0; } + + template + bool operator<(traversal_archetype_ const&, + traversal_archetype_ const&) + { return true; } + + template + bool operator>(traversal_archetype_ const&, + traversal_archetype_ const&) + { return true; } + + template + bool operator<=(traversal_archetype_ const&, + traversal_archetype_ const&) + { return true; } + + template + bool operator>=(traversal_archetype_ const&, + traversal_archetype_ const&) + { return true; } + + struct bogus_type; + + template + struct convertible_type + : mpl::if_< is_const, + typename remove_const::type, + bogus_type > + {}; + +} // namespace detail + + +template struct undefined; + +template +struct iterator_access_archetype_impl +{ + template struct archetype; +}; + +template +struct iterator_access_archetype + : iterator_access_archetype_impl< + AccessCategory + >::template archetype +{ +}; + +template <> +struct iterator_access_archetype_impl< + archetypes::readable_iterator_t +> +{ + template + struct archetype + { + typedef typename remove_cv::type value_type; + typedef Value reference; + typedef Value* pointer; + + value_type operator*() const { return static_object::get(); } + + detail::arrow_proxy operator->() const { return detail::arrow_proxy(); } + }; +}; + +template <> +struct iterator_access_archetype_impl< + archetypes::writable_iterator_t +> +{ + template + struct archetype + { + BOOST_STATIC_ASSERT(!is_const::value); + typedef void value_type; + typedef void reference; + typedef void pointer; + + detail::assign_proxy operator*() const { return detail::assign_proxy(); } + }; +}; + +template <> +struct iterator_access_archetype_impl< + archetypes::readable_writable_iterator_t +> +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, archetypes::readable_iterator_t + > + { + typedef detail::read_write_proxy reference; + + detail::read_write_proxy operator*() const { return detail::read_write_proxy(); } + }; +}; + +template <> +struct iterator_access_archetype_impl +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, archetypes::readable_iterator_t + > + { + typedef Value& reference; + + Value& operator*() const { return static_object::get(); } + Value* operator->() const { return 0; } + }; +}; + +template <> +struct iterator_access_archetype_impl +{ + template + struct archetype + : public virtual iterator_access_archetype< + Value, archetypes::readable_lvalue_iterator_t + > + { + BOOST_STATIC_ASSERT((!is_const::value)); + }; +}; + + +template +struct iterator_archetype; + +template +struct traversal_archetype_base + : detail::operator_brackets< + typename remove_cv::type + , AccessCategory + , TraversalCategory + > + , detail::traversal_archetype_< + iterator_archetype + , Value + , TraversalCategory + > +{ +}; + +namespace detail +{ + template + struct iterator_archetype_base + : iterator_access_archetype + , traversal_archetype_base + { + typedef iterator_access_archetype access; + + typedef typename detail::facade_iterator_category< + TraversalCategory + , typename mpl::eval_if< + archetypes::has_access< + AccessCategory, archetypes::writable_iterator_t + > + , remove_const + , add_const + >::type + , typename access::reference + >::type iterator_category; + + // Needed for some broken libraries (see below) + struct workaround_iterator_base + { + typedef typename iterator_archetype_base::iterator_category iterator_category; + typedef Value value_type; + typedef typename traversal_archetype_base< + Value, AccessCategory, TraversalCategory + >::difference_type difference_type; + typedef typename access::pointer pointer; + typedef typename access::reference reference; + }; + }; +} + +template +struct iterator_archetype + : public detail::iterator_archetype_base + + // These broken libraries require derivation from std::iterator + // (or related magic) in order to handle iter_swap and other + // iterator operations +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ + || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) + , public detail::iterator_archetype_base< + Value, AccessCategory, TraversalCategory + >::workaround_iterator_base +# endif +{ + // Derivation from std::iterator above caused references to nested + // types to be ambiguous, so now we have to redeclare them all + // here. +# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, < 310) \ + || BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(0x20101)) + + typedef detail::iterator_archetype_base< + Value,AccessCategory,TraversalCategory + > base; + + typedef typename base::value_type value_type; + typedef typename base::reference reference; + typedef typename base::pointer pointer; + typedef typename base::difference_type difference_type; + typedef typename base::iterator_category iterator_category; +# endif + + iterator_archetype() { } + iterator_archetype(iterator_archetype const& x) + : detail::iterator_archetype_base< + Value + , AccessCategory + , TraversalCategory + >(x) + {} + + iterator_archetype& operator=(iterator_archetype const&) + { return *this; } + +# if 0 + // Optional conversion from mutable + iterator_archetype( + iterator_archetype< + typename detail::convertible_type::type + , AccessCategory + , TraversalCategory> const& + ); +# endif +}; + +} // namespace iterators + +// Backward compatibility names +namespace iterator_archetypes = iterators::archetypes; +using iterators::access_archetype; +using iterators::traversal_archetype; +using iterators::iterator_archetype; +using iterators::undefined; +using iterators::iterator_access_archetype_impl; +using iterators::traversal_archetype_base; + +} // namespace boost + +#endif // BOOST_ITERATOR_ARCHETYPES_HPP diff --git a/libs/iterator/include/boost/iterator/iterator_categories.hpp b/libs/iterator/include/boost/iterator/iterator_categories.hpp new file mode 100644 index 00000000..baf805af --- /dev/null +++ b/libs/iterator/include/boost/iterator/iterator_categories.hpp @@ -0,0 +1,216 @@ +// (C) Copyright Jeremy Siek 2002. +// 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) + +#ifndef BOOST_ITERATOR_CATEGORIES_HPP +# define BOOST_ITERATOR_CATEGORIES_HPP + +# include +# include + +# include + +# include +# include +# include +# include + +# include + +# include + +#include + +namespace boost { +namespace iterators { + +// +// Traversal Categories +// + +struct no_traversal_tag {}; + +struct incrementable_traversal_tag + : no_traversal_tag +{ +// incrementable_traversal_tag() {} +// incrementable_traversal_tag(std::output_iterator_tag const&) {}; +}; + +struct single_pass_traversal_tag + : incrementable_traversal_tag +{ +// single_pass_traversal_tag() {} +// single_pass_traversal_tag(std::input_iterator_tag const&) {}; +}; + +struct forward_traversal_tag + : single_pass_traversal_tag +{ +// forward_traversal_tag() {} +// forward_traversal_tag(std::forward_iterator_tag const&) {}; +}; + +struct bidirectional_traversal_tag + : forward_traversal_tag +{ +// bidirectional_traversal_tag() {}; +// bidirectional_traversal_tag(std::bidirectional_iterator_tag const&) {}; +}; + +struct random_access_traversal_tag + : bidirectional_traversal_tag +{ +// random_access_traversal_tag() {}; +// random_access_traversal_tag(std::random_access_iterator_tag const&) {}; +}; + +namespace detail +{ + // + // Convert a "strictly old-style" iterator category to a traversal + // tag. This is broken out into a separate metafunction to reduce + // the cost of instantiating iterator_category_to_traversal, below, + // for new-style types. + // + template + struct old_category_to_traversal + : mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , void + > + > + > + > + > + {}; + +} // namespace detail + +// +// Convert an iterator category into a traversal tag +// +template +struct iterator_category_to_traversal + : mpl::eval_if< // if already convertible to a traversal tag, we're done. + is_convertible + , mpl::identity + , boost::iterators::detail::old_category_to_traversal + > +{}; + +// Trait to get an iterator's traversal category +template +struct iterator_traversal + : iterator_category_to_traversal< + typename std::iterator_traits::iterator_category + > +{}; + +# ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT +// Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work +// out well. Instantiating the nested apply template also +// requires instantiating iterator_traits on the +// placeholder. Instead we just specialize it as a metafunction +// class. +template <> +struct iterator_traversal +{ + template + struct apply : iterator_traversal + {}; +}; +template <> +struct iterator_traversal + : iterator_traversal +{}; +# endif + +// +// Convert an iterator traversal to one of the traversal tags. +// +template +struct pure_traversal_tag + : mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , mpl::eval_if< + is_convertible + , mpl::identity + , void + > + > + > + > + > +{ +}; + +// +// Trait to retrieve one of the iterator traversal tags from the iterator category or traversal. +// +template +struct pure_iterator_traversal + : pure_traversal_tag::type> +{}; + +# ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT +template <> +struct pure_iterator_traversal +{ + template + struct apply : pure_iterator_traversal + {}; +}; +template <> +struct pure_iterator_traversal + : pure_iterator_traversal +{}; +# endif + +} // namespace iterators + +using iterators::no_traversal_tag; +using iterators::incrementable_traversal_tag; +using iterators::single_pass_traversal_tag; +using iterators::forward_traversal_tag; +using iterators::bidirectional_traversal_tag; +using iterators::random_access_traversal_tag; +using iterators::iterator_category_to_traversal; +using iterators::iterator_traversal; + +// This import is needed for backward compatibility with Boost.Range: +// boost/range/detail/demote_iterator_traversal_tag.hpp +// It should be removed when that header is fixed. +namespace detail { +using iterators::pure_traversal_tag; +} // namespace detail + +} // namespace boost + +#include + +#endif // BOOST_ITERATOR_CATEGORIES_HPP diff --git a/libs/iterator/include/boost/iterator/iterator_concepts.hpp b/libs/iterator/include/boost/iterator/iterator_concepts.hpp new file mode 100644 index 00000000..3c65553e --- /dev/null +++ b/libs/iterator/include/boost/iterator/iterator_concepts.hpp @@ -0,0 +1,273 @@ +// (C) Copyright Jeremy Siek 2002. +// 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) + +#ifndef BOOST_ITERATOR_CONCEPTS_HPP +#define BOOST_ITERATOR_CONCEPTS_HPP + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +// Use boost/limits to work around missing limits headers on some compilers +#include +#include + +#include +#include + +#include + +namespace boost_concepts +{ + // Used a different namespace here (instead of "boost") so that the + // concept descriptions do not take for granted the names in + // namespace boost. + + //=========================================================================== + // Iterator Access Concepts + + BOOST_concept(ReadableIterator,(Iterator)) + : boost::Assignable + , boost::CopyConstructible + + { + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type value_type; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::reference reference; + + BOOST_CONCEPT_USAGE(ReadableIterator) + { + + value_type v = *i; + boost::ignore_unused_variable_warning(v); + } + private: + Iterator i; + }; + + template < + typename Iterator + , typename ValueType = BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type + > + struct WritableIterator + : boost::CopyConstructible + { + BOOST_CONCEPT_USAGE(WritableIterator) + { + *i = v; + } + private: + ValueType v; + Iterator i; + }; + + template < + typename Iterator + , typename ValueType = BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type + > + struct WritableIteratorConcept : WritableIterator {}; + + BOOST_concept(SwappableIterator,(Iterator)) + { + BOOST_CONCEPT_USAGE(SwappableIterator) + { + std::iter_swap(i1, i2); + } + private: + Iterator i1; + Iterator i2; + }; + + BOOST_concept(LvalueIterator,(Iterator)) + { + typedef typename std::iterator_traits::value_type value_type; + + BOOST_CONCEPT_USAGE(LvalueIterator) + { + value_type& r = const_cast(*i); + boost::ignore_unused_variable_warning(r); + } + private: + Iterator i; + }; + + + //=========================================================================== + // Iterator Traversal Concepts + + BOOST_concept(IncrementableIterator,(Iterator)) + : boost::Assignable + , boost::CopyConstructible + { + typedef typename boost::iterator_traversal::type traversal_category; + + BOOST_CONCEPT_ASSERT(( + boost::Convertible< + traversal_category + , boost::incrementable_traversal_tag + >)); + + BOOST_CONCEPT_USAGE(IncrementableIterator) + { + ++i; + (void)i++; + } + private: + Iterator i; + }; + + BOOST_concept(SinglePassIterator,(Iterator)) + : IncrementableIterator + , boost::EqualityComparable + + { + BOOST_CONCEPT_ASSERT(( + boost::Convertible< + BOOST_DEDUCED_TYPENAME SinglePassIterator::traversal_category + , boost::single_pass_traversal_tag + > )); + }; + + BOOST_concept(ForwardTraversal,(Iterator)) + : SinglePassIterator + , boost::DefaultConstructible + { + typedef typename std::iterator_traits::difference_type difference_type; + + BOOST_STATIC_ASSERT(boost::is_integral::value); + BOOST_STATIC_ASSERT(std::numeric_limits::is_signed); + + BOOST_CONCEPT_ASSERT(( + boost::Convertible< + BOOST_DEDUCED_TYPENAME ForwardTraversal::traversal_category + , boost::forward_traversal_tag + > )); + }; + + BOOST_concept(BidirectionalTraversal,(Iterator)) + : ForwardTraversal + { + BOOST_CONCEPT_ASSERT(( + boost::Convertible< + BOOST_DEDUCED_TYPENAME BidirectionalTraversal::traversal_category + , boost::bidirectional_traversal_tag + > )); + + BOOST_CONCEPT_USAGE(BidirectionalTraversal) + { + --i; + (void)i--; + } + private: + Iterator i; + }; + + BOOST_concept(RandomAccessTraversal,(Iterator)) + : BidirectionalTraversal + { + BOOST_CONCEPT_ASSERT(( + boost::Convertible< + BOOST_DEDUCED_TYPENAME RandomAccessTraversal::traversal_category + , boost::random_access_traversal_tag + > )); + + BOOST_CONCEPT_USAGE(RandomAccessTraversal) + { + i += n; + i = i + n; + i = n + i; + i -= n; + i = i - n; + n = i - j; + } + + private: + typename BidirectionalTraversal::difference_type n; + Iterator i, j; + }; + + //=========================================================================== + // Iterator Interoperability + + namespace detail + { + template + void interop_single_pass_constraints(Iterator1 const& i1, Iterator2 const& i2) + { + bool b; + b = i1 == i2; + b = i1 != i2; + + b = i2 == i1; + b = i2 != i1; + boost::ignore_unused_variable_warning(b); + } + + template + void interop_rand_access_constraints( + Iterator1 const& i1, Iterator2 const& i2, + boost::random_access_traversal_tag, boost::random_access_traversal_tag) + { + bool b; + typename std::iterator_traits::difference_type n; + b = i1 < i2; + b = i1 <= i2; + b = i1 > i2; + b = i1 >= i2; + n = i1 - i2; + + b = i2 < i1; + b = i2 <= i1; + b = i2 > i1; + b = i2 >= i1; + n = i2 - i1; + boost::ignore_unused_variable_warning(b); + boost::ignore_unused_variable_warning(n); + } + + template + void interop_rand_access_constraints( + Iterator1 const&, Iterator2 const&, + boost::single_pass_traversal_tag, boost::single_pass_traversal_tag) + { } + + } // namespace detail + + BOOST_concept(InteroperableIterator,(Iterator)(ConstIterator)) + { + private: + typedef typename boost::iterators::pure_iterator_traversal::type traversal_category; + typedef typename boost::iterators::pure_iterator_traversal::type const_traversal_category; + + public: + BOOST_CONCEPT_ASSERT((SinglePassIterator)); + BOOST_CONCEPT_ASSERT((SinglePassIterator)); + + BOOST_CONCEPT_USAGE(InteroperableIterator) + { + detail::interop_single_pass_constraints(i, ci); + detail::interop_rand_access_constraints(i, ci, traversal_category(), const_traversal_category()); + + ci = i; + } + + private: + Iterator i; + ConstIterator ci; + }; + +} // namespace boost_concepts + +#include + +#endif // BOOST_ITERATOR_CONCEPTS_HPP diff --git a/libs/iterator/include/boost/iterator/iterator_facade.hpp b/libs/iterator/include/boost/iterator/iterator_facade.hpp new file mode 100644 index 00000000..c4b5ae4c --- /dev/null +++ b/libs/iterator/include/boost/iterator/iterator_facade.hpp @@ -0,0 +1,1062 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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) +#ifndef BOOST_ITERATOR_FACADE_23022003THW_HPP +#define BOOST_ITERATOR_FACADE_23022003THW_HPP + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include // this goes last + +namespace boost { +namespace iterators { + + // This forward declaration is required for the friend declaration + // in iterator_core_access + template class iterator_facade; + + namespace detail + { + // A binary metafunction class that always returns bool. VC6 + // ICEs on mpl::always, probably because of the default + // parameters. + struct always_bool2 + { + template + struct apply + { + typedef bool type; + }; + }; + + // The type trait checks if the category or traversal is at least as advanced as the specified required traversal + template< typename CategoryOrTraversal, typename Required > + struct is_traversal_at_least : + public boost::is_convertible< typename iterator_category_to_traversal< CategoryOrTraversal >::type, Required > + {}; + + // + // enable if for use in operator implementation. + // + template < + class Facade1 + , class Facade2 + , class Return + > + struct enable_if_interoperable : + public boost::iterators::enable_if< + is_interoperable< Facade1, Facade2 > + , Return + > + {}; + + // + // enable if for use in implementation of operators specific for random access traversal. + // + template < + class Facade1 + , class Facade2 + , class Return + > + struct enable_if_interoperable_and_random_access_traversal : + public boost::iterators::enable_if< + mpl::and_< + is_interoperable< Facade1, Facade2 > + , is_traversal_at_least< typename iterator_category< Facade1 >::type, random_access_traversal_tag > + , is_traversal_at_least< typename iterator_category< Facade2 >::type, random_access_traversal_tag > + > + , Return + > + {}; + + // + // Generates associated types for an iterator_facade with the + // given parameters. + // + template < + class ValueParam + , class CategoryOrTraversal + , class Reference + , class Difference + > + struct iterator_facade_types + { + typedef typename facade_iterator_category< + CategoryOrTraversal, ValueParam, Reference + >::type iterator_category; + + typedef typename remove_const::type value_type; + + // Not the real associated pointer type + typedef typename mpl::eval_if< + boost::iterators::detail::iterator_writability_disabled + , add_pointer + , add_pointer + >::type pointer; + +# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ + && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \ + || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \ + || BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)) \ + || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 310) + + // To interoperate with some broken library/compiler + // combinations, user-defined iterators must be derived from + // std::iterator. It is possible to implement a standard + // library for broken compilers without this limitation. +# define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1 + + typedef + iterator + base; +# endif + }; + + // iterators whose dereference operators reference the same value + // for all iterators into the same sequence (like many input + // iterators) need help with their postfix ++: the referenced + // value must be read and stored away before the increment occurs + // so that *a++ yields the originally referenced element and not + // the next one. + template + class postfix_increment_proxy + { + typedef typename iterator_value::type value_type; + + public: + explicit postfix_increment_proxy(Iterator const& x) + : stored_iterator(x) + , stored_value(*x) + {} + + // Returning a mutable reference allows nonsense like + // (*r++).mutate(), but it imposes fewer assumptions about the + // behavior of the value_type. In particular, recall that + // (*r).mutate() is legal if operator* returns by value. + // Provides readability of *r++ + value_type& operator*() const + { + return stored_value; + } + + // Provides X(r++) + operator Iterator const&() const + { + return stored_iterator; + } + + // Provides (r++)->foo() + value_type* operator->() const + { + return boost::addressof(stored_value); + } + + private: + Iterator stored_iterator; + mutable value_type stored_value; + }; + + + template + class writable_postfix_increment_dereference_proxy; + + template + struct is_not_writable_postfix_increment_dereference_proxy : + public boost::true_type + {}; + + template + struct is_not_writable_postfix_increment_dereference_proxy< + writable_postfix_increment_dereference_proxy + > : + public boost::false_type + {}; + + template + class writable_postfix_increment_proxy; + + // + // In general, we can't determine that such an iterator isn't + // writable -- we also need to store a copy of the old iterator so + // that it can be written into. + template + class writable_postfix_increment_dereference_proxy + { + friend class writable_postfix_increment_proxy; + + typedef typename iterator_value::type value_type; + + public: + explicit writable_postfix_increment_dereference_proxy(Iterator const& x) + : stored_iterator(x) + , stored_value(*x) + {} + + // Provides readability of *r++ + operator value_type&() const + { + return this->stored_value; + } + + template + writable_postfix_increment_dereference_proxy const& + operator=(writable_postfix_increment_dereference_proxy const& x) const + { + typedef typename iterator_value::type other_value_type; + *this->stored_iterator = static_cast(x); + return *this; + } + + // Provides writability of *r++ +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + typename iterators::enable_if< + is_not_writable_postfix_increment_dereference_proxy< T >, + writable_postfix_increment_dereference_proxy const& + >::type operator=(T&& x) const + { + *this->stored_iterator = static_cast< T&& >(x); + return *this; + } +#else + template + typename iterators::enable_if< + is_not_writable_postfix_increment_dereference_proxy< T >, + writable_postfix_increment_dereference_proxy const& + >::type operator=(T const& x) const + { + *this->stored_iterator = x; + return *this; + } + + // This overload just in case only non-const objects are writable + template + typename iterators::enable_if< + is_not_writable_postfix_increment_dereference_proxy< T >, + writable_postfix_increment_dereference_proxy const& + >::type operator=(T& x) const + { + *this->stored_iterator = x; + return *this; + } +#endif + + private: + Iterator stored_iterator; + mutable value_type stored_value; + }; + + template + class writable_postfix_increment_proxy + { + typedef typename iterator_value::type value_type; + + public: + explicit writable_postfix_increment_proxy(Iterator const& x) + : dereference_proxy(x) + {} + + writable_postfix_increment_dereference_proxy const& + operator*() const + { + return dereference_proxy; + } + + // Provides X(r++) + operator Iterator const&() const + { + return dereference_proxy.stored_iterator; + } + + // Provides (r++)->foo() + value_type* operator->() const + { + return boost::addressof(dereference_proxy.stored_value); + } + + private: + writable_postfix_increment_dereference_proxy dereference_proxy; + }; + +# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + template + struct is_non_proxy_reference_impl + { + static Reference r; + + template + static typename mpl::if_< + is_convertible< + R const volatile* + , Value const volatile* + > + , char[1] + , char[2] + >::type& helper(R const&); + + BOOST_STATIC_CONSTANT(bool, value = sizeof(helper(r)) == 1); + }; + + template + struct is_non_proxy_reference + : mpl::bool_< + is_non_proxy_reference_impl::value + > + {}; +# else + template + struct is_non_proxy_reference + : is_convertible< + typename remove_reference::type + const volatile* + , Value const volatile* + > + {}; +# endif + + // A metafunction to choose the result type of postfix ++ + // + // Because the C++98 input iterator requirements say that *r++ has + // type T (value_type), implementations of some standard + // algorithms like lexicographical_compare may use constructions + // like: + // + // *r++ < *s++ + // + // If *r++ returns a proxy (as required if r is writable but not + // multipass), this sort of expression will fail unless the proxy + // supports the operator<. Since there are any number of such + // operations, we're not going to try to support them. Therefore, + // even if r++ returns a proxy, *r++ will only return a proxy if + // *r also returns a proxy. + template + struct postfix_increment_result + : mpl::eval_if< + mpl::and_< + // A proxy is only needed for readable iterators + is_convertible< + Reference + // Use add_lvalue_reference to form `reference to Value` due to + // some (strict) C++03 compilers (e.g. `gcc -std=c++03`) reject + // 'reference-to-reference' in the template which described in CWG + // DR106. + // http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_defects.html#106 + , typename add_lvalue_reference::type + > + + // No multipass iterator can have values that disappear + // before positions can be re-visited + , mpl::not_< + is_convertible< + typename iterator_category_to_traversal::type + , forward_traversal_tag + > + > + > + , mpl::if_< + is_non_proxy_reference + , postfix_increment_proxy + , writable_postfix_increment_proxy + > + , mpl::identity + > + {}; + + // operator->() needs special support for input iterators to strictly meet the + // standard's requirements. If *i is not a reference type, we must still + // produce an lvalue to which a pointer can be formed. We do that by + // returning a proxy object containing an instance of the reference object. + template + struct operator_arrow_dispatch // proxy references + { + struct proxy + { + explicit proxy(Reference const & x) : m_ref(x) {} + Reference* operator->() { return boost::addressof(m_ref); } + // This function is needed for MWCW and BCC, which won't call + // operator-> again automatically per 13.3.1.2 para 8 + operator Reference*() { return boost::addressof(m_ref); } + Reference m_ref; + }; + typedef proxy result_type; + static result_type apply(Reference const & x) + { + return result_type(x); + } + }; + + template + struct operator_arrow_dispatch // "real" references + { + typedef Pointer result_type; + static result_type apply(T& x) + { + return boost::addressof(x); + } + }; + + // A proxy return type for operator[], needed to deal with + // iterators that may invalidate referents upon destruction. + // Consider the temporary iterator in *(a + n) + template + class operator_brackets_proxy + { + // Iterator is actually an iterator_facade, so we do not have to + // go through iterator_traits to access the traits. + typedef typename Iterator::reference reference; + typedef typename Iterator::value_type value_type; + + public: + operator_brackets_proxy(Iterator const& iter) + : m_iter(iter) + {} + + operator reference() const + { + return *m_iter; + } + + operator_brackets_proxy& operator=(value_type const& val) + { + *m_iter = val; + return *this; + } + + private: + Iterator m_iter; + }; + + // A metafunction that determines whether operator[] must return a + // proxy, or whether it can simply return a copy of the value_type. + template + struct use_operator_brackets_proxy + : mpl::not_< + mpl::and_< + // Really we want an is_copy_constructible trait here, + // but is_POD will have to suffice in the meantime. + boost::is_POD + , iterator_writability_disabled + > + > + {}; + + template + struct operator_brackets_result + { + typedef typename mpl::if_< + use_operator_brackets_proxy + , operator_brackets_proxy + , Value + >::type type; + }; + + template + operator_brackets_proxy make_operator_brackets_result(Iterator const& iter, mpl::true_) + { + return operator_brackets_proxy(iter); + } + + template + typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_) + { + return *iter; + } + + struct choose_difference_type + { + template + struct apply + : +# ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP + iterator_difference +# else + mpl::eval_if< + is_convertible + , iterator_difference + , iterator_difference + > +# endif + {}; + + }; + + template < + class Derived + , class Value + , class CategoryOrTraversal + , class Reference + , class Difference + , bool IsBidirectionalTraversal + , bool IsRandomAccessTraversal + > + class iterator_facade_base; + + } // namespace detail + + + // Macros which describe the declarations of binary operators +# ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY +# define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \ + template < \ + class Derived1, class V1, class TC1, class Reference1, class Difference1 \ + , class Derived2, class V2, class TC2, class Reference2, class Difference2 \ + > \ + prefix typename mpl::apply2::type \ + operator op( \ + iterator_facade const& lhs \ + , iterator_facade const& rhs) +# else +# define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \ + template < \ + class Derived1, class V1, class TC1, class Reference1, class Difference1 \ + , class Derived2, class V2, class TC2, class Reference2, class Difference2 \ + > \ + prefix typename enabler< \ + Derived1, Derived2 \ + , typename mpl::apply2::type \ + >::type \ + operator op( \ + iterator_facade const& lhs \ + , iterator_facade const& rhs) +# endif + +# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \ + BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::iterators::detail::enable_if_interoperable) + +# define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(prefix, op, result_type) \ + BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::iterators::detail::enable_if_interoperable_and_random_access_traversal) + +# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \ + template \ + prefix typename boost::iterators::enable_if< \ + boost::iterators::detail::is_traversal_at_least< TC, boost::iterators::random_access_traversal_tag >, \ + Derived \ + >::type operator+ args + + // + // Helper class for granting access to the iterator core interface. + // + // The simple core interface is used by iterator_facade. The core + // interface of a user/library defined iterator type should not be made public + // so that it does not clutter the public interface. Instead iterator_core_access + // should be made friend so that iterator_facade can access the core + // interface through iterator_core_access. + // + class iterator_core_access + { +# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + // Tasteless as this may seem, making all members public allows member templates + // to work in the absence of member template friends. + public: +# else + + template friend class iterator_facade; + template + friend class detail::iterator_facade_base; + +# define BOOST_ITERATOR_FACADE_RELATION(op) \ + BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, boost::iterators::detail::always_bool2); + + BOOST_ITERATOR_FACADE_RELATION(==) + BOOST_ITERATOR_FACADE_RELATION(!=) + +# undef BOOST_ITERATOR_FACADE_RELATION + +# define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op) \ + BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(friend,op, boost::iterators::detail::always_bool2); + + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<) + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>) + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=) + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=) + +# undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION + + BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD( + friend, -, boost::iterators::detail::choose_difference_type) + ; + + BOOST_ITERATOR_FACADE_PLUS_HEAD( + friend inline + , (iterator_facade const& + , typename Derived::difference_type) + ) + ; + + BOOST_ITERATOR_FACADE_PLUS_HEAD( + friend inline + , (typename Derived::difference_type + , iterator_facade const&) + ) + ; + +# endif + + template + static typename Facade::reference dereference(Facade const& f) + { + return f.dereference(); + } + + template + static void increment(Facade& f) + { + f.increment(); + } + + template + static void decrement(Facade& f) + { + f.decrement(); + } + + template + static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::true_) + { + return f1.equal(f2); + } + + template + static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::false_) + { + return f2.equal(f1); + } + + template + static void advance(Facade& f, typename Facade::difference_type n) + { + f.advance(n); + } + + template + static typename Facade1::difference_type distance_from( + Facade1 const& f1, Facade2 const& f2, mpl::true_) + { + return -f1.distance_to(f2); + } + + template + static typename Facade2::difference_type distance_from( + Facade1 const& f1, Facade2 const& f2, mpl::false_) + { + return f2.distance_to(f1); + } + + // + // Curiously Recurring Template interface. + // + template + static I& derived(iterator_facade& facade) + { + return *static_cast(&facade); + } + + template + static I const& derived(iterator_facade const& facade) + { + return *static_cast(&facade); + } + + // objects of this class are useless + BOOST_DELETED_FUNCTION(iterator_core_access()) + }; + + namespace detail { + + // Implementation for forward traversal iterators + template < + class Derived + , class Value + , class CategoryOrTraversal + , class Reference + , class Difference + > + class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false > +# ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE + : public boost::iterators::detail::iterator_facade_types< + Value, CategoryOrTraversal, Reference, Difference + >::base +# undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE +# endif + { + private: + typedef boost::iterators::detail::iterator_facade_types< + Value, CategoryOrTraversal, Reference, Difference + > associated_types; + + typedef boost::iterators::detail::operator_arrow_dispatch< + Reference + , typename associated_types::pointer + > operator_arrow_dispatch_; + + public: + typedef typename associated_types::value_type value_type; + typedef Reference reference; + typedef Difference difference_type; + + typedef typename operator_arrow_dispatch_::result_type pointer; + + typedef typename associated_types::iterator_category iterator_category; + + public: + reference operator*() const + { + return iterator_core_access::dereference(this->derived()); + } + + pointer operator->() const + { + return operator_arrow_dispatch_::apply(*this->derived()); + } + + Derived& operator++() + { + iterator_core_access::increment(this->derived()); + return this->derived(); + } + + protected: + // + // Curiously Recurring Template interface. + // + Derived& derived() + { + return *static_cast(this); + } + + Derived const& derived() const + { + return *static_cast(this); + } + }; + + // Implementation for bidirectional traversal iterators + template < + class Derived + , class Value + , class CategoryOrTraversal + , class Reference + , class Difference + > + class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > : + public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false > + { + public: + Derived& operator--() + { + iterator_core_access::decrement(this->derived()); + return this->derived(); + } + + Derived operator--(int) + { + Derived tmp(this->derived()); + --*this; + return tmp; + } + }; + + // Implementation for random access traversal iterators + template < + class Derived + , class Value + , class CategoryOrTraversal + , class Reference + , class Difference + > + class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, true > : + public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > + { + private: + typedef iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > base_type; + + public: + typedef typename base_type::reference reference; + typedef typename base_type::difference_type difference_type; + + public: + typename boost::iterators::detail::operator_brackets_result::type + operator[](difference_type n) const + { + typedef boost::iterators::detail::use_operator_brackets_proxy use_proxy; + + return boost::iterators::detail::make_operator_brackets_result( + this->derived() + n + , use_proxy() + ); + } + + Derived& operator+=(difference_type n) + { + iterator_core_access::advance(this->derived(), n); + return this->derived(); + } + + Derived& operator-=(difference_type n) + { + iterator_core_access::advance(this->derived(), -n); + return this->derived(); + } + + Derived operator-(difference_type x) const + { + Derived result(this->derived()); + return result -= x; + } + }; + + } // namespace detail + + // + // iterator_facade - use as a public base class for defining new + // standard-conforming iterators. + // + template < + class Derived // The derived iterator type being constructed + , class Value + , class CategoryOrTraversal + , class Reference = Value& + , class Difference = std::ptrdiff_t + > + class iterator_facade : + public detail::iterator_facade_base< + Derived, + Value, + CategoryOrTraversal, + Reference, + Difference, + detail::is_traversal_at_least< CategoryOrTraversal, bidirectional_traversal_tag >::value, + detail::is_traversal_at_least< CategoryOrTraversal, random_access_traversal_tag >::value + > + { + protected: + // For use by derived classes + typedef iterator_facade iterator_facade_; + }; + + template + inline typename boost::iterators::detail::postfix_increment_result::type + operator++( + iterator_facade& i + , int + ) + { + typename boost::iterators::detail::postfix_increment_result::type + tmp(*static_cast(&i)); + + ++i; + + return tmp; + } + + + // + // Comparison operator implementation. The library supplied operators + // enables the user to provide fully interoperable constant/mutable + // iterator types. I.e. the library provides all operators + // for all mutable/constant iterator combinations. + // + // Note though that this kind of interoperability for constant/mutable + // iterators is not required by the standard for container iterators. + // All the standard asks for is a conversion mutable -> constant. + // Most standard library implementations nowadays provide fully interoperable + // iterator implementations, but there are still heavily used implementations + // that do not provide them. (Actually it's even worse, they do not provide + // them for only a few iterators.) + // + // ?? Maybe a BOOST_ITERATOR_NO_FULL_INTEROPERABILITY macro should + // enable the user to turn off mixed type operators + // + // The library takes care to provide only the right operator overloads. + // I.e. + // + // bool operator==(Iterator, Iterator); + // bool operator==(ConstIterator, Iterator); + // bool operator==(Iterator, ConstIterator); + // bool operator==(ConstIterator, ConstIterator); + // + // ... + // + // In order to do so it uses c++ idioms that are not yet widely supported + // by current compiler releases. The library is designed to degrade gracefully + // in the face of compiler deficiencies. In general compiler + // deficiencies result in less strict error checking and more obscure + // error messages, functionality is not affected. + // + // For full operation compiler support for "Substitution Failure Is Not An Error" + // (aka. enable_if) and boost::is_convertible is required. + // + // The following problems occur if support is lacking. + // + // Pseudo code + // + // --------------- + // AdaptorA a1; + // AdaptorA a2; + // + // // This will result in a no such overload error in full operation + // // If enable_if or is_convertible is not supported + // // The instantiation will fail with an error hopefully indicating that + // // there is no operator== for Iterator1, Iterator2 + // // The same will happen if no enable_if is used to remove + // // false overloads from the templated conversion constructor + // // of AdaptorA. + // + // a1 == a2; + // ---------------- + // + // AdaptorA a; + // AdaptorB b; + // + // // This will result in a no such overload error in full operation + // // If enable_if is not supported the static assert used + // // in the operator implementation will fail. + // // This will accidently work if is_convertible is not supported. + // + // a == b; + // ---------------- + // + +# ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP +# define BOOST_ITERATOR_CONVERTIBLE(a,b) mpl::true_() +# else +# define BOOST_ITERATOR_CONVERTIBLE(a,b) is_convertible() +# endif + +# define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, return_prefix, base_op) \ + BOOST_ITERATOR_FACADE_INTEROP_HEAD(inline, op, result_type) \ + { \ + /* For those compilers that do not support enable_if */ \ + BOOST_STATIC_ASSERT(( \ + is_interoperable< Derived1, Derived2 >::value \ + )); \ + return_prefix iterator_core_access::base_op( \ + *static_cast(&lhs) \ + , *static_cast(&rhs) \ + , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \ + ); \ + } + +# define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \ + BOOST_ITERATOR_FACADE_INTEROP( \ + op \ + , boost::iterators::detail::always_bool2 \ + , return_prefix \ + , base_op \ + ) + + BOOST_ITERATOR_FACADE_RELATION(==, return, equal) + BOOST_ITERATOR_FACADE_RELATION(!=, return !, equal) + +# undef BOOST_ITERATOR_FACADE_RELATION + + +# define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS(op, result_type, return_prefix, base_op) \ + BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(inline, op, result_type) \ + { \ + /* For those compilers that do not support enable_if */ \ + BOOST_STATIC_ASSERT(( \ + is_interoperable< Derived1, Derived2 >::value && \ + boost::iterators::detail::is_traversal_at_least< typename iterator_category< Derived1 >::type, random_access_traversal_tag >::value && \ + boost::iterators::detail::is_traversal_at_least< typename iterator_category< Derived2 >::type, random_access_traversal_tag >::value \ + )); \ + return_prefix iterator_core_access::base_op( \ + *static_cast(&lhs) \ + , *static_cast(&rhs) \ + , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \ + ); \ + } + +# define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op, return_prefix, base_op) \ + BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS( \ + op \ + , boost::iterators::detail::always_bool2 \ + , return_prefix \ + , base_op \ + ) + + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<, return 0 >, distance_from) + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>, return 0 <, distance_from) + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=, return 0 >=, distance_from) + BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=, return 0 <=, distance_from) + +# undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION + + // operator- requires an additional part in the static assertion + BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS( + - + , boost::iterators::detail::choose_difference_type + , return + , distance_from + ) + +# undef BOOST_ITERATOR_FACADE_INTEROP +# undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS + +# define BOOST_ITERATOR_FACADE_PLUS(args) \ + BOOST_ITERATOR_FACADE_PLUS_HEAD(inline, args) \ + { \ + Derived tmp(static_cast(i)); \ + return tmp += n; \ + } + + BOOST_ITERATOR_FACADE_PLUS(( + iterator_facade const& i + , typename Derived::difference_type n + )) + + BOOST_ITERATOR_FACADE_PLUS(( + typename Derived::difference_type n + , iterator_facade const& i + )) + +# undef BOOST_ITERATOR_FACADE_PLUS +# undef BOOST_ITERATOR_FACADE_PLUS_HEAD + +# undef BOOST_ITERATOR_FACADE_INTEROP_HEAD +# undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD +# undef BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL + +} // namespace iterators + +using iterators::iterator_core_access; +using iterators::iterator_facade; + +} // namespace boost + +#include + +#endif // BOOST_ITERATOR_FACADE_23022003THW_HPP diff --git a/libs/iterator/include/boost/iterator/iterator_traits.hpp b/libs/iterator/include/boost/iterator/iterator_traits.hpp new file mode 100644 index 00000000..6582a68f --- /dev/null +++ b/libs/iterator/include/boost/iterator/iterator_traits.hpp @@ -0,0 +1,61 @@ +// Copyright David Abrahams 2003. +// 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) +#ifndef ITERATOR_TRAITS_DWA200347_HPP +# define ITERATOR_TRAITS_DWA200347_HPP + +# include + +#include + +namespace boost { +namespace iterators { + +// Macro for supporting old compilers, no longer needed but kept +// for backwards compatibility (it was documented). +#define BOOST_ITERATOR_CATEGORY iterator_category + + +template +struct iterator_value +{ + typedef typename std::iterator_traits::value_type type; +}; + +template +struct iterator_reference +{ + typedef typename std::iterator_traits::reference type; +}; + + +template +struct iterator_pointer +{ + typedef typename std::iterator_traits::pointer type; +}; + +template +struct iterator_difference +{ + typedef typename std::iterator_traits::difference_type type; +}; + +template +struct iterator_category +{ + typedef typename std::iterator_traits::iterator_category type; +}; + +} // namespace iterators + +using iterators::iterator_value; +using iterators::iterator_reference; +using iterators::iterator_pointer; +using iterators::iterator_difference; +using iterators::iterator_category; + +} // namespace boost + +#endif // ITERATOR_TRAITS_DWA200347_HPP diff --git a/libs/iterator/include/boost/iterator/minimum_category.hpp b/libs/iterator/include/boost/iterator/minimum_category.hpp new file mode 100644 index 00000000..15679bc7 --- /dev/null +++ b/libs/iterator/include/boost/iterator/minimum_category.hpp @@ -0,0 +1,95 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to 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) +#ifndef BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ +# define BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ + +# include +# include +# include + +# include +# include + +namespace boost { +namespace iterators { +namespace detail { + +template +struct minimum_category_impl; + +template +struct error_not_related_by_convertibility; + +template <> +struct minimum_category_impl +{ + template struct apply + { + typedef T2 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + { + typedef T1 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + { + BOOST_STATIC_ASSERT((is_same::value)); + typedef T1 type; + }; +}; + +template <> +struct minimum_category_impl +{ + template struct apply + : error_not_related_by_convertibility + { + }; +}; + +} // namespace detail + +// +// Returns the minimum category type or fails to compile +// if T1 and T2 are unrelated. +// +template +struct minimum_category +{ + typedef boost::iterators::detail::minimum_category_impl< + ::boost::is_convertible::value + , ::boost::is_convertible::value + > outer; + + typedef typename outer::template apply inner; + typedef typename inner::type type; + + BOOST_MPL_AUX_LAMBDA_SUPPORT(2,minimum_category,(T1,T2)) +}; + +template <> +struct minimum_category +{ + template + struct apply : minimum_category + {}; + + BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(2,minimum_category,(mpl::_1,mpl::_2)) +}; + +} // namespace iterators + +} // namespace boost + +#endif // BOOST_ITERATOR_MINIMUM_CATEGORY_HPP_INCLUDED_ diff --git a/libs/iterator/include/boost/iterator/new_iterator_tests.hpp b/libs/iterator/include/boost/iterator/new_iterator_tests.hpp new file mode 100644 index 00000000..2091e597 --- /dev/null +++ b/libs/iterator/include/boost/iterator/new_iterator_tests.hpp @@ -0,0 +1,265 @@ +#ifndef BOOST_NEW_ITERATOR_TESTS_HPP +# define BOOST_NEW_ITERATOR_TESTS_HPP + +// +// Copyright (c) David Abrahams 2001. +// Copyright (c) Jeremy Siek 2001-2003. +// Copyright (c) Thomas Witt 2002. +// +// Use, modification and distribution is subject to 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) +// + +// This is meant to be the beginnings of a comprehensive, generic +// test suite for STL concepts such as iterators and containers. +// +// Revision History: +// 28 Oct 2002 Started update for new iterator categories +// (Jeremy Siek) +// 28 Apr 2002 Fixed input iterator requirements. +// For a == b a++ == b++ is no longer required. +// See 24.1.1/3 for details. +// (Thomas Witt) +// 08 Feb 2001 Fixed bidirectional iterator test so that +// --i is no longer a precondition. +// (Jeremy Siek) +// 04 Feb 2001 Added lvalue test, corrected preconditions +// (David Abrahams) + +# include +# include +# include // for detail::dummy_constructor +# include +# include +# include +# include +# include +# include + +# include +# include +# include + +namespace boost { + + +// Do separate tests for *i++ so we can treat, e.g., smart pointers, +// as readable and/or writable iterators. +template +void readable_iterator_traversal_test(Iterator i1, T v, mpl::true_) +{ + T v2(*i1++); + BOOST_TEST(v == v2); +} + +template +void readable_iterator_traversal_test(const Iterator i1, T v, mpl::false_) +{} + +template +void writable_iterator_traversal_test(Iterator i1, T v, mpl::true_) +{ + ++i1; // we just wrote into that position + *i1++ = v; + Iterator x(i1++); + (void)x; +} + +template +void writable_iterator_traversal_test(const Iterator i1, T v, mpl::false_) +{} + + +// Preconditions: *i == v +template +void readable_iterator_test(const Iterator i1, T v) +{ + Iterator i2(i1); // Copy Constructible + typedef typename std::iterator_traits::reference ref_t; + ref_t r1 = *i1; + ref_t r2 = *i2; + T v1 = r1; + T v2 = r2; + BOOST_TEST(v1 == v); + BOOST_TEST(v2 == v); + +# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + readable_iterator_traversal_test(i1, v, detail::is_postfix_incrementable()); + + // I think we don't really need this as it checks the same things as + // the above code. + BOOST_STATIC_ASSERT(is_readable_iterator::value); +# endif +} + +template +void writable_iterator_test(Iterator i, T v, T v2) +{ + Iterator i2(i); // Copy Constructible + *i2 = v; + +# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + writable_iterator_traversal_test( + i, v2, mpl::and_< + detail::is_incrementable + , detail::is_postfix_incrementable + >()); +# endif +} + +template +void swappable_iterator_test(Iterator i, Iterator j) +{ + Iterator i2(i), j2(j); + typename std::iterator_traits::value_type bi = *i, bj = *j; + iter_swap(i2, j2); + typename std::iterator_traits::value_type ai = *i, aj = *j; + BOOST_TEST(bi == aj && bj == ai); +} + +template +void constant_lvalue_iterator_test(Iterator i, T v1) +{ + Iterator i2(i); + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::reference reference; + BOOST_STATIC_ASSERT((is_same::value)); + const T& v2 = *i2; + BOOST_TEST(v1 == v2); +# ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!is_non_const_lvalue_iterator::value); +# endif +} + +template +void non_const_lvalue_iterator_test(Iterator i, T v1, T v2) +{ + Iterator i2(i); + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::reference reference; + BOOST_STATIC_ASSERT((is_same::value)); + T& v3 = *i2; + BOOST_TEST(v1 == v3); + + // A non-const lvalue iterator is not neccessarily writable, but we + // are assuming the value_type is assignable here + *i = v2; + + T& v4 = *i2; + BOOST_TEST(v2 == v4); +# ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(is_non_const_lvalue_iterator::value); +# endif +} + +template +void forward_readable_iterator_test(Iterator i, Iterator j, T val1, T val2) +{ + Iterator i2; + Iterator i3(i); + i2 = i; + BOOST_TEST(i2 == i3); + BOOST_TEST(i != j); + BOOST_TEST(i2 != j); + readable_iterator_test(i, val1); + readable_iterator_test(i2, val1); + readable_iterator_test(i3, val1); + + BOOST_TEST(i == i2++); + BOOST_TEST(i != ++i3); + + readable_iterator_test(i2, val2); + readable_iterator_test(i3, val2); + + readable_iterator_test(i, val1); +} + +template +void forward_swappable_iterator_test(Iterator i, Iterator j, T val1, T val2) +{ + forward_readable_iterator_test(i, j, val1, val2); + Iterator i2 = i; + ++i2; + swappable_iterator_test(i, i2); +} + +// bidirectional +// Preconditions: *i == v1, *++i == v2 +template +void bidirectional_readable_iterator_test(Iterator i, T v1, T v2) +{ + Iterator j(i); + ++j; + forward_readable_iterator_test(i, j, v1, v2); + ++i; + + Iterator i1 = i, i2 = i; + + BOOST_TEST(i == i1--); + BOOST_TEST(i != --i2); + + readable_iterator_test(i, v2); + readable_iterator_test(i1, v1); + readable_iterator_test(i2, v1); + + --i; + BOOST_TEST(i == i1); + BOOST_TEST(i == i2); + ++i1; + ++i2; + + readable_iterator_test(i, v1); + readable_iterator_test(i1, v2); + readable_iterator_test(i2, v2); +} + +// random access +// Preconditions: [i,i+N) is a valid range +template +void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals) +{ + bidirectional_readable_iterator_test(i, vals[0], vals[1]); + const Iterator j = i; + int c; + + for (c = 0; c < N-1; ++c) + { + BOOST_TEST(i == j + c); + BOOST_TEST(*i == vals[c]); + typename std::iterator_traits::value_type x = j[c]; + BOOST_TEST(*i == x); + BOOST_TEST(*i == *(j + c)); + BOOST_TEST(*i == *(c + j)); + ++i; + BOOST_TEST(i > j); + BOOST_TEST(i >= j); + BOOST_TEST(j <= i); + BOOST_TEST(j < i); + } + + Iterator k = j + N - 1; + for (c = 0; c < N-1; ++c) + { + BOOST_TEST(i == k - c); + BOOST_TEST(*i == vals[N - 1 - c]); + typename std::iterator_traits::value_type x = j[N - 1 - c]; + BOOST_TEST(*i == x); + Iterator q = k - c; + BOOST_TEST(*i == *q); + BOOST_TEST(i > j); + BOOST_TEST(i >= j); + BOOST_TEST(j <= i); + BOOST_TEST(j < i); + --i; + } +} + +} // namespace boost + +# include + +#endif // BOOST_NEW_ITERATOR_TESTS_HPP diff --git a/libs/iterator/include/boost/iterator/permutation_iterator.hpp b/libs/iterator/include/boost/iterator/permutation_iterator.hpp new file mode 100644 index 00000000..3876f3d9 --- /dev/null +++ b/libs/iterator/include/boost/iterator/permutation_iterator.hpp @@ -0,0 +1,76 @@ +// (C) Copyright Toon Knapen 2001. +// (C) Copyright David Abrahams 2003. +// (C) Copyright Roland Richter 2003. +// 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) + +#ifndef BOOST_PERMUTATION_ITERATOR_HPP +#define BOOST_PERMUTATION_ITERATOR_HPP + +#include + +#include + + +namespace boost { +namespace iterators { + +template< class ElementIterator + , class IndexIterator> +class permutation_iterator + : public iterator_adaptor< + permutation_iterator + , IndexIterator, typename std::iterator_traits::value_type + , use_default, typename std::iterator_traits::reference> +{ + typedef iterator_adaptor< + permutation_iterator + , IndexIterator, typename std::iterator_traits::value_type + , use_default, typename std::iterator_traits::reference> super_t; + + friend class iterator_core_access; + +public: + permutation_iterator() : m_elt_iter() {} + + explicit permutation_iterator(ElementIterator x, IndexIterator y) + : super_t(y), m_elt_iter(x) {} + + template + permutation_iterator( + permutation_iterator const& r + , typename enable_if_convertible::type* = 0 + , typename enable_if_convertible::type* = 0 + ) + : super_t(r.base()), m_elt_iter(r.m_elt_iter) + {} + +private: + typename super_t::reference dereference() const + { return *(m_elt_iter + *this->base()); } + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + template friend class permutation_iterator; +#else + public: +#endif + ElementIterator m_elt_iter; +}; + + +template +inline permutation_iterator +make_permutation_iterator( ElementIterator e, IndexIterator i ) +{ + return permutation_iterator( e, i ); +} + +} // namespace iterators + +using iterators::permutation_iterator; +using iterators::make_permutation_iterator; + +} // namespace boost + +#endif diff --git a/libs/iterator/include/boost/iterator/reverse_iterator.hpp b/libs/iterator/include/boost/iterator/reverse_iterator.hpp new file mode 100644 index 00000000..03b7925c --- /dev/null +++ b/libs/iterator/include/boost/iterator/reverse_iterator.hpp @@ -0,0 +1,77 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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) +#ifndef BOOST_REVERSE_ITERATOR_23022003THW_HPP +#define BOOST_REVERSE_ITERATOR_23022003THW_HPP + +#include + +namespace boost { +namespace iterators { + + // + // + // + template + class reverse_iterator + : public iterator_adaptor< reverse_iterator, Iterator > + { + typedef iterator_adaptor< reverse_iterator, Iterator > super_t; + + friend class iterator_core_access; + + public: + reverse_iterator() {} + + explicit reverse_iterator(Iterator x) + : super_t(x) {} + + template + reverse_iterator( + reverse_iterator const& r + , typename enable_if_convertible::type* = 0 + ) + : super_t(r.base()) + {} + + private: + typename super_t::reference dereference() const + { + Iterator it = this->base_reference(); + --it; + return *it; + } + + void increment() { --this->base_reference(); } + void decrement() { ++this->base_reference(); } + + void advance(typename super_t::difference_type n) + { + this->base_reference() -= n; + } + + template + typename super_t::difference_type + distance_to(reverse_iterator const& y) const + { + return this->base_reference() - y.base(); + } + }; + + template + inline reverse_iterator make_reverse_iterator(BidirectionalIterator x) + { + return reverse_iterator(x); + } + +} // namespace iterators + +using iterators::reverse_iterator; +using iterators::make_reverse_iterator; + +} // namespace boost + +#endif // BOOST_REVERSE_ITERATOR_23022003THW_HPP diff --git a/libs/iterator/include/boost/iterator/transform_iterator.hpp b/libs/iterator/include/boost/iterator/transform_iterator.hpp new file mode 100644 index 00000000..5b2b810e --- /dev/null +++ b/libs/iterator/include/boost/iterator/transform_iterator.hpp @@ -0,0 +1,179 @@ +// (C) Copyright David Abrahams 2002. +// (C) Copyright Jeremy Siek 2002. +// (C) Copyright Thomas Witt 2002. +// 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) +#ifndef BOOST_TRANSFORM_ITERATOR_23022003THW_HPP +#define BOOST_TRANSFORM_ITERATOR_23022003THW_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310)) +#include +#endif + +#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) +#include +#endif + +#include + + +namespace boost { +namespace iterators { + + template + class transform_iterator; + + namespace detail + { + // Compute the iterator_adaptor instantiation to be used for transform_iterator + template + struct transform_iterator_base + { + private: + // By default, dereferencing the iterator yields the same as + // the function. + typedef typename ia_dflt_help< + Reference +#ifdef BOOST_RESULT_OF_USE_TR1 + , result_of::reference)> +#else + , result_of::reference)> +#endif + >::type reference; + + // To get the default for Value: remove any reference on the + // result type, but retain any constness to signal + // non-writability. Note that if we adopt Thomas' suggestion + // to key non-writability *only* on the Reference argument, + // we'd need to strip constness here as well. + typedef typename ia_dflt_help< + Value + , remove_reference + >::type cv_value_type; + + public: + typedef iterator_adaptor< + transform_iterator + , Iterator + , cv_value_type + , use_default // Leave the traversal category alone + , reference + > type; + }; + } + + template + class transform_iterator + : public boost::iterators::detail::transform_iterator_base::type + { + typedef typename + boost::iterators::detail::transform_iterator_base::type + super_t; + + friend class iterator_core_access; + + public: + transform_iterator() { } + + transform_iterator(Iterator const& x, UnaryFunc f) + : super_t(x), m_f(f) { } + + explicit transform_iterator(Iterator const& x) + : super_t(x) + { + // Pro8 is a little too aggressive about instantiating the + // body of this function. +#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + // don't provide this constructor if UnaryFunc is a + // function pointer type, since it will be 0. Too dangerous. + BOOST_STATIC_ASSERT(is_class::value); +#endif + } + + template < + class OtherUnaryFunction + , class OtherIterator + , class OtherReference + , class OtherValue> + transform_iterator( + transform_iterator const& t + , typename enable_if_convertible::type* = 0 +#if !BOOST_WORKAROUND(BOOST_MSVC, == 1310) + , typename enable_if_convertible::type* = 0 +#endif + ) + : super_t(t.base()), m_f(t.functor()) + {} + + UnaryFunc functor() const + { return m_f; } + + private: + typename super_t::reference dereference() const + { return m_f(*this->base()); } + + // Probably should be the initial base class so it can be + // optimized away via EBO if it is an empty class. + UnaryFunc m_f; + }; + + template + inline transform_iterator + make_transform_iterator(Iterator it, UnaryFunc fun) + { + return transform_iterator(it, fun); + } + + // Version which allows explicit specification of the UnaryFunc + // type. + // + // This generator is not provided if UnaryFunc is a function + // pointer type, because it's too dangerous: the default-constructed + // function pointer in the iterator be 0, leading to a runtime + // crash. + template + inline typename iterators::enable_if< + is_class // We should probably find a cheaper test than is_class<> + , transform_iterator + >::type + make_transform_iterator(Iterator it) + { + return transform_iterator(it, UnaryFunc()); + } + +#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + template + inline transform_iterator< Return (*)(Argument), Iterator, Return> + make_transform_iterator(Iterator it, Return (*fun)(Argument)) + { + return transform_iterator(it, fun); + } +#endif + +} // namespace iterators + +using iterators::transform_iterator; +using iterators::make_transform_iterator; + +} // namespace boost + +#include + +#endif // BOOST_TRANSFORM_ITERATOR_23022003THW_HPP diff --git a/libs/iterator/include/boost/iterator/zip_iterator.hpp b/libs/iterator/include/boost/iterator/zip_iterator.hpp new file mode 100644 index 00000000..f5780aeb --- /dev/null +++ b/libs/iterator/include/boost/iterator/zip_iterator.hpp @@ -0,0 +1,367 @@ +// Copyright David Abrahams and Thomas Becker 2000-2006. +// Copyright Kohei Takahashi 2012-2014. +// +// 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) + +#ifndef BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_ +# define BOOST_ZIP_ITERATOR_TMB_07_13_2003_HPP_ + +#include +#include +#include +#include // for enable_if_convertible +#include + +#include + +#include // for std::pair +#include // for backward compatibility + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace iterators { + + // Zip iterator forward declaration for zip_iterator_base + template + class zip_iterator; + + namespace detail + { + + // Functors to be used with tuple algorithms + // + template + class advance_iterator + { + public: + advance_iterator(DiffType step) : m_step(step) {} + + template + void operator()(Iterator& it) const + { it += m_step; } + + private: + DiffType m_step; + }; + // + struct increment_iterator + { + template + void operator()(Iterator& it) const + { ++it; } + }; + // + struct decrement_iterator + { + template + void operator()(Iterator& it) const + { --it; } + }; + // + struct dereference_iterator + { + template + struct result; + + template + struct result + { + typedef typename + remove_cv::type>::type + iterator; + + typedef typename iterator_reference::type type; + }; + + template + typename result::type + operator()(Iterator const& it) const + { return *it; } + }; + + // Metafunction to obtain the type of the tuple whose element types + // are the reference types of an iterator tuple. + // + template + struct tuple_of_references + : mpl::transform< + IteratorTuple, + iterator_reference + > + { + }; + + // Specialization for std::pair + template + struct tuple_of_references > + { + typedef std::pair< + typename iterator_reference::type + , typename iterator_reference::type + > type; + }; + + // Metafunction to obtain the minimal traversal tag in a tuple + // of iterators. + // + template + struct minimum_traversal_category_in_iterator_tuple + { + typedef typename mpl::transform< + IteratorTuple + , pure_traversal_tag > + >::type tuple_of_traversal_tags; + + typedef typename mpl::fold< + tuple_of_traversal_tags + , random_access_traversal_tag + , minimum_category<> + >::type type; + }; + + template + struct minimum_traversal_category_in_iterator_tuple > + { + typedef typename pure_traversal_tag< + typename iterator_traversal::type + >::type iterator1_traversal; + typedef typename pure_traversal_tag< + typename iterator_traversal::type + >::type iterator2_traversal; + + typedef typename minimum_category< + iterator1_traversal + , typename minimum_category< + iterator2_traversal + , random_access_traversal_tag + >::type + >::type type; + }; + + /////////////////////////////////////////////////////////////////// + // + // Class zip_iterator_base + // + // Builds and exposes the iterator facade type from which the zip + // iterator will be derived. + // + template + struct zip_iterator_base + { + private: + // Reference type is the type of the tuple obtained from the + // iterators' reference types. + typedef typename + detail::tuple_of_references::type reference; + + // Value type is the same as reference type. + typedef reference value_type; + + // Difference type is the first iterator's difference type + typedef typename iterator_difference< + typename mpl::at_c::type + >::type difference_type; + + // Traversal catetgory is the minimum traversal category in the + // iterator tuple. + typedef typename + detail::minimum_traversal_category_in_iterator_tuple< + IteratorTuple + >::type traversal_category; + public: + + // The iterator facade type from which the zip iterator will + // be derived. + typedef iterator_facade< + zip_iterator, + value_type, + traversal_category, + reference, + difference_type + > type; + }; + + template <> + struct zip_iterator_base + { + typedef int type; + }; + + template + struct converter + { + template + static reference call(Seq seq) + { + typedef typename fusion::traits::tag_of::type tag; + return fusion::convert(seq); + } + }; + + template + struct converter > + { + typedef std::pair reference; + template + static reference call(Seq seq) + { + return reference( + fusion::at_c<0>(seq) + , fusion::at_c<1>(seq)); + } + }; + } + + ///////////////////////////////////////////////////////////////////// + // + // zip_iterator class definition + // + template + class zip_iterator : + public detail::zip_iterator_base::type + { + + // Typedef super_t as our base class. + typedef typename + detail::zip_iterator_base::type super_t; + + // iterator_core_access is the iterator's best friend. + friend class iterator_core_access; + + public: + + // Construction + // ============ + + // Default constructor + zip_iterator() { } + + // Constructor from iterator tuple + zip_iterator(IteratorTuple iterator_tuple) + : m_iterator_tuple(iterator_tuple) + { } + + // Copy constructor + template + zip_iterator( + const zip_iterator& other, + typename enable_if_convertible< + OtherIteratorTuple, + IteratorTuple + >::type* = 0 + ) : m_iterator_tuple(other.get_iterator_tuple()) + {} + + // Get method for the iterator tuple. + const IteratorTuple& get_iterator_tuple() const + { return m_iterator_tuple; } + + private: + + // Implementation of Iterator Operations + // ===================================== + + // Dereferencing returns a tuple built from the dereferenced + // iterators in the iterator tuple. + typename super_t::reference dereference() const + { + typedef typename super_t::reference reference; + typedef detail::converter gen; + return gen::call(fusion::transform( + get_iterator_tuple(), + detail::dereference_iterator())); + } + + // Two zip iterators are equal if all iterators in the iterator + // tuple are equal. NOTE: It should be possible to implement this + // as + // + // return get_iterator_tuple() == other.get_iterator_tuple(); + // + // but equality of tuples currently (7/2003) does not compile + // under several compilers. No point in bringing in a bunch + // of #ifdefs here. + // + template + bool equal(const zip_iterator& other) const + { + return fusion::equal_to( + get_iterator_tuple(), + other.get_iterator_tuple()); + } + + // Advancing a zip iterator means to advance all iterators in the + // iterator tuple. + void advance(typename super_t::difference_type n) + { + fusion::for_each( + m_iterator_tuple, + detail::advance_iterator(n)); + } + // Incrementing a zip iterator means to increment all iterators in + // the iterator tuple. + void increment() + { + fusion::for_each( + m_iterator_tuple, + detail::increment_iterator()); + } + + // Decrementing a zip iterator means to decrement all iterators in + // the iterator tuple. + void decrement() + { + fusion::for_each( + m_iterator_tuple, + detail::decrement_iterator()); + } + + // Distance is calculated using the first iterator in the tuple. + template + typename super_t::difference_type distance_to( + const zip_iterator& other + ) const + { + return fusion::at_c<0>(other.get_iterator_tuple()) - + fusion::at_c<0>(this->get_iterator_tuple()); + } + + // Data Members + // ============ + + // The iterator tuple. + IteratorTuple m_iterator_tuple; + + }; + + // Make function for zip iterator + // + template + inline zip_iterator + make_zip_iterator(IteratorTuple t) + { return zip_iterator(t); } + +} // namespace iterators + +using iterators::zip_iterator; +using iterators::make_zip_iterator; + +} // namespace boost + +#endif diff --git a/libs/iterator/include/boost/iterator_adaptors.hpp b/libs/iterator/include/boost/iterator_adaptors.hpp new file mode 100644 index 00000000..ed9579c5 --- /dev/null +++ b/libs/iterator/include/boost/iterator_adaptors.hpp @@ -0,0 +1,13 @@ +// Copyright David Abrahams 2004. 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) + +// See www.boost.org/libs/iterator for documentation. + +#ifndef ITERATOR_ADAPTORS_DWA2004725_HPP +# define ITERATOR_ADAPTORS_DWA2004725_HPP + +#define BOOST_ITERATOR_ADAPTORS_VERSION 0x0200 +#include + +#endif // ITERATOR_ADAPTORS_DWA2004725_HPP diff --git a/libs/iterator/include/boost/next_prior.hpp b/libs/iterator/include/boost/next_prior.hpp new file mode 100644 index 00000000..d943b97f --- /dev/null +++ b/libs/iterator/include/boost/next_prior.hpp @@ -0,0 +1,154 @@ +// Boost next_prior.hpp header file ---------------------------------------// + +// (C) Copyright Dave Abrahams and Daniel Walker 1999-2003. +// Copyright (c) Andrey Semashev 2017 +// +// 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) + +// See http://www.boost.org/libs/utility for documentation. + +// Revision History +// 13 Dec 2003 Added next(x, n) and prior(x, n) (Daniel Walker) + +#ifndef BOOST_NEXT_PRIOR_HPP_INCLUDED +#define BOOST_NEXT_PRIOR_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + +// Helper functions for classes like bidirectional iterators not supporting +// operator+ and operator- +// +// Usage: +// const std::list::iterator p = get_some_iterator(); +// const std::list::iterator prev = boost::prior(p); +// const std::list::iterator next = boost::next(prev, 2); + +// Contributed by Dave Abrahams + +namespace next_prior_detail { + +template< typename T, typename Distance, bool HasPlus = has_plus< T, Distance >::value > +struct next_plus_impl; + +template< typename T, typename Distance > +struct next_plus_impl< T, Distance, true > +{ + static T call(T x, Distance n) + { + return x + n; + } +}; + +template< typename T, typename Distance, bool HasPlusAssign = has_plus_assign< T, Distance >::value > +struct next_plus_assign_impl : + public next_plus_impl< T, Distance > +{ +}; + +template< typename T, typename Distance > +struct next_plus_assign_impl< T, Distance, true > +{ + static T call(T x, Distance n) + { + x += n; + return x; + } +}; + +template< typename T, typename Distance, bool IsIterator = boost::iterators::is_iterator< T >::value > +struct next_advance_impl : + public next_plus_assign_impl< T, Distance > +{ +}; + +template< typename T, typename Distance > +struct next_advance_impl< T, Distance, true > +{ + static T call(T x, Distance n) + { + boost::iterators::advance(x, n); + return x; + } +}; + + +template< typename T, typename Distance, bool HasMinus = has_minus< T, Distance >::value > +struct prior_minus_impl; + +template< typename T, typename Distance > +struct prior_minus_impl< T, Distance, true > +{ + static T call(T x, Distance n) + { + return x - n; + } +}; + +template< typename T, typename Distance, bool HasMinusAssign = has_minus_assign< T, Distance >::value > +struct prior_minus_assign_impl : + public prior_minus_impl< T, Distance > +{ +}; + +template< typename T, typename Distance > +struct prior_minus_assign_impl< T, Distance, true > +{ + static T call(T x, Distance n) + { + x -= n; + return x; + } +}; + +template< typename T, typename Distance, bool IsIterator = boost::iterators::is_iterator< T >::value > +struct prior_advance_impl : + public prior_minus_assign_impl< T, Distance > +{ +}; + +template< typename T, typename Distance > +struct prior_advance_impl< T, Distance, true > +{ + static T call(T x, Distance n) + { + // Avoid negating n to sidestep possible integer overflow + boost::iterators::reverse_iterator< T > rx(x); + boost::iterators::advance(rx, n); + return rx.base(); + } +}; + +} // namespace next_prior_detail + +template +inline T next(T x) { return ++x; } + +template +inline T next(T x, Distance n) +{ + return next_prior_detail::next_advance_impl< T, Distance >::call(x, n); +} + +template +inline T prior(T x) { return --x; } + +template +inline T prior(T x, Distance n) +{ + return next_prior_detail::prior_advance_impl< T, Distance >::call(x, n); +} + +} // namespace boost + +#endif // BOOST_NEXT_PRIOR_HPP_INCLUDED diff --git a/libs/iterator/include/boost/pending/detail/int_iterator.hpp b/libs/iterator/include/boost/pending/detail/int_iterator.hpp new file mode 100644 index 00000000..dcc7024d --- /dev/null +++ b/libs/iterator/include/boost/pending/detail/int_iterator.hpp @@ -0,0 +1,82 @@ +// (C) Copyright Jeremy Siek 1999. +// 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) + +#ifndef BOOST_INT_ITERATOR_H +#define BOOST_INT_ITERATOR_H + +#if !defined BOOST_MSVC +#include +#endif +#include +#include +#include +//using namespace std; + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE +namespace boost { +namespace iterators { +#endif + +// this should use random_access_iterator_helper but I've had +// VC++ portablility problems with that. -JGS +template +class int_iterator +{ + typedef int_iterator self; +public: + typedef std::random_access_iterator_tag iterator_category; + typedef IntT value_type; + typedef IntT& reference; + typedef IntT* pointer; + typedef std::ptrdiff_t difference_type; + + inline int_iterator() : _i(0) { } + inline int_iterator(IntT i) : _i(i) { } + inline int_iterator(const self& x) : _i(x._i) { } + inline self& operator=(const self& x) { _i = x._i; return *this; } + inline IntT operator*() { return _i; } + inline IntT operator[](IntT n) { return _i + n; } + inline self& operator++() { ++_i; return *this; } + inline self operator++(int) { self t = *this; ++_i; return t; } + inline self& operator+=(IntT n) { _i += n; return *this; } + inline self operator+(IntT n) { self t = *this; t += n; return t; } + inline self& operator--() { --_i; return *this; } + inline self operator--(int) { self t = *this; --_i; return t; } + inline self& operator-=(IntT n) { _i -= n; return *this; } + inline IntT operator-(const self& x) const { return _i - x._i; } + inline bool operator==(const self& x) const { return _i == x._i; } + // vc++ had a problem finding != in random_access_iterator_helper + // need to look into this... for now implementing everything here -JGS + inline bool operator!=(const self& x) const { return _i != x._i; } + inline bool operator<(const self& x) const { return _i < x._i; } + inline bool operator<=(const self& x) const { return _i <= x._i; } + inline bool operator>(const self& x) const { return _i > x._i; } + inline bool operator>=(const self& x) const { return _i >= x._i; } +protected: + IntT _i; +}; + +template +inline int_iterator +operator+(IntT n, int_iterator t) { t += n; return t; } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE +} /* namespace iterators */ + +using iterators::int_iterator; + +} /* namespace boost */ +#endif + +#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE +namespace boost { +using ::int_iterator; +namespace iterators { +using ::int_iterator; +}} +#endif + + +#endif /* BOOST_INT_ITERATOR_H */ diff --git a/libs/iterator/include/boost/pending/iterator_adaptors.hpp b/libs/iterator/include/boost/pending/iterator_adaptors.hpp new file mode 100644 index 00000000..2256e812 --- /dev/null +++ b/libs/iterator/include/boost/pending/iterator_adaptors.hpp @@ -0,0 +1,6 @@ +// Copyright David Abrahams 2003. +// 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) + +#include diff --git a/libs/iterator/include/boost/pending/iterator_tests.hpp b/libs/iterator/include/boost/pending/iterator_tests.hpp new file mode 100644 index 00000000..a6836836 --- /dev/null +++ b/libs/iterator/include/boost/pending/iterator_tests.hpp @@ -0,0 +1,290 @@ +// Copyright David Abrahams and Jeremy Siek 2003. +// 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) +#ifndef BOOST_ITERATOR_TESTS_HPP +# define BOOST_ITERATOR_TESTS_HPP + +// This is meant to be the beginnings of a comprehensive, generic +// test suite for STL concepts such as iterators and containers. +// +// Revision History: +// 28 Apr 2002 Fixed input iterator requirements. +// For a == b a++ == b++ is no longer required. +// See 24.1.1/3 for details. +// (Thomas Witt) +// 08 Feb 2001 Fixed bidirectional iterator test so that +// --i is no longer a precondition. +// (Jeremy Siek) +// 04 Feb 2001 Added lvalue test, corrected preconditions +// (David Abrahams) + +# include +# include +# include // for detail::dummy_constructor +# include +# include +# include +# include +# include + +namespace boost { + + // use this for the value type +struct dummyT { + dummyT() { } + dummyT(detail::dummy_constructor) { } + dummyT(int x) : m_x(x) { } + int foo() const { return m_x; } + bool operator==(const dummyT& d) const { return m_x == d.m_x; } + int m_x; +}; + +} + +namespace boost { +namespace iterators { + +// Tests whether type Iterator satisfies the requirements for a +// TrivialIterator. +// Preconditions: i != j, *i == val +template +void trivial_iterator_test(const Iterator i, const Iterator j, T val) +{ + Iterator k; + BOOST_TEST(i == i); + BOOST_TEST(j == j); + BOOST_TEST(i != j); +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + T v = *i; +#else + typename std::iterator_traits::value_type v = *i; +#endif + BOOST_TEST(v == val); + boost::ignore_unused(v); +#if 0 + // hmm, this will give a warning for transform_iterator... perhaps + // this should be separated out into a stand-alone test since there + // are several situations where it can't be used, like for + // integer_range::iterator. + BOOST_TEST(v == i->foo()); +#endif + k = i; + BOOST_TEST(k == k); + BOOST_TEST(k == i); + BOOST_TEST(k != j); + BOOST_TEST(*k == val); + boost::ignore_unused(k); +} + + +// Preconditions: i != j +template +void mutable_trivial_iterator_test(const Iterator i, const Iterator j, T val) +{ + *i = val; + trivial_iterator_test(i, j, val); +} + + +// Preconditions: *i == v1, *++i == v2 +template +void input_iterator_test(Iterator i, T v1, T v2) +{ + Iterator i1(i); + + BOOST_TEST(i == i1); + BOOST_TEST(!(i != i1)); + + // I can see no generic way to create an input iterator + // that is in the domain of== of i and != i. + // The following works for istream_iterator but is not + // guaranteed to work for arbitrary input iterators. + // + // Iterator i2; + // + // BOOST_TEST(i != i2); + // BOOST_TEST(!(i == i2)); + + BOOST_TEST(*i1 == v1); + BOOST_TEST(*i == v1); + + // we cannot test for equivalence of (void)++i & (void)i++ + // as i is only guaranteed to be single pass. + BOOST_TEST(*i++ == v1); + boost::ignore_unused(i1); + + i1 = i; + + BOOST_TEST(i == i1); + BOOST_TEST(!(i != i1)); + + BOOST_TEST(*i1 == v2); + BOOST_TEST(*i == v2); + boost::ignore_unused(i1); + + // i is dereferencable, so it must be incrementable. + ++i; + + // how to test for operator-> ? +} + +// how to test output iterator? + + +template struct lvalue_test +{ + template static void check(Iterator) + { +# ifndef BOOST_NO_STD_ITERATOR_TRAITS + typedef typename std::iterator_traits::reference reference; + typedef typename std::iterator_traits::value_type value_type; +# else + typedef typename Iterator::reference reference; + typedef typename Iterator::value_type value_type; +# endif + BOOST_STATIC_ASSERT(boost::is_reference::value); + BOOST_STATIC_ASSERT((boost::is_same::value + || boost::is_same::value + )); + } +}; + +# ifdef BOOST_NO_STD_ITERATOR_TRAITS +template <> struct lvalue_test { + template static void check(T) {} +}; +#endif + +template +void forward_iterator_test(Iterator i, T v1, T v2) +{ + input_iterator_test(i, v1, v2); + + Iterator i1 = i, i2 = i; + + BOOST_TEST(i == i1++); + BOOST_TEST(i != ++i2); + + trivial_iterator_test(i, i1, v1); + trivial_iterator_test(i, i2, v1); + + ++i; + BOOST_TEST(i == i1); + BOOST_TEST(i == i2); + ++i1; + ++i2; + + trivial_iterator_test(i, i1, v2); + trivial_iterator_test(i, i2, v2); + + // borland doesn't allow non-type template parameters +# if !defined(BOOST_BORLANDC) || (BOOST_BORLANDC > 0x551) + lvalue_test<(boost::is_pointer::value)>::check(i); +#endif +} + +// Preconditions: *i == v1, *++i == v2 +template +void bidirectional_iterator_test(Iterator i, T v1, T v2) +{ + forward_iterator_test(i, v1, v2); + ++i; + + Iterator i1 = i, i2 = i; + + BOOST_TEST(i == i1--); + BOOST_TEST(i != --i2); + + trivial_iterator_test(i, i1, v2); + trivial_iterator_test(i, i2, v2); + + --i; + BOOST_TEST(i == i1); + BOOST_TEST(i == i2); + ++i1; + ++i2; + + trivial_iterator_test(i, i1, v1); + trivial_iterator_test(i, i2, v1); +} + +// mutable_bidirectional_iterator_test + +template struct undefined; + +// Preconditions: [i,i+N) is a valid range +template +void random_access_iterator_test(Iterator i, int N, TrueVals vals) +{ + bidirectional_iterator_test(i, vals[0], vals[1]); + const Iterator j = i; + int c; + + typedef typename std::iterator_traits::value_type value_type; + struct local + { + static value_type to_value_type(value_type v) { return v; } + }; + + for (c = 0; c < N-1; ++c) { + BOOST_TEST(i == j + c); + BOOST_TEST(*i == vals[c]); + BOOST_TEST(*i == local::to_value_type(j[c])); + BOOST_TEST(*i == *(j + c)); + BOOST_TEST(*i == *(c + j)); + ++i; + BOOST_TEST(i > j); + BOOST_TEST(i >= j); + BOOST_TEST(j <= i); + BOOST_TEST(j < i); + } + + Iterator k = j + N - 1; + for (c = 0; c < N-1; ++c) { + BOOST_TEST(i == k - c); + BOOST_TEST(*i == vals[N - 1 - c]); + BOOST_TEST(*i == local::to_value_type(j[N - 1 - c])); + Iterator q = k - c; + boost::ignore_unused(q); + BOOST_TEST(*i == *q); + BOOST_TEST(i > j); + BOOST_TEST(i >= j); + BOOST_TEST(j <= i); + BOOST_TEST(j < i); + --i; + } +} + +// Precondition: i != j +template +void const_nonconst_iterator_test(Iterator i, ConstIterator j) +{ + BOOST_TEST(i != j); + BOOST_TEST(j != i); + + ConstIterator k(i); + BOOST_TEST(k == i); + BOOST_TEST(i == k); + + k = i; + BOOST_TEST(k == i); + BOOST_TEST(i == k); + boost::ignore_unused(k); +} + +} // namespace iterators + +using iterators::undefined; +using iterators::trivial_iterator_test; +using iterators::mutable_trivial_iterator_test; +using iterators::input_iterator_test; +using iterators::lvalue_test; +using iterators::forward_iterator_test; +using iterators::bidirectional_iterator_test; +using iterators::random_access_iterator_test; +using iterators::const_nonconst_iterator_test; + +} // namespace boost + +#endif // BOOST_ITERATOR_TESTS_HPP diff --git a/libs/iterator/include/boost/pointee.hpp b/libs/iterator/include/boost/pointee.hpp new file mode 100644 index 00000000..69efa940 --- /dev/null +++ b/libs/iterator/include/boost/pointee.hpp @@ -0,0 +1,76 @@ +#ifndef POINTEE_DWA200415_HPP +# define POINTEE_DWA200415_HPP + +// +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to 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) +// +// typename pointee

::type provides the pointee type of P. +// +// For example, it is T for T* and X for shared_ptr. +// +// http://www.boost.org/libs/iterator/doc/pointee.html +// + +# include +# include +# include +# include +# include +# include + +#include + +namespace boost { + +namespace detail +{ + template + struct smart_ptr_pointee + { + typedef typename P::element_type type; + }; + + template + struct iterator_pointee + { + typedef typename std::iterator_traits::value_type value_type; + + struct impl + { + template + static char test(T const&); + + static char (& test(value_type&) )[2]; + + static Iterator& x; + }; + + BOOST_STATIC_CONSTANT(bool, is_constant = sizeof(impl::test(*impl::x)) == 1); + + typedef typename mpl::if_c< +# if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) + ::boost::detail::iterator_pointee::is_constant +# else + is_constant +# endif + , typename add_const::type + , value_type + >::type type; + }; +} + +template +struct pointee + : mpl::eval_if< + detail::is_incrementable

+ , detail::iterator_pointee

+ , detail::smart_ptr_pointee

+ > +{ +}; + +} // namespace boost + +#endif // POINTEE_DWA200415_HPP diff --git a/libs/iterator/include/boost/shared_container_iterator.hpp b/libs/iterator/include/boost/shared_container_iterator.hpp new file mode 100644 index 00000000..8adcaf7e --- /dev/null +++ b/libs/iterator/include/boost/shared_container_iterator.hpp @@ -0,0 +1,69 @@ +// (C) Copyright Ronald Garcia 2002. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org/libs/utility/shared_container_iterator.html for documentation. + +#ifndef BOOST_SHARED_CONTAINER_ITERATOR_HPP +#define BOOST_SHARED_CONTAINER_ITERATOR_HPP + +#include "boost/iterator_adaptors.hpp" +#include "boost/shared_ptr.hpp" +#include + +namespace boost { +namespace iterators { + +template +class shared_container_iterator : public iterator_adaptor< + shared_container_iterator, + typename Container::iterator> { + + typedef iterator_adaptor< + shared_container_iterator, + typename Container::iterator> super_t; + + typedef typename Container::iterator iterator_t; + typedef boost::shared_ptr container_ref_t; + + container_ref_t container_ref; +public: + shared_container_iterator() { } + + shared_container_iterator(iterator_t const& x,container_ref_t const& c) : + super_t(x), container_ref(c) { } + + +}; + +template +inline shared_container_iterator +make_shared_container_iterator(typename Container::iterator iter, + boost::shared_ptr const& container) { + typedef shared_container_iterator iterator; + return iterator(iter,container); +} + + + +template +inline std::pair< + shared_container_iterator, + shared_container_iterator > +make_shared_container_range(boost::shared_ptr const& container) { + return + std::make_pair( + make_shared_container_iterator(container->begin(),container), + make_shared_container_iterator(container->end(),container)); +} + +} // namespace iterators + +using iterators::shared_container_iterator; +using iterators::make_shared_container_iterator; +using iterators::make_shared_container_range; + +} // namespace boost + +#endif diff --git a/libs/iterator/index.html b/libs/iterator/index.html new file mode 100644 index 00000000..71517c40 --- /dev/null +++ b/libs/iterator/index.html @@ -0,0 +1,12 @@ + + + + + +Automatically loading index page... if nothing happens, please go to +doc/index.html. + + + + + diff --git a/libs/iterator/meta/libraries.json b/libs/iterator/meta/libraries.json new file mode 100644 index 00000000..34c9d484 --- /dev/null +++ b/libs/iterator/meta/libraries.json @@ -0,0 +1,19 @@ +{ + "key": "iterator", + "name": "Iterator", + "authors": [ + "Dave Abrahams", + "Jeremy Siek", + "Thomas Witt" + ], + "description": "The Boost Iterator Library contains two parts. The first is a system of concepts which extend the C++ standard iterator requirements. The second is a framework of components for building iterators based on these extended concepts and includes several useful iterator adaptors.", + "category": [ + "Iterators" + ], + "maintainers": [ + "David Abrahams ", + "Thomas Witt ", + "Jeffrey Lee Hellrung Jr. " + ], + "cxxstd": "03" +} diff --git a/libs/iterator/test/Jamfile.v2 b/libs/iterator/test/Jamfile.v2 new file mode 100644 index 00000000..0cd9b7fe --- /dev/null +++ b/libs/iterator/test/Jamfile.v2 @@ -0,0 +1,70 @@ +# Copyright David Abrahams 2003. 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) + +test-suite iterator + : + # These first two tests will run last, and are expected to fail + # for many less-capable compilers. + + [ compile-fail interoperable_fail.cpp ] + # test uses expected success, so that we catch unrelated + # compilation problems. + [ run is_convertible_fail.cpp ] + + [ run zip_iterator_test.cpp + : : : + # stlport's debug mode generates long symbols which overwhelm + # vc6 + #<*>release + ] + [ run zip_iterator_test2_std_tuple.cpp ] + [ run zip_iterator_test2_fusion_vector.cpp ] + [ run zip_iterator_test2_fusion_list.cpp ] +# [ run zip_iterator_test2_fusion_deque.cpp ] // See bug report for fusion https://svn.boost.org/trac/boost/ticket/11572 + [ run zip_iterator_test_fusion.cpp ] + [ run zip_iterator_test_std_tuple.cpp ] + [ run zip_iterator_test_std_pair.cpp ] + + [ run is_iterator.cpp ] + + # These tests should work for just about everything. + [ compile is_lvalue_iterator.cpp ] + [ compile is_readable_iterator.cpp ] + [ compile pointee.cpp ] + + [ run unit_tests.cpp ] + [ run concept_tests.cpp ] + [ run iterator_adaptor_cc.cpp ] + [ run iterator_adaptor_test.cpp ] + [ compile iterator_archetype_cc.cpp ] + [ compile-fail iter_archetype_default_ctor.cpp ] + [ compile-fail lvalue_concept_fail.cpp ] + [ run transform_iterator_test.cpp ] + [ run indirect_iterator_test.cpp ] + [ compile indirect_iter_member_types.cpp ] + [ run filter_iterator_test.cpp ] + [ run iterator_facade.cpp ] + [ run reverse_iterator_test.cpp ] + [ run counting_iterator_test.cpp ] + [ run interoperable.cpp ] + [ run iterator_traits_test.cpp ] + [ run permutation_iterator_test.cpp : : : # on + ] + [ run function_input_iterator_test.cpp ] + [ run function_output_iterator_test.cpp ] + [ compile-fail function_output_iterator_cf.cpp ] + + [ run generator_iterator_test.cpp ] + + [ run minimum_category.cpp ] + [ compile-fail minimum_category_compile_fail.cpp ] + + [ run next_prior_test.cpp ] + [ run advance_test.cpp ] + [ run distance_test.cpp ] + [ compile adl_test.cpp ] + [ compile range_distance_compat_test.cpp ] + + [ run shared_iterator_test.cpp ] +; diff --git a/libs/iterator/test/adl_test.cpp b/libs/iterator/test/adl_test.cpp new file mode 100644 index 00000000..5d5f6996 --- /dev/null +++ b/libs/iterator/test/adl_test.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2017 Michel Morin. +// +// 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) + +#include +#include +#include +#include + +int main() +{ + // Test that boost::advance/distance are not found by ADL. + // (https://github.com/boostorg/iterator/issues/43) + + typedef boost::array boost_type; + std::vector std_boost(2); + std::vector::iterator it = std_boost.begin(); + + advance(it, 2); + (void)distance(it, it); + + return 0; +} diff --git a/libs/iterator/test/advance_test.cpp b/libs/iterator/test/advance_test.cpp new file mode 100644 index 00000000..85cd4ac6 --- /dev/null +++ b/libs/iterator/test/advance_test.cpp @@ -0,0 +1,91 @@ +// Copyright (C) 2017 Michel Morin. +// +// 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) + +#include +#include +#include +#include +#include +#include + +int twice(int x) { return x + x; } + +template +void test_advance(Iterator it_from, Iterator it_to, int n) +{ + boost::advance(it_from, n); + BOOST_TEST(it_from == it_to); +} + +int main() +{ + int array[3] = {1, 2, 3}; + int* ptr1 = array; + int* ptr2 = array + 3; + + { + test_advance(ptr1, ptr2, 3); + test_advance(ptr2, ptr1, -3); + + test_advance( + boost::make_transform_iterator(ptr1, twice) + , boost::make_transform_iterator(ptr2, twice) + , 3 + ); + test_advance( + boost::make_transform_iterator(ptr2, twice) + , boost::make_transform_iterator(ptr1, twice) + , -3 + ); + } + + { + std::vector ints(ptr1, ptr2); + test_advance(ints.begin(), ints.end(), 3); + test_advance(ints.end(), ints.begin(), -3); + + test_advance( + boost::make_transform_iterator(ints.begin(), twice) + , boost::make_transform_iterator(ints.end(), twice) + , 3 + ); + test_advance( + boost::make_transform_iterator(ints.end(), twice) + , boost::make_transform_iterator(ints.begin(), twice) + , -3 + ); + } + + { + std::list ints(ptr1, ptr2); + test_advance(ints.begin(), ints.end(), 3); + test_advance(ints.end(), ints.begin(), -3); + + test_advance( + boost::make_transform_iterator(ints.begin(), twice) + , boost::make_transform_iterator(ints.end(), twice) + , 3 + ); + test_advance( + boost::make_transform_iterator(ints.end(), twice) + , boost::make_transform_iterator(ints.begin(), twice) + , -3 + ); + } + + { + boost::container::slist ints(ptr1, ptr2); + test_advance(ints.begin(), ints.end(), 3); + + test_advance( + boost::make_transform_iterator(ints.begin(), twice) + , boost::make_transform_iterator(ints.end(), twice) + , 3 + ); + } + + return boost::report_errors(); +} diff --git a/libs/iterator/test/concept_tests.cpp b/libs/iterator/test/concept_tests.cpp new file mode 100644 index 00000000..091f6e52 --- /dev/null +++ b/libs/iterator/test/concept_tests.cpp @@ -0,0 +1,107 @@ +// (C) Copyright Jeremy Siek 2002. +// 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) + +#include +#include +#include + +#include +#include + +struct new_random_access + : std::random_access_iterator_tag + , boost::random_access_traversal_tag +{}; + +struct new_iterator +{ + typedef new_random_access iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + + int& operator*() const { return *m_x; } + new_iterator& operator++() { return *this; } + new_iterator operator++(int) { return *this; } + new_iterator& operator--() { return *this; } + new_iterator operator--(int) { return *this; } + new_iterator& operator+=(std::ptrdiff_t) { return *this; } + new_iterator operator+(std::ptrdiff_t) { return *this; } + new_iterator& operator-=(std::ptrdiff_t) { return *this; } + std::ptrdiff_t operator-(const new_iterator&) const { return 0; } + new_iterator operator-(std::ptrdiff_t) const { return *this; } + bool operator==(const new_iterator&) const { return false; } + bool operator!=(const new_iterator&) const { return false; } + bool operator<(const new_iterator&) const { return false; } + int* m_x; +}; +new_iterator operator+(std::ptrdiff_t, new_iterator x) { return x; } + +struct old_iterator +{ + typedef std::random_access_iterator_tag iterator_category; + typedef int value_type; + typedef std::ptrdiff_t difference_type; + typedef int* pointer; + typedef int& reference; + + int& operator*() const { return *m_x; } + old_iterator& operator++() { return *this; } + old_iterator operator++(int) { return *this; } + old_iterator& operator--() { return *this; } + old_iterator operator--(int) { return *this; } + old_iterator& operator+=(std::ptrdiff_t) { return *this; } + old_iterator operator+(std::ptrdiff_t) { return *this; } + old_iterator& operator-=(std::ptrdiff_t) { return *this; } + old_iterator operator-(std::ptrdiff_t) const { return *this; } + std::ptrdiff_t operator-(const old_iterator&) const { return 0; } + bool operator==(const old_iterator&) const { return false; } + bool operator!=(const old_iterator&) const { return false; } + bool operator<(const old_iterator&) const { return false; } + int* m_x; +}; +old_iterator operator+(std::ptrdiff_t, old_iterator x) { return x; } + +int +main() +{ + boost::iterator_traversal::type tc; + boost::random_access_traversal_tag derived = tc; + (void)derived; + + boost::function_requires< + boost_concepts::WritableIteratorConcept >(); + boost::function_requires< + boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< + boost_concepts::RandomAccessTraversalConcept >(); + + boost::function_requires< + boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< + boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< + boost_concepts::RandomAccessTraversalConcept >(); + + boost::function_requires< + boost_concepts::WritableIteratorConcept >(); + boost::function_requires< + boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< + boost_concepts::RandomAccessTraversalConcept >(); + + boost::function_requires< + boost_concepts::WritableIteratorConcept >(); + boost::function_requires< + boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< + boost_concepts::RandomAccessTraversalConcept >(); + + boost::function_requires< + boost_concepts::InteroperableIteratorConcept >(); + + return 0; +} diff --git a/libs/iterator/test/constant_iter_arrow.cpp b/libs/iterator/test/constant_iter_arrow.cpp new file mode 100644 index 00000000..3579c53b --- /dev/null +++ b/libs/iterator/test/constant_iter_arrow.cpp @@ -0,0 +1,16 @@ +// Copyright David Abrahams 2004. 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) + +#include +#include + +struct my_iter : boost::iterator_adaptor const*> +{ + my_iter(std::pair const*); + my_iter(); +}; + +std::pair const x(1,1); +my_iter p(&x); +int y = p->first; // operator-> attempts to return an non-const pointer diff --git a/libs/iterator/test/constant_iter_arrow_fail.cpp b/libs/iterator/test/constant_iter_arrow_fail.cpp new file mode 100644 index 00000000..05f551a9 --- /dev/null +++ b/libs/iterator/test/constant_iter_arrow_fail.cpp @@ -0,0 +1,20 @@ +// Copyright David Abrahams 2004. 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) + +#include +#include + +struct my_iter : boost::iterator_adaptor const*> +{ + my_iter(std::pair const*); + my_iter(); +}; + +std::pair const x(1,1); +my_iter p(&x); + +void test() +{ + p->first = 3; +} diff --git a/libs/iterator/test/counting_iterator_test.cpp b/libs/iterator/test/counting_iterator_test.cpp new file mode 100644 index 00000000..09d4295b --- /dev/null +++ b/libs/iterator/test/counting_iterator_test.cpp @@ -0,0 +1,301 @@ +// (C) Copyright David Abrahams 2001. +// 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) +// +// See http://www.boost.org for most recent version including documentation. +// +// Revision History +// 16 Feb 2001 Added a missing const. Made the tests run (somewhat) with +// plain MSVC again. (David Abrahams) +// 11 Feb 2001 #if 0'd out use of counting_iterator on non-numeric types in +// MSVC without STLport, so that the other tests may proceed +// (David Abrahams) +// 04 Feb 2001 Added use of iterator_tests.hpp (David Abrahams) +// 28 Jan 2001 Removed not_an_iterator detritus (David Abrahams) +// 24 Jan 2001 Initial revision (David Abrahams) + +#include + +#ifdef BOOST_BORLANDC // Borland mis-detects our custom iterators +# pragma warn -8091 // template argument ForwardIterator passed to '...' is a output iterator +# pragma warn -8071 // Conversion may lose significant digits (due to counting_iterator += n). +#endif + +#ifdef BOOST_MSVC +# pragma warning(disable:4786) // identifier truncated in debug info +#endif + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#ifndef BOOST_BORLANDC +# include +#endif +#include +#include +#include +#ifndef BOOST_NO_SLIST +# ifdef BOOST_SLIST_HEADER +# include BOOST_SLIST_HEADER +# else +# include +# endif +#endif + + +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS +template +struct signed_assert_nonnegative +{ + static void test(T x) { BOOST_TEST(x >= 0); } +}; + +template +struct unsigned_assert_nonnegative +{ + static void test(T x) {} +}; + +template +struct assert_nonnegative + : boost::conditional< + std::numeric_limits::is_signed + , signed_assert_nonnegative + , unsigned_assert_nonnegative + >::type +{ +}; +#endif + +// Special tests for RandomAccess CountingIterators. +template +void category_test( + CountingIterator start, + CountingIterator finish, + Value, + std::random_access_iterator_tag) +{ + typedef typename + std::iterator_traits::difference_type + difference_type; + difference_type distance = std::distance(start, finish); + + // Pick a random position internal to the range + difference_type offset = (unsigned)rand() % distance; + +#ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_TEST(offset >= 0); +#else + assert_nonnegative::test(offset); +#endif + + CountingIterator internal = start; + std::advance(internal, offset); + + // Try some binary searches on the range to show that it's ordered + BOOST_TEST(std::binary_search(start, finish, *internal)); + + // #including tuple crashed borland, so I had to give up on tie(). + std::pair xy( + std::equal_range(start, finish, *internal)); + CountingIterator x = xy.first, y = xy.second; + + BOOST_TEST(std::distance(x, y) == 1); + + // Show that values outside the range can't be found + BOOST_TEST(!std::binary_search(start, boost::prior(finish), *finish)); + + // Do the generic random_access_iterator_test + typedef typename CountingIterator::value_type value_type; + std::vector v; + for (value_type z = *start; !(z == *finish); ++z) + v.push_back(z); + + // Note that this test requires a that the first argument is + // dereferenceable /and/ a valid iterator prior to the first argument + boost::random_access_iterator_test(start, v.size(), v.begin()); +} + +// Special tests for bidirectional CountingIterators +template +void category_test(CountingIterator start, Value v1, std::bidirectional_iterator_tag) +{ + Value v2 = v1; + ++v2; + + // Note that this test requires a that the first argument is + // dereferenceable /and/ a valid iterator prior to the first argument + boost::bidirectional_iterator_test(start, v1, v2); +} + +template +void category_test(CountingIterator start, CountingIterator finish, Value v1, std::forward_iterator_tag) +{ + Value v2 = v1; + ++v2; + if (finish != start && finish != boost::next(start)) + boost::forward_readable_iterator_test(start, finish, v1, v2); +} + +template +void test_aux(CountingIterator start, CountingIterator finish, Value v1) +{ + typedef typename CountingIterator::iterator_category category; + + // If it's a RandomAccessIterator we can do a few delicate tests + category_test(start, finish, v1, category()); + + // Okay, brute force... + for (CountingIterator p = start + ; p != finish && boost::next(p) != finish + ; ++p) + { + BOOST_TEST(boost::next(*p) == *boost::next(p)); + } + + // prove that a reference can be formed to these values + typedef typename CountingIterator::value_type value; + const value* q = &*start; + (void)q; // suppress unused variable warning +} + +template +void test(Incrementable start, Incrementable finish) +{ + test_aux(boost::make_counting_iterator(start), boost::make_counting_iterator(finish), start); +} + +template +void test_integer(Integer* = 0) // default arg works around MSVC bug +{ + Integer start = 0; + Integer finish = 120; + test(start, finish); +} + +template +void test_integer3(Integer* = 0, Category* = 0, Difference* = 0) // default arg works around MSVC bug +{ + Integer start = 0; + Integer finish = 120; + typedef boost::counting_iterator iterator; + test_aux(iterator(start), iterator(finish), start); +} + +template +void test_container(Container* = 0) // default arg works around MSVC bug +{ + Container c(1 + (unsigned)rand() % 1673); + + const typename Container::iterator start = c.begin(); + + // back off by 1 to leave room for dereferenceable value at the end + typename Container::iterator finish = start; + std::advance(finish, c.size() - 1); + + test(start, finish); + + typedef typename Container::const_iterator const_iterator; + test(const_iterator(start), const_iterator(finish)); +} + +class my_int1 { +public: + my_int1() { } + my_int1(int x) : m_int(x) { } + my_int1& operator++() { ++m_int; return *this; } + bool operator==(const my_int1& x) const { return m_int == x.m_int; } +private: + int m_int; +}; + +class my_int2 { +public: + typedef void value_type; + typedef void pointer; + typedef void reference; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + my_int2() { } + my_int2(int x) : m_int(x) { } + my_int2& operator++() { ++m_int; return *this; } + my_int2& operator--() { --m_int; return *this; } + bool operator==(const my_int2& x) const { return m_int == x.m_int; } +private: + int m_int; +}; + +class my_int3 { +public: + typedef void value_type; + typedef void pointer; + typedef void reference; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; + + my_int3() { } + my_int3(int x) : m_int(x) { } + my_int3& operator++() { ++m_int; return *this; } + my_int3& operator+=(std::ptrdiff_t n) { m_int += n; return *this; } + std::ptrdiff_t operator-(const my_int3& x) const { return m_int - x.m_int; } + my_int3& operator--() { --m_int; return *this; } + bool operator==(const my_int3& x) const { return m_int == x.m_int; } + bool operator!=(const my_int3& x) const { return m_int != x.m_int; } + bool operator<(const my_int3& x) const { return m_int < x.m_int; } +private: + int m_int; +}; + +int main() +{ + // Test the built-in integer types. + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); +#if defined(BOOST_HAS_LONG_LONG) + test_integer(); + test_integer(); +#endif +#if defined(BOOST_HAS_INT128) + test_integer(); + test_integer(); +#endif + + // Test user-defined type. + + test_integer3(); + test_integer3(); + test_integer(); + test_integer(); + + // Some tests on container iterators, to prove we handle a few different categories + test_container >(); + test_container >(); +# ifndef BOOST_NO_SLIST + test_container >(); +# endif + + // Also prove that we can handle raw pointers. + int array[2000]; + test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1)); + + return boost::report_errors(); +} diff --git a/libs/iterator/test/detail/zip_iterator_test.ipp b/libs/iterator/test/detail/zip_iterator_test.ipp new file mode 100644 index 00000000..7e0d2f7b --- /dev/null +++ b/libs/iterator/test/detail/zip_iterator_test.ipp @@ -0,0 +1,85 @@ +// Copyright (c) 2014 Kohei Takahashi. +// +// 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) +// +// See http://www.boost.org for most recent version including documentation. + +#include + +#include +#include +#include +#include +#include + + +int main() +{ + typedef TUPLE< + std::vector::iterator, + std::vector::iterator + > iterator_tuple; + + std::vector vi = boost::assign::list_of(42)(72); + std::vector vs = boost::assign::list_of("kokoro")("pyonpyon"); + + { + boost::zip_iterator i1(MAKE_TUPLE(vi.begin(), vs.begin())); + boost::zip_iterator i2 = i1; + + BOOST_TEST( i1 == i2); + BOOST_TEST( i1++ == i2); + BOOST_TEST( i1 == (i2 + 1)); + BOOST_TEST((i1 - 1) == i2); + BOOST_TEST( i1-- == ++i2); + BOOST_TEST( i1 == --i2); + } + + { + boost::zip_iterator i1(MAKE_TUPLE(vi.begin(), vs.begin())); + boost::zip_iterator i2 = i1 + 1; + + BOOST_TEST( i1 != i2); + BOOST_TEST( i1++ != i2); + BOOST_TEST( i1 != (i2 + 1)); + BOOST_TEST((i1 - 1) != i2); + BOOST_TEST( i1-- != ++i2); + BOOST_TEST( i1 != --i2); + } + + { + boost::zip_iterator i(MAKE_TUPLE(vi.begin(), vs.begin())); + + BOOST_TEST(boost::fusion::at_c<0>(* i ) == 42); + BOOST_TEST(boost::fusion::at_c<1>(* i ) == "kokoro"); + BOOST_TEST(boost::fusion::at_c<0>(*(i + 1)) == 72); + BOOST_TEST(boost::fusion::at_c<1>(*(i + 1)) == "pyonpyon"); + } + + { + // Trac #12895 + boost::zip_iterator< + TUPLE + > i(MAKE_TUPLE(&vi[0], &vs[0])); + + BOOST_TEST(boost::fusion::at_c<0>(* i ) == 42); + BOOST_TEST(boost::fusion::at_c<1>(* i ) == "kokoro"); + BOOST_TEST(boost::fusion::at_c<0>(*(i + 1)) == 72); + BOOST_TEST(boost::fusion::at_c<1>(*(i + 1)) == "pyonpyon"); + } + + { + boost::zip_iterator i1(MAKE_TUPLE(vi.begin(), vs.begin())); + boost::zip_iterator i2(MAKE_TUPLE(vi.end(), vs.end())); + + BOOST_TEST((i2 - i1) == 2); + ++i1; + BOOST_TEST((i2 - i1) == 1); + --i2; + BOOST_TEST((i2 - i1) == 0); + } + + return boost::report_errors(); +} diff --git a/libs/iterator/test/detail/zip_iterator_test_original.ipp b/libs/iterator/test/detail/zip_iterator_test_original.ipp new file mode 100644 index 00000000..dc042214 --- /dev/null +++ b/libs/iterator/test/detail/zip_iterator_test_original.ipp @@ -0,0 +1,857 @@ +// (C) Copyright Dave Abrahams and Thomas Becker 2003. 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) +// + +// File: +// ===== +// zip_iterator_test_main.cpp + +// Author: +// ======= +// Thomas Becker + +// Created: +// ======== +// Jul 15, 2003 + +// Purpose: +// ======== +// Test driver for zip_iterator.hpp + +// Compilers Tested: +// ================= +// Metrowerks Codewarrior Pro 7.2, 8.3 +// gcc 2.95.3 +// gcc 3.2 +// Microsoft VC 6sp5 (test fails due to some compiler bug) +// Microsoft VC 7 (works) +// Microsoft VC 7.1 +// Intel 5 +// Intel 6 +// Intel 7.1 +// Intel 8 +// Borland 5.5.1 (broken due to lack of support from Boost.Tuples) + +///////////////////////////////////////////////////////////////////////////// +// +// Includes +// +///////////////////////////////////////////////////////////////////////////// + +#include +#include // 2nd #include tests #include guard. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/// Tests for https://svn.boost.org/trac/boost/ticket/1517 +int to_value(int const &v) +{ + return v; +} + +void category_test() +{ + std::list rng1; + std::string rng2; + + boost::make_zip_iterator( + ZI_MAKE_TUPLE( + boost::make_transform_iterator(rng1.begin(), &to_value), // BidirectionalInput + rng2.begin() // RandomAccess + ) + ); +} +/// + +///////////////////////////////////////////////////////////////////////////// +// +// Das Main Funktion +// +///////////////////////////////////////////////////////////////////////////// + +int main( void ) +{ + + category_test(); + + std::cout << "\n" + << "***********************************************\n" + << "* *\n" + << "* Test driver for boost::zip_iterator *\n" + << "* Copyright Thomas Becker 2003 *\n" + << "* *\n" + << "***********************************************\n\n" + << std::flush; + + size_t num_successful_tests = 0; + size_t num_failed_tests = 0; + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator construction and dereferencing + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator construction and dereferencing: " + << std::flush; + + std::vector vect1(3); + vect1[0] = 42.; + vect1[1] = 43.; + vect1[2] = 44.; + + std::set intset; + intset.insert(52); + intset.insert(53); + intset.insert(54); + // + + typedef + boost::zip_iterator< + ZI_TUPLE< + std::set::iterator + , std::vector::iterator + > + > zit_mixed; + + zit_mixed zip_it_mixed = zit_mixed( + ZI_MAKE_TUPLE( + intset.begin() + , vect1.begin() + ) + ); + + ZI_TUPLE val_tuple( + *zip_it_mixed); + + ZI_TUPLE ref_tuple( + *zip_it_mixed); + + double dblOldVal = ZI_TUPLE_GET(1)(ref_tuple); + ZI_TUPLE_GET(1)(ref_tuple) -= 41.; + + if( 52 == ZI_TUPLE_GET(0)(val_tuple) && + 42. == ZI_TUPLE_GET(1)(val_tuple) && + 52 == ZI_TUPLE_GET(0)(ref_tuple) && + 1. == ZI_TUPLE_GET(1)(ref_tuple) && + 1. == *vect1.begin() + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + // Undo change to vect1 + ZI_TUPLE_GET(1)(ref_tuple) = dblOldVal; + +#if defined(ZI_USE_BOOST_TUPLE) + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator with 12 components + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterators with 12 components: " + << std::flush; + + // Declare 12 containers + // + std::list li1; + li1.push_back(1); + std::set se1; + se1.insert(2); + std::vector ve1; + ve1.push_back(3); + // + std::list li2; + li2.push_back(4); + std::set se2; + se2.insert(5); + std::vector ve2; + ve2.push_back(6); + // + std::list li3; + li3.push_back(7); + std::set se3; + se3.insert(8); + std::vector ve3; + ve3.push_back(9); + // + std::list li4; + li4.push_back(10); + std::set se4; + se4.insert(11); + std::vector ve4; + ve4.push_back(12); + + // typedefs for cons lists of iterators. + typedef boost::tuples::cons< + std::set::iterator, + ZI_TUPLE< + std::vector::iterator, + std::list::iterator, + std::set::iterator, + std::vector::iterator, + std::list::iterator, + std::set::iterator, + std::vector::iterator, + std::list::iterator, + std::set::iterator, + std::vector::const_iterator + >::inherited + > cons_11_its_type; + // + typedef boost::tuples::cons< + std::list::const_iterator, + cons_11_its_type + > cons_12_its_type; + + // typedefs for cons lists for dereferencing the zip iterator + // made from the cons list above. + typedef boost::tuples::cons< + const int&, + ZI_TUPLE< + int&, + int&, + const int&, + int&, + int&, + const int&, + int&, + int&, + const int&, + const int& + >::inherited + > cons_11_refs_type; + // + typedef boost::tuples::cons< + const int&, + cons_11_refs_type + > cons_12_refs_type; + + // typedef for zip iterator with 12 elements + typedef boost::zip_iterator zip_it_12_type; + + // Declare a 12-element zip iterator. + zip_it_12_type zip_it_12( + cons_12_its_type( + li1.begin(), + cons_11_its_type( + se1.begin(), + ZI_MAKE_TUPLE( + ve1.begin(), + li2.begin(), + se2.begin(), + ve2.begin(), + li3.begin(), + se3.begin(), + ve3.begin(), + li4.begin(), + se4.begin(), + ve4.begin() + ) + ) + ) + ); + + // Dereference, mess with the result a little. + cons_12_refs_type zip_it_12_dereferenced(*zip_it_12); + ZI_TUPLE_GET(9)(zip_it_12_dereferenced) = 42; + + // Make a copy and move it a little to force some instantiations. + zip_it_12_type zip_it_12_copy(zip_it_12); + ++zip_it_12_copy; + + if( ZI_TUPLE_GET(11)(zip_it_12.get_iterator_tuple()) == ve4.begin() && + ZI_TUPLE_GET(11)(zip_it_12_copy.get_iterator_tuple()) == ve4.end() && + 1 == ZI_TUPLE_GET(0)(zip_it_12_dereferenced) && + 12 == ZI_TUPLE_GET(11)(zip_it_12_dereferenced) && + 42 == *(li4.begin()) + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + +#endif + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator incrementing and dereferencing + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator ++ and *: " + << std::flush; + + std::vector vect2(3); + vect2[0] = 2.2; + vect2[1] = 3.3; + vect2[2] = 4.4; + + boost::zip_iterator< + ZI_TUPLE< + std::vector::const_iterator, + std::vector::const_iterator + > + > + zip_it_begin( + ZI_MAKE_TUPLE( + vect1.begin(), + vect2.begin() + ) + ); + + boost::zip_iterator< + ZI_TUPLE< + std::vector::const_iterator, + std::vector::const_iterator + > + > + zip_it_run( + ZI_MAKE_TUPLE( + vect1.begin(), + vect2.begin() + ) + ); + + boost::zip_iterator< + ZI_TUPLE< + std::vector::const_iterator, + std::vector::const_iterator + > + > + zip_it_end( + ZI_MAKE_TUPLE( + vect1.end(), + vect2.end() + ) + ); + + if( zip_it_run == zip_it_begin && + 42. == ZI_TUPLE_GET(0)(*zip_it_run) && + 2.2 == ZI_TUPLE_GET(1)(*zip_it_run) && + 43. == ZI_TUPLE_GET(0)(*(++zip_it_run)) && + 3.3 == ZI_TUPLE_GET(1)(*zip_it_run) && + 44. == ZI_TUPLE_GET(0)(*(++zip_it_run)) && + 4.4 == ZI_TUPLE_GET(1)(*zip_it_run) && + zip_it_end == ++zip_it_run + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator decrementing and dereferencing + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator -- and *: " + << std::flush; + + if( zip_it_run == zip_it_end && + zip_it_end == zip_it_run-- && + 44. == ZI_TUPLE_GET(0)(*zip_it_run) && + 4.4 == ZI_TUPLE_GET(1)(*zip_it_run) && + 43. == ZI_TUPLE_GET(0)(*(--zip_it_run)) && + 3.3 == ZI_TUPLE_GET(1)(*zip_it_run) && + 42. == ZI_TUPLE_GET(0)(*(--zip_it_run)) && + 2.2 == ZI_TUPLE_GET(1)(*zip_it_run) && + zip_it_begin == zip_it_run + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator copy construction and equality + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator copy construction and equality: " + << std::flush; + + boost::zip_iterator< + ZI_TUPLE< + std::vector::const_iterator, + std::vector::const_iterator + > + > zip_it_run_copy(zip_it_run); + + if(zip_it_run == zip_it_run && zip_it_run == zip_it_run_copy) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator inequality + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator inequality: " + << std::flush; + + if(!(zip_it_run != zip_it_run_copy) && zip_it_run != ++zip_it_run_copy) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator less than + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator less than: " + << std::flush; + + // Note: zip_it_run_copy == zip_it_run + 1 + // + if( zip_it_run < zip_it_run_copy && + !( zip_it_run < --zip_it_run_copy) && + zip_it_run == zip_it_run_copy + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator less than or equal + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "zip iterator less than or equal: " + << std::flush; + + // Note: zip_it_run_copy == zip_it_run + // + ++zip_it_run; + zip_it_run_copy += 2; + + if( zip_it_run <= zip_it_run_copy && + zip_it_run <= --zip_it_run_copy && + !( zip_it_run <= --zip_it_run_copy) && + zip_it_run <= zip_it_run + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator greater than + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator greater than: " + << std::flush; + + // Note: zip_it_run_copy == zip_it_run - 1 + // + if( zip_it_run > zip_it_run_copy && + !( zip_it_run > ++zip_it_run_copy) && + zip_it_run == zip_it_run_copy + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator greater than or equal + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator greater than or equal: " + << std::flush; + + ++zip_it_run; + + // Note: zip_it_run == zip_it_run_copy + 1 + // + if( zip_it_run >= zip_it_run_copy && + --zip_it_run >= zip_it_run_copy && + ! (zip_it_run >= ++zip_it_run_copy) + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator + int + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator + int: " + << std::flush; + + // Note: zip_it_run == zip_it_run_copy - 1 + // + zip_it_run = zip_it_run + 2; + ++zip_it_run_copy; + + if( zip_it_run == zip_it_run_copy && zip_it_run == zip_it_begin + 3 ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator - int + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator - int: " + << std::flush; + + // Note: zip_it_run == zip_it_run_copy, and both are at end position + // + zip_it_run = zip_it_run - 2; + --zip_it_run_copy; + --zip_it_run_copy; + + if( zip_it_run == zip_it_run_copy && (zip_it_run - 1) == zip_it_begin ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator += + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator +=: " + << std::flush; + + // Note: zip_it_run == zip_it_run_copy, and both are at begin + 1 + // + zip_it_run += 2; + if( zip_it_run == zip_it_begin + 3 ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator -= + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator -=: " + << std::flush; + + // Note: zip_it_run is at end position, zip_it_run_copy is at + // begin plus one. + // + zip_it_run -= 2; + if( zip_it_run == zip_it_run_copy ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator getting member iterators + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator member iterators: " + << std::flush; + + // Note: zip_it_run and zip_it_run_copy are both at + // begin plus one. + // + if( ZI_TUPLE_GET(0)(zip_it_run.get_iterator_tuple()) == vect1.begin() + 1 && + ZI_TUPLE_GET(1)(zip_it_run.get_iterator_tuple()) == vect2.begin() + 1 + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Making zip iterators + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Making zip iterators: " + << std::flush; + + std::vector > + vect_of_tuples(3); + + std::copy( + boost::make_zip_iterator( + ZI_MAKE_TUPLE( + vect1.begin(), + vect2.begin() + ) + ), + boost::make_zip_iterator( + ZI_MAKE_TUPLE( + vect1.end(), + vect2.end() + ) + ), + vect_of_tuples.begin() + ); + + if( 42. == ZI_TUPLE_GET(0)(*vect_of_tuples.begin()) && + 2.2 == ZI_TUPLE_GET(1)(*vect_of_tuples.begin()) && + 43. == ZI_TUPLE_GET(0)(*(vect_of_tuples.begin() + 1)) && + 3.3 == ZI_TUPLE_GET(1)(*(vect_of_tuples.begin() + 1)) && + 44. == ZI_TUPLE_GET(0)(*(vect_of_tuples.begin() + 2)) && + 4.4 == ZI_TUPLE_GET(1)(*(vect_of_tuples.begin() + 2)) + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator non-const --> const conversion + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator non-const to const conversion: " + << std::flush; + + boost::zip_iterator< + ZI_TUPLE< + std::set::const_iterator, + std::vector::const_iterator + > + > + zip_it_const( + ZI_MAKE_TUPLE( + intset.begin(), + vect2.begin() + ) + ); + // + boost::zip_iterator< + ZI_TUPLE< + std::set::iterator, + std::vector::const_iterator + > + > + zip_it_half_const( + ZI_MAKE_TUPLE( + intset.begin(), + vect2.begin() + ) + ); + // + boost::zip_iterator< + ZI_TUPLE< + std::set::iterator, + std::vector::iterator + > + > + zip_it_non_const( + ZI_MAKE_TUPLE( + intset.begin(), + vect2.begin() + ) + ); + + zip_it_half_const = ++zip_it_non_const; + zip_it_const = zip_it_half_const; + ++zip_it_const; +// zip_it_non_const = ++zip_it_const; // Error: can't convert from const to non-const + + if( 54 == ZI_TUPLE_GET(0)(*zip_it_const) && + 4.4 == ZI_TUPLE_GET(1)(*zip_it_const) && + 53 == ZI_TUPLE_GET(0)(*zip_it_half_const) && + 3.3 == ZI_TUPLE_GET(1)(*zip_it_half_const) + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + + +#if defined(ZI_USE_BOOST_TUPLE) + + ///////////////////////////////////////////////////////////////////////////// + // + // Zip iterator categories + // + ///////////////////////////////////////////////////////////////////////////// + + std::cout << "Zip iterator categories: " + << std::flush; + + // The big iterator of the previous test has vector, list, and set iterators. + // Therefore, it must be bidirectional, but not random access. + bool bBigItIsBidirectionalIterator = boost::is_convertible< + boost::iterator_traversal::type + , boost::bidirectional_traversal_tag + >::value; + + bool bBigItIsRandomAccessIterator = boost::is_convertible< + boost::iterator_traversal::type + , boost::random_access_traversal_tag + >::value; + + // A combining iterator with all vector iterators must have random access + // traversal. + // + typedef boost::zip_iterator< + ZI_TUPLE< + std::vector::const_iterator, + std::vector::const_iterator + > + > all_vects_type; + + bool bAllVectsIsRandomAccessIterator = boost::is_convertible< + boost::iterator_traversal::type + , boost::random_access_traversal_tag + >::value; + + // The big test. + if( bBigItIsBidirectionalIterator && + ! bBigItIsRandomAccessIterator && + bAllVectsIsRandomAccessIterator + ) + { + ++num_successful_tests; + std::cout << "OK" << std::endl; + } + else + { + ++num_failed_tests; + std::cout << "not OK" << std::endl; + } + +#endif + + // Done + // + std::cout << "\nTest Result:" + << "\n============" + << "\nNumber of successful tests: " << static_cast(num_successful_tests) + << "\nNumber of failed tests: " << static_cast(num_failed_tests) + << std::endl; + + return num_failed_tests; +} + diff --git a/libs/iterator/test/distance_test.cpp b/libs/iterator/test/distance_test.cpp new file mode 100644 index 00000000..91587d67 --- /dev/null +++ b/libs/iterator/test/distance_test.cpp @@ -0,0 +1,84 @@ +// Copyright (C) 2017 Michel Morin. +// +// 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) + +#include +#include +#include +#include +#include +#include + +int twice(int x) { return x + x; } + +template +void test_distance(Iterator it_from, Iterator it_to, int n) +{ + BOOST_TEST(boost::distance(it_from, it_to) == n); +} + +int main() +{ + int array[3] = {1, 2, 3}; + int* ptr1 = array; + int* ptr2 = array + 3; + + { + test_distance(ptr1, ptr2, 3); + test_distance(ptr2, ptr1, -3); + + test_distance( + boost::make_transform_iterator(ptr1, twice) + , boost::make_transform_iterator(ptr2, twice) + , 3 + ); + test_distance( + boost::make_transform_iterator(ptr2, twice) + , boost::make_transform_iterator(ptr1, twice) + , -3 + ); + } + + { + std::vector ints(ptr1, ptr2); + test_distance(ints.begin(), ints.end(), 3); + test_distance(ints.end(), ints.begin(), -3); + + test_distance( + boost::make_transform_iterator(ints.begin(), twice) + , boost::make_transform_iterator(ints.end(), twice) + , 3 + ); + test_distance( + boost::make_transform_iterator(ints.end(), twice) + , boost::make_transform_iterator(ints.begin(), twice) + , -3 + ); + } + + { + std::list ints(ptr1, ptr2); + test_distance(ints.begin(), ints.end(), 3); + + test_distance( + boost::make_transform_iterator(ints.begin(), twice) + , boost::make_transform_iterator(ints.end(), twice) + , 3 + ); + } + + { + boost::container::slist ints(ptr1, ptr2); + test_distance(ints.begin(), ints.end(), 3); + + test_distance( + boost::make_transform_iterator(ints.begin(), twice) + , boost::make_transform_iterator(ints.end(), twice) + , 3 + ); + } + + return boost::report_errors(); +} diff --git a/libs/iterator/test/filter_iterator_test.cpp b/libs/iterator/test/filter_iterator_test.cpp new file mode 100644 index 00000000..cf850bcf --- /dev/null +++ b/libs/iterator/test/filter_iterator_test.cpp @@ -0,0 +1,272 @@ +// Copyright David Abrahams 2003, Jeremy Siek 2004. + +// 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) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using boost::dummyT; + +struct one_or_four +{ + bool operator()(dummyT x) const + { + return x.foo() == 1 || x.foo() == 4; + } +}; + +template struct undefined; + +template struct see_type; + +// Test filter iterator +int main() +{ + // Concept checks + // Adapting old-style iterators + { + typedef boost::filter_iterator > Iter; + boost::function_requires< boost::InputIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::SinglePassIteratorConcept >(); + } + { + typedef boost::filter_iterator > Iter; + boost::function_requires< boost::InputIteratorConcept >(); + boost::function_requires< boost::OutputIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::SinglePassIteratorConcept >(); + } + { + typedef boost::filter_iterator > Iter; + boost::function_requires< boost::ForwardIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::ForwardTraversalConcept >(); + } + { + typedef boost::filter_iterator > Iter; + boost::function_requires< boost::Mutable_ForwardIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::ForwardTraversalConcept >(); + } + { + typedef boost::filter_iterator > Iter; + boost::function_requires< boost::BidirectionalIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } + { + typedef boost::filter_iterator > Iter; + boost::function_requires< boost::Mutable_BidirectionalIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } + { + typedef boost::filter_iterator > Iter; + boost::function_requires< boost::BidirectionalIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } + { + typedef boost::filter_iterator > Iter; + boost::function_requires< boost::Mutable_BidirectionalIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } + // Adapting new-style iterators + { + typedef boost::iterator_archetype< + const dummyT + , boost::iterator_archetypes::readable_iterator_t + , boost::single_pass_traversal_tag + > BaseIter; + typedef boost::filter_iterator Iter; + boost::function_requires< boost::InputIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::SinglePassIteratorConcept >(); + } +#if !BOOST_WORKAROUND(BOOST_MSVC, == 1200) // Causes Internal Error in linker. + { + typedef boost::iterator_archetype< + dummyT + , boost::iterator_archetypes::readable_writable_iterator_t + , boost::single_pass_traversal_tag + > BaseIter; + typedef boost::filter_iterator Iter; + + boost::function_requires< boost::InputIteratorConcept >(); + boost::function_requires< boost::OutputIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::SinglePassIteratorConcept >(); + } +#endif + { + typedef boost::iterator_archetype< + const dummyT + , boost::iterator_archetypes::readable_iterator_t + , boost::forward_traversal_tag + > BaseIter; + typedef boost::filter_iterator Iter; + boost::function_requires< boost::InputIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::ForwardTraversalConcept >(); + } + +#if !BOOST_WORKAROUND(BOOST_MSVC, == 1200) // Causes Internal Error in linker. + { + typedef boost::iterator_archetype< + dummyT + , boost::iterator_archetypes::readable_writable_iterator_t + , boost::forward_traversal_tag + > BaseIter; + typedef boost::filter_iterator Iter; + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::ForwardTraversalConcept >(); + } + { + typedef boost::iterator_archetype< + const dummyT + , boost::iterator_archetypes::readable_lvalue_iterator_t + , boost::forward_traversal_tag + > BaseIter; + typedef boost::filter_iterator Iter; + boost::function_requires< boost::ForwardIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< boost_concepts::ForwardTraversalConcept >(); + } + { + typedef boost::iterator_archetype< + dummyT + , boost::iterator_archetypes::writable_lvalue_iterator_t + , boost::forward_traversal_tag + > BaseIter; + typedef boost::filter_iterator Iter; + boost::function_requires< boost::Mutable_ForwardIteratorConcept >(); + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< boost_concepts::ForwardTraversalConcept >(); + } +#endif + + { + typedef boost::iterator_archetype< + const dummyT + , boost::iterator_archetypes::readable_iterator_t + , boost::random_access_traversal_tag + > BaseIter; + typedef boost::filter_iterator Iter; + boost::function_requires< boost::InputIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } + +#if !BOOST_WORKAROUND(BOOST_MSVC, == 1200) // Causes Internal Error in linker. + { + typedef boost::iterator_archetype< + dummyT + , boost::iterator_archetypes::readable_writable_iterator_t + , boost::random_access_traversal_tag + > BaseIter; + typedef boost::filter_iterator Iter; + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } + { + typedef boost::iterator_archetype< + const dummyT + , boost::iterator_archetypes::readable_lvalue_iterator_t + , boost::random_access_traversal_tag + > BaseIter; + typedef boost::filter_iterator Iter; + boost::function_requires< boost::BidirectionalIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } + { + typedef boost::iterator_archetype< + dummyT + , boost::iterator_archetypes::writable_lvalue_iterator_t + , boost::random_access_traversal_tag + > BaseIter; + typedef boost::filter_iterator Iter; + boost::function_requires< boost::Mutable_BidirectionalIteratorConcept >(); + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } +#endif + + // Run-time tests + + dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), + dummyT(3), dummyT(4), dummyT(5) }; + const int N = sizeof(array)/sizeof(dummyT); + + typedef boost::filter_iterator filter_iter; + + boost::bidirectional_readable_iterator_test( + filter_iter(one_or_four(), array, array+N) + , dummyT(1), dummyT(4)); + + BOOST_STATIC_ASSERT( + (!boost::is_convertible< + boost::iterator_traversal::type + , boost::random_access_traversal_tag + >::value + )); + + //# endif + + // On compilers not supporting partial specialization, we can do more type + // deduction with deque iterators than with pointers... unless the library + // is broken ;-( + std::deque array2; + std::copy(array+0, array+N, std::back_inserter(array2)); + boost::bidirectional_readable_iterator_test( + boost::make_filter_iterator(one_or_four(), array2.begin(), array2.end()), + dummyT(1), dummyT(4)); + + boost::bidirectional_readable_iterator_test( + boost::make_filter_iterator(one_or_four(), array2.begin(), array2.end()), + dummyT(1), dummyT(4)); + + boost::bidirectional_readable_iterator_test( + boost::make_filter_iterator( + one_or_four() + , boost::make_reverse_iterator(array2.end()) + , boost::make_reverse_iterator(array2.begin()) + ), + dummyT(4), dummyT(1)); + + boost::bidirectional_readable_iterator_test( + filter_iter(array+0, array+N), + dummyT(1), dummyT(4)); + + boost::bidirectional_readable_iterator_test( + filter_iter(one_or_four(), array, array + N), + dummyT(1), dummyT(4)); + + + return boost::report_errors(); +} diff --git a/libs/iterator/test/function_input_iterator_test.cpp b/libs/iterator/test/function_input_iterator_test.cpp new file mode 100644 index 00000000..f64e9f59 --- /dev/null +++ b/libs/iterator/test/function_input_iterator_test.cpp @@ -0,0 +1,129 @@ +// Copyright 2010 (c) Dean Michael Berris +// 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) + +#include + +#include +#include +#include + +#include + +#if !defined(BOOST_NO_CXX11_DECLTYPE) +// Force boost::result_of use decltype, even on compilers that don't support N3276. +// This enables this test to also verify if the iterator works with lambdas +// on such compilers with this config macro. Note that without the macro result_of +// (and consequently the iterator) is guaranteed to _not_ work, so this case is not +// worth testing anyway. +#define BOOST_RESULT_OF_USE_DECLTYPE +#endif + +#include +#include + +namespace { + +struct ones { + typedef int result_type; + result_type operator() () { + return 1; + } +}; + +int ones_function () { + return 1; +} + +struct counter { + typedef int result_type; + int n; + explicit counter(int n_) : n(n_) { } + result_type operator() () { + return n++; + } +}; + +} // namespace + +using namespace std; + +int main() +{ + // test the iterator with function objects + ones ones_generator; + vector values(10); + generate(values.begin(), values.end(), ones()); + + vector generated; + copy( + boost::make_function_input_iterator(ones_generator, 0), + boost::make_function_input_iterator(ones_generator, 10), + back_inserter(generated) + ); + + BOOST_TEST_ALL_EQ(values.begin(), values.end(), generated.begin(), generated.end()); + + // test the iterator with normal functions + vector().swap(generated); + copy( + boost::make_function_input_iterator(&ones_function, 0), + boost::make_function_input_iterator(&ones_function, 10), + back_inserter(generated) + ); + + BOOST_TEST_ALL_EQ(values.begin(), values.end(), generated.begin(), generated.end()); + + // test the iterator with a reference to a function + vector().swap(generated); + copy( + boost::make_function_input_iterator(ones_function, 0), + boost::make_function_input_iterator(ones_function, 10), + back_inserter(generated) + ); + + BOOST_TEST_ALL_EQ(values.begin(), values.end(), generated.begin(), generated.end()); + + // test the iterator with a stateful function object + counter counter_generator(42); + vector().swap(generated); + copy( + boost::make_function_input_iterator(counter_generator, 0), + boost::make_function_input_iterator(counter_generator, 10), + back_inserter(generated) + ); + + BOOST_TEST_EQ(generated.size(), 10u); + BOOST_TEST_EQ(counter_generator.n, 42 + 10); + for(std::size_t i = 0; i != 10; ++i) + BOOST_TEST_EQ(generated[i], static_cast(42 + i)); + + // Test that incrementing the iterator returns a reference to the iterator type + { + typedef boost::iterators::function_input_iterator function_counter_iterator_t; + function_counter_iterator_t it1(counter_generator, 0); + function_counter_iterator_t it2(++it1); + function_counter_iterator_t it3(it2++); + BOOST_TEST_EQ(*it3, 54); + } + +#if !defined(BOOST_NO_CXX11_LAMBDAS) && !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) \ + && defined(BOOST_RESULT_OF_USE_DECLTYPE) + // test the iterator with lambda expressions + int num = 42; + auto lambda_generator = [&num] { return num++; }; + vector().swap(generated); + copy( + boost::make_function_input_iterator(lambda_generator, 0), + boost::make_function_input_iterator(lambda_generator, 10), + back_inserter(generated) + ); + + BOOST_TEST_EQ(generated.size(), 10u); + for(std::size_t i = 0; i != 10; ++i) + BOOST_TEST_EQ(generated[i], static_cast(42 + i)); +#endif // BOOST_NO_CXX11_LAMBDAS + + return boost::report_errors(); +} diff --git a/libs/iterator/test/function_output_iterator_cf.cpp b/libs/iterator/test/function_output_iterator_cf.cpp new file mode 100644 index 00000000..a3f1d9cf --- /dev/null +++ b/libs/iterator/test/function_output_iterator_cf.cpp @@ -0,0 +1,37 @@ +// Copyright 2022 (c) Andrey Semashev +// 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) + +#include + +namespace { + +struct sum_func +{ + typedef void result_type; + + explicit sum_func(int& n) : m_n(n) {} + result_type operator() (int x) const + { + m_n += x; + } + +private: + int& m_n; +}; + +} // namespace + +int main() +{ + int n = 0; + boost::iterators::function_output_iterator< sum_func > it1 = + boost::iterators::make_function_output_iterator(sum_func(n)); + boost::iterators::function_output_iterator< sum_func > it2 = + boost::iterators::make_function_output_iterator(sum_func(n)); + + *it1 = *it2; + + return 0; +} diff --git a/libs/iterator/test/function_output_iterator_test.cpp b/libs/iterator/test/function_output_iterator_test.cpp new file mode 100644 index 00000000..953a4434 --- /dev/null +++ b/libs/iterator/test/function_output_iterator_test.cpp @@ -0,0 +1,61 @@ +// Copyright 2022 (c) Andrey Semashev +// 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) + +#include + +#include +#include + +namespace { + +struct sum_func +{ + typedef void result_type; + + explicit sum_func(int& n) : m_n(n) {} + result_type operator() (int x) const + { + m_n += x; + } + +private: + int& m_n; +}; + +} // namespace + +int main() +{ + { + int n = 0; + boost::iterators::function_output_iterator< sum_func > it = + boost::iterators::make_function_output_iterator(sum_func(n)); + + *it = 1; + ++it; + *it = 2; + ++it; + *it = 3; + + BOOST_TEST_EQ(n, 6); + } + +#if !defined(BOOST_NO_CXX11_LAMBDAS) && !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) + { + int n = 0; + auto it = boost::iterators::make_function_output_iterator([&n](int x) { n -= x; }); + + *it = 1; + ++it; + *it = 2; + ++it; + *it = 3; + + BOOST_TEST_EQ(n, -6); + } +#endif + + return boost::report_errors(); +} diff --git a/libs/iterator/test/generator_iterator_test.cpp b/libs/iterator/test/generator_iterator_test.cpp new file mode 100644 index 00000000..c31bd66a --- /dev/null +++ b/libs/iterator/test/generator_iterator_test.cpp @@ -0,0 +1,63 @@ +// +// Copyright 2014 Peter Dimov +// +// 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 +// + +#include +#include +#include + +class X +{ +private: + + int v; + +public: + + typedef int result_type; + + X(): v( 0 ) + { + } + + int operator()() + { + return ++v; + } +}; + +template OutputIterator copy_n( InputIterator first, Size n, OutputIterator result ) +{ + while( n-- > 0 ) + { + *result++ = *first++; + } + + return result; +} + +void copy_test() +{ + X x; + boost::generator_iterator in( &x ); + + int const N = 4; + int v[ N ] = { 0 }; + + ::copy_n( in, 4, v ); + + BOOST_TEST_EQ( v[0], 1 ); + BOOST_TEST_EQ( v[1], 2 ); + BOOST_TEST_EQ( v[2], 3 ); + BOOST_TEST_EQ( v[3], 4 ); +} + +int main() +{ + copy_test(); + return boost::report_errors(); +} diff --git a/libs/iterator/test/indirect_iter_member_types.cpp b/libs/iterator/test/indirect_iter_member_types.cpp new file mode 100644 index 00000000..240e664f --- /dev/null +++ b/libs/iterator/test/indirect_iter_member_types.cpp @@ -0,0 +1,87 @@ +// (C) Copyright Jeremy Siek 2004. +// 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) + +// Revision History +// 03 Jan 2004 Jeremy Siek +// First draft. + + +#include +#include + +#include +#include +#include "static_assert_same.hpp" +#include + +struct zow { }; + +struct my_ptr { + typedef zow const element_type; + zow const& operator*() const; +// typedef const zow& reference; +// typedef const zow* pointer; +// typedef void difference_type; +// typedef boost::no_traversal_tag iterator_category; +}; + + +// Borland 5.6.4 and earlier drop const all over the place, so this +// test will fail in the lines marked with (**) + +int main() +{ + { + typedef boost::indirect_iterator Iter; + STATIC_ASSERT_SAME(Iter::value_type, int); + STATIC_ASSERT_SAME(Iter::reference, int&); + STATIC_ASSERT_SAME(Iter::pointer, int*); + STATIC_ASSERT_SAME(Iter::difference_type, std::ptrdiff_t); + + BOOST_STATIC_ASSERT((boost::is_convertible::value)); + BOOST_STATIC_ASSERT((boost::is_convertible::type, + boost::random_access_traversal_tag>::value)); + } + { + typedef boost::indirect_iterator Iter; + STATIC_ASSERT_SAME(Iter::value_type, int); + STATIC_ASSERT_SAME(Iter::reference, const int&); + STATIC_ASSERT_SAME(Iter::pointer, const int*); // (**) + } + { + typedef boost::indirect_iterator Iter; + STATIC_ASSERT_SAME(Iter::value_type, int); + STATIC_ASSERT_SAME(Iter::reference, int&); + STATIC_ASSERT_SAME(Iter::pointer, int*); + } + { + typedef boost::indirect_iterator Iter; + STATIC_ASSERT_SAME(Iter::value_type, int); + STATIC_ASSERT_SAME(Iter::reference, const int&); + STATIC_ASSERT_SAME(Iter::pointer, const int*); // (**) + } + { + typedef boost::indirect_iterator Iter; + STATIC_ASSERT_SAME(Iter::value_type, zow); + STATIC_ASSERT_SAME(Iter::reference, const zow&); // (**) + STATIC_ASSERT_SAME(Iter::pointer, const zow*); // (**) + + STATIC_ASSERT_SAME(Iter::difference_type, std::ptrdiff_t); + + BOOST_STATIC_ASSERT((boost::is_convertible::value)); + BOOST_STATIC_ASSERT((boost::is_convertible::type, + boost::random_access_traversal_tag>::value)); + } + { + typedef boost::indirect_iterator Iter; + STATIC_ASSERT_SAME(Iter::value_type, int); + STATIC_ASSERT_SAME(Iter::reference, long&); + STATIC_ASSERT_SAME(Iter::pointer, int*); + STATIC_ASSERT_SAME(Iter::difference_type, short); + } + return 0; +} diff --git a/libs/iterator/test/indirect_iterator_test.cpp b/libs/iterator/test/indirect_iterator_test.cpp new file mode 100644 index 00000000..a08afa8b --- /dev/null +++ b/libs/iterator/test/indirect_iterator_test.cpp @@ -0,0 +1,220 @@ +// (C) Copyright Jeremy Siek 1999. +// 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) + +// Revision History +// 22 Nov 2002 Thomas Witt +// Added interoperability check. +// 08 Mar 2001 Jeremy Siek +// Moved test of indirect iterator into its own file. It to +// to be in iterator_adaptor_test.cpp. + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#if !defined(__SGI_STL_PORT) \ + && (defined(BOOST_MSVC_STD_ITERATOR) \ + || BOOST_WORKAROUND(_CPPLIB_VER, <= 310) \ + || BOOST_WORKAROUND(__GNUC__, <= 2)) + +// std container random-access iterators don't support mutable/const +// interoperability (but may support const/mutable interop). +# define NO_MUTABLE_CONST_STD_SET_ITERATOR_INTEROPERABILITY + +#endif + + +template struct see_type; +template struct see_val; + +struct my_iterator_tag : public std::random_access_iterator_tag { }; + +using boost::dummyT; + +typedef std::vector storage; +typedef std::vector pointer_ra_container; +typedef std::set iterator_set; + +template +struct indirect_iterator_pair_generator +{ + typedef boost::indirect_iterator iterator; + + typedef boost::indirect_iterator< + typename Container::iterator + , typename iterator::value_type const + > const_iterator; +}; + +void more_indirect_iterator_tests() +{ + storage store(1000); + std::generate(store.begin(), store.end(), rand); + + pointer_ra_container ptr_ra_container; + iterator_set iter_set; + + for (storage::iterator p = store.begin(); p != store.end(); ++p) + { + ptr_ra_container.push_back(&*p); + iter_set.insert(p); + } + + typedef indirect_iterator_pair_generator indirect_ra_container; + + indirect_ra_container::iterator db(ptr_ra_container.begin()); + indirect_ra_container::iterator de(ptr_ra_container.end()); + BOOST_TEST(static_cast(de - db) == store.size()); + BOOST_TEST(db + store.size() == de); + indirect_ra_container::const_iterator dci = db; + + BOOST_TEST(dci == db); + +#ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY + BOOST_TEST(db == dci); +#endif + + BOOST_TEST(dci != de); + BOOST_TEST(dci < de); + BOOST_TEST(dci <= de); + +#ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY + BOOST_TEST(de >= dci); + BOOST_TEST(de > dci); +#endif + + dci = de; + BOOST_TEST(dci == de); + + boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin())); + + *db = 999; + BOOST_TEST(store.front() == 999); + + // Borland C++ is getting very confused about the typedefs here + typedef boost::indirect_iterator indirect_set_iterator; + typedef boost::indirect_iterator< + iterator_set::iterator + , iterator_set::iterator::value_type const + > const_indirect_set_iterator; + + indirect_set_iterator sb(iter_set.begin()); + indirect_set_iterator se(iter_set.end()); + const_indirect_set_iterator sci(iter_set.begin()); + BOOST_TEST(sci == sb); + +# ifndef NO_MUTABLE_CONST_STD_SET_ITERATOR_INTEROPERABILITY + BOOST_TEST(se != sci); +# endif + + BOOST_TEST(sci != se); + sci = se; + BOOST_TEST(sci == se); + + *boost::prior(se) = 888; + BOOST_TEST(store.back() == 888); + BOOST_TEST(std::equal(sb, se, store.begin())); + + boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]); + BOOST_TEST(std::equal(db, de, store.begin())); +} + +// element_type detector; defaults to true so the test passes when +// has_xxx isn't implemented +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_element_type, element_type, true) + +int +main() +{ + dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), + dummyT(3), dummyT(4), dummyT(5) }; + const int N = sizeof(array)/sizeof(dummyT); + +# if BOOST_WORKAROUND(BOOST_MSVC, == 1200) + boost::shared_ptr zz((dummyT*)0); // Why? I don't know, but it suppresses a bad instantiation. +# endif + + typedef std::vector > shared_t; + shared_t shared; + + // Concept checks + { + typedef boost::indirect_iterator iter_t; + + BOOST_STATIC_ASSERT( + has_element_type< + std::iterator_traits::value_type + >::value + ); + + typedef boost::indirect_iterator< + shared_t::iterator + , boost::iterator_value::type const + > c_iter_t; + +# ifndef NO_MUTABLE_CONST_RA_ITERATOR_INTEROPERABILITY + boost::function_requires< boost_concepts::InteroperableIteratorConcept >(); +# endif + } + + // Test indirect_iterator_generator + { + for (int jj = 0; jj < N; ++jj) + shared.push_back(boost::shared_ptr(new dummyT(jj))); + + dummyT* ptr[N]; + for (int k = 0; k < N; ++k) + ptr[k] = array + k; + + typedef boost::indirect_iterator indirect_iterator; + + typedef boost::indirect_iterator + const_indirect_iterator; + + indirect_iterator i(ptr); + boost::random_access_iterator_test(i, N, array); + + boost::random_access_iterator_test( + boost::indirect_iterator(shared.begin()) + , N, array); + + boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array); + + // check operator-> + assert((*i).m_x == i->foo()); + + const_indirect_iterator j(ptr); + boost::random_access_iterator_test(j, N, array); + + dummyT const*const* const_ptr = ptr; + boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array); + + boost::const_nonconst_iterator_test(i, ++j); + + more_indirect_iterator_tests(); + } + return boost::report_errors(); +} diff --git a/libs/iterator/test/interoperable.cpp b/libs/iterator/test/interoperable.cpp new file mode 100644 index 00000000..ad416726 --- /dev/null +++ b/libs/iterator/test/interoperable.cpp @@ -0,0 +1,60 @@ +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to 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) + +#include +#include +#include +#include + +struct mutable_it : boost::iterator_adaptor +{ + typedef boost::iterator_adaptor super_t; + + mutable_it(); + explicit mutable_it(int* p) : super_t(p) {} + + bool equal(mutable_it const& rhs) const + { + return this->base() == rhs.base(); + } +}; + +struct constant_it : boost::iterator_adaptor +{ + typedef boost::iterator_adaptor super_t; + + constant_it(); + explicit constant_it(int* p) : super_t(p) {} + constant_it(mutable_it const& x) : super_t(x.base()) {} + + bool equal(constant_it const& rhs) const + { + return this->base() == rhs.base(); + } +}; + +int main() +{ + int data[] = { 49, 77 }; + + mutable_it i(data); + constant_it j(data + 1); + BOOST_TEST(i < j); + BOOST_TEST(j > i); + BOOST_TEST(i <= j); + BOOST_TEST(j >= i); + BOOST_TEST(j - i == 1); + BOOST_TEST(i - j == -1); + + constant_it k = i; + + BOOST_TEST(!(i < k)); + BOOST_TEST(!(k > i)); + BOOST_TEST(i <= k); + BOOST_TEST(k >= i); + BOOST_TEST(k - i == 0); + BOOST_TEST(i - k == 0); + + return boost::report_errors(); +} diff --git a/libs/iterator/test/interoperable_fail.cpp b/libs/iterator/test/interoperable_fail.cpp new file mode 100644 index 00000000..d6d249a4 --- /dev/null +++ b/libs/iterator/test/interoperable_fail.cpp @@ -0,0 +1,21 @@ +// Copyright Thomas Witt 2003. +// 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) +#include +#include +#include +#include +#include + +int main() +{ + { + typedef boost::reverse_iterator::iterator> rev_iter; + typedef boost::indirect_iterator::iterator> ind_iter; + + ind_iter() == rev_iter(); + } + + return boost::exit_success; +} diff --git a/libs/iterator/test/is_convertible_fail.cpp b/libs/iterator/test/is_convertible_fail.cpp new file mode 100644 index 00000000..757b5c6a --- /dev/null +++ b/libs/iterator/test/is_convertible_fail.cpp @@ -0,0 +1,19 @@ +// +// Copyright (c) Thomas Witt 2002. +// +// Use, modification and distribution is subject to 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) +// +#include +#include + +int main() +{ + typedef boost::reverse_iterator rev_iter1; + typedef boost::reverse_iterator rev_iter2; + + return boost::is_convertible::value + ? boost::exit_failure : boost::exit_success; +} diff --git a/libs/iterator/test/is_iterator.cpp b/libs/iterator/test/is_iterator.cpp new file mode 100644 index 00000000..7d67dda1 --- /dev/null +++ b/libs/iterator/test/is_iterator.cpp @@ -0,0 +1,164 @@ +/* + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * https://www.boost.org/LICENSE_1_0.txt) + * + * Copyright (c) 2023 Andrey Semashev + */ +/*! + * \file is_iterator.cpp + * + * This header contains tests for the \c is_iterator type trait. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +template< typename T > +struct value_iterator +{ + typedef std::input_iterator_tag iterator_category; + typedef T value_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef T& reference; + + value_type operator*() const; +}; + +template< typename T > +struct proxy_iterator +{ + typedef T value_type; + typedef std::output_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef T& reference; + + struct proxy + { + operator value_type&() const; + proxy& operator=(value_type) const; + }; + + proxy operator*() const; +}; + +template< typename T > +struct lvalue_iterator +{ + typedef T value_type; + typedef T& reference; + typedef T difference_type; + typedef std::input_iterator_tag iterator_category; + typedef T* pointer; + + T& operator*() const; + lvalue_iterator& operator++(); + lvalue_iterator operator++(int); +}; + +template< typename T > +struct constant_lvalue_iterator +{ + typedef T value_type; + typedef T const& reference; + typedef T difference_type; + typedef std::input_iterator_tag iterator_category; + typedef T const* pointer; + + T const& operator*() const; + constant_lvalue_iterator& operator++(); + constant_lvalue_iterator operator++(int); +}; + +template< typename Iterator > +class adapted_iterator : + public boost::iterators::iterator_adaptor< adapted_iterator< Iterator >, Iterator > +{ + friend class iterator_core_access; + +private: + typedef boost::iterators::iterator_adaptor< adapted_iterator< Iterator >, Iterator > base_type; + +private: + typename base_type::reference dereference() const; + void increment(); + void decrement(); + void advance(typename base_type::difference_type n); + template< typename OtherIterator > + typename base_type::difference_type distance_to(adapted_iterator< OtherIterator > const& y) const; +}; + +struct complete {}; +struct incomplete; + +int main() +{ + BOOST_TEST(boost::iterators::is_iterator< int* >::value); + BOOST_TEST(boost::iterators::is_iterator< const int* >::value); + BOOST_TEST(boost::iterators::is_iterator< complete* >::value); + BOOST_TEST(boost::iterators::is_iterator< std::reverse_iterator< int* > >::value); + BOOST_TEST(boost::iterators::is_iterator< std::reverse_iterator< complete* > >::value); + BOOST_TEST(boost::iterators::is_iterator< adapted_iterator< int* > >::value); + + BOOST_TEST(boost::iterators::is_iterator< std::string::iterator >::value); + BOOST_TEST(boost::iterators::is_iterator< std::string::const_iterator >::value); + BOOST_TEST(boost::iterators::is_iterator< std::string::reverse_iterator >::value); + BOOST_TEST(boost::iterators::is_iterator< std::string::const_reverse_iterator >::value); + + BOOST_TEST(boost::iterators::is_iterator< std::list< int >::iterator >::value); + BOOST_TEST(boost::iterators::is_iterator< std::list< int >::const_iterator >::value); + BOOST_TEST(boost::iterators::is_iterator< std::list< int >::reverse_iterator >::value); + BOOST_TEST(boost::iterators::is_iterator< std::list< int >::const_reverse_iterator >::value); + + BOOST_TEST(boost::iterators::is_iterator< std::vector< int >::iterator >::value); + BOOST_TEST(boost::iterators::is_iterator< std::vector< int >::const_iterator >::value); + BOOST_TEST(boost::iterators::is_iterator< std::vector< int >::reverse_iterator >::value); + BOOST_TEST(boost::iterators::is_iterator< std::vector< int >::const_reverse_iterator >::value); + + BOOST_TEST(boost::iterators::is_iterator< std::insert_iterator< std::vector< int > > >::value); + BOOST_TEST(boost::iterators::is_iterator< std::back_insert_iterator< std::vector< int > > >::value); + BOOST_TEST(boost::iterators::is_iterator< std::front_insert_iterator< std::vector< int > > >::value); + BOOST_TEST(boost::iterators::is_iterator< std::istream_iterator< int > >::value); + BOOST_TEST(boost::iterators::is_iterator< std::ostream_iterator< int > >::value); + BOOST_TEST(boost::iterators::is_iterator< std::istreambuf_iterator< char > >::value); + BOOST_TEST(boost::iterators::is_iterator< std::ostreambuf_iterator< char > >::value); + + BOOST_TEST(!boost::iterators::is_iterator< int >::value); + BOOST_TEST(!boost::iterators::is_iterator< complete >::value); + BOOST_TEST(!boost::iterators::is_iterator< void >::value); + BOOST_TEST(!boost::iterators::is_iterator< const void >::value); + BOOST_TEST(!boost::iterators::is_iterator< void* >::value); +#if defined(BOOST_TT_HAS_WORKING_IS_COMPLETE) + BOOST_TEST(!boost::iterators::is_iterator< incomplete >::value); + BOOST_TEST(!boost::iterators::is_iterator< incomplete* >::value); +#endif + BOOST_TEST(!boost::iterators::is_iterator< int (int) >::value); + BOOST_TEST(!boost::iterators::is_iterator< int (*)(int) >::value); + BOOST_TEST(!boost::iterators::is_iterator< int complete::* >::value); + BOOST_TEST(!boost::iterators::is_iterator< int (complete::*)(int) >::value); + BOOST_TEST(!boost::iterators::is_iterator< int (complete::*)(int) const >::value); +#if defined(__cpp_noexcept_function_type) && (__cpp_noexcept_function_type >= 201510L) + BOOST_TEST(!boost::iterators::is_iterator< int (*)(int) noexcept >::value); + BOOST_TEST(!boost::iterators::is_iterator< int (complete::*)(int) noexcept >::value); + BOOST_TEST(!boost::iterators::is_iterator< int (complete::*)(int) const noexcept >::value); +#endif + BOOST_TEST(!boost::iterators::is_iterator< int[] >::value); + BOOST_TEST(!boost::iterators::is_iterator< int[10] >::value); + BOOST_TEST(!boost::iterators::is_iterator< int*[] >::value); + BOOST_TEST(!boost::iterators::is_iterator< int*[10] >::value); + + BOOST_TEST(!boost::iterators::is_iterator< int& >::value); + BOOST_TEST(!boost::iterators::is_iterator< int*& >::value); + BOOST_TEST(!boost::iterators::is_iterator< int (&)(int) >::value); + BOOST_TEST(!boost::iterators::is_iterator< int (&)[10] >::value); + + return boost::report_errors(); +} diff --git a/libs/iterator/test/is_lvalue_iterator.cpp b/libs/iterator/test/is_lvalue_iterator.cpp new file mode 100644 index 00000000..16de0141 --- /dev/null +++ b/libs/iterator/test/is_lvalue_iterator.cpp @@ -0,0 +1,148 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to 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) + +#include +#include +#include +#include // std::ptrdiff_t +#include +#include +#include + +// Last, for BOOST_NO_LVALUE_RETURN_DETECTION +#include + +struct v +{ + v(); + ~v(); +}; + + +struct value_iterator +{ + typedef std::input_iterator_tag iterator_category; + typedef v value_type; + typedef std::ptrdiff_t difference_type; + typedef v* pointer; + typedef v& reference; + + v operator*() const; +}; + +struct noncopyable_iterator +{ + typedef std::forward_iterator_tag iterator_category; + typedef boost::noncopyable value_type; + typedef std::ptrdiff_t difference_type; + typedef boost::noncopyable* pointer; + typedef boost::noncopyable& reference; + + boost::noncopyable const& operator*() const; +}; + +template +struct proxy_iterator +{ + typedef T value_type; + typedef std::output_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef T& reference; + + struct proxy + { + operator value_type&() const; + proxy& operator=(value_type) const; + }; + + proxy operator*() const; +}; + +template +struct lvalue_iterator +{ + typedef T value_type; + typedef T& reference; + typedef T difference_type; + typedef std::input_iterator_tag iterator_category; + typedef T* pointer; + + T& operator*() const; + lvalue_iterator& operator++(); + lvalue_iterator operator++(int); +}; + +template +struct constant_lvalue_iterator +{ + typedef T value_type; + typedef T const& reference; + typedef T difference_type; + typedef std::input_iterator_tag iterator_category; + typedef T const* pointer; + + T const& operator*() const; + constant_lvalue_iterator& operator++(); + constant_lvalue_iterator operator++(int); +}; + + +int main() +{ + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::iterator>::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::const_iterator>::value); + BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator > >::value); + BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator >::value); +#ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(!boost::is_lvalue_iterator::value); +#endif + // Make sure inaccessible copy constructor doesn't prevent + // reference binding + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value); + + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + + + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator >::value); + + + + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator::iterator>::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator::const_iterator>::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator > >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); +#ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator::value); +#endif + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator::value); + + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator >::value); +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator >::value); +#endif + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator >::value); + + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + BOOST_STATIC_ASSERT(!boost::is_non_const_lvalue_iterator >::value); + + return 0; +} diff --git a/libs/iterator/test/is_readable_iterator.cpp b/libs/iterator/test/is_readable_iterator.cpp new file mode 100644 index 00000000..1d33a64a --- /dev/null +++ b/libs/iterator/test/is_readable_iterator.cpp @@ -0,0 +1,96 @@ +// Copyright David Abrahams 2003. Use, modification and distribution is +// subject to 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) + +#include +#include +#include +#include // std::ptrdiff_t +#include +#include +#include + +// Last, for BOOST_NO_LVALUE_RETURN_DETECTION +#include + +struct v +{ + v(); + ~v(); +}; + + +struct value_iterator +{ + typedef std::input_iterator_tag iterator_category; + typedef v value_type; + typedef std::ptrdiff_t difference_type; + typedef v* pointer; + typedef v& reference; + + v operator*() const; +}; + +struct noncopyable_iterator +{ + typedef std::forward_iterator_tag iterator_category; + typedef boost::noncopyable value_type; + typedef std::ptrdiff_t difference_type; + typedef boost::noncopyable* pointer; + typedef boost::noncopyable& reference; + + boost::noncopyable const& operator*() const; +}; + +struct proxy_iterator +{ + typedef std::output_iterator_tag iterator_category; + typedef v value_type; + typedef std::ptrdiff_t difference_type; + typedef v* pointer; + typedef v& reference; + + struct proxy + { + operator v&(); + proxy& operator=(v) const; + }; + + proxy operator*() const; +}; + +struct proxy_iterator2 +{ + typedef std::output_iterator_tag iterator_category; + typedef v value_type; + typedef std::ptrdiff_t difference_type; + typedef v* pointer; + typedef v& reference; + + struct proxy + { + proxy& operator=(v) const; + }; + + proxy operator*() const; +}; + + +int main() +{ + BOOST_STATIC_ASSERT(boost::is_readable_iterator::value); + BOOST_STATIC_ASSERT(boost::is_readable_iterator::value); + BOOST_STATIC_ASSERT(boost::is_readable_iterator::iterator>::value); + BOOST_STATIC_ASSERT(boost::is_readable_iterator::const_iterator>::value); + BOOST_STATIC_ASSERT(!boost::is_readable_iterator > >::value); + BOOST_STATIC_ASSERT(!boost::is_readable_iterator >::value); + BOOST_STATIC_ASSERT(boost::is_readable_iterator::value); + BOOST_STATIC_ASSERT(!boost::is_readable_iterator::value); + BOOST_STATIC_ASSERT(boost::is_readable_iterator::value); + + // Make sure inaccessible copy constructor doesn't prevent + // readability + BOOST_STATIC_ASSERT(boost::is_readable_iterator::value); + + return 0; +} diff --git a/libs/iterator/test/iter_archetype_default_ctor.cpp b/libs/iterator/test/iter_archetype_default_ctor.cpp new file mode 100644 index 00000000..7936bdd2 --- /dev/null +++ b/libs/iterator/test/iter_archetype_default_ctor.cpp @@ -0,0 +1,21 @@ +// +// Copyright Thomas Witt 2004. +// 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) +// +#include + + +int main() +{ + typedef boost::iterator_archetype< + int + , boost::iterator_archetypes::readable_iterator_t + , boost::single_pass_traversal_tag + > iter; + + // single_pass_traversal iterators are not required to be + // default constructible + iter it; +} diff --git a/libs/iterator/test/iterator_adaptor_cc.cpp b/libs/iterator/test/iterator_adaptor_cc.cpp new file mode 100644 index 00000000..2ea75825 --- /dev/null +++ b/libs/iterator/test/iterator_adaptor_cc.cpp @@ -0,0 +1,46 @@ +// Copyright (C) 2004 Jeremy Siek +// 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) + +#include +#include +#include +#include +#include + +int main() +{ + { + typedef boost::reverse_iterator rev_iter; + typedef boost::reverse_iterator c_rev_iter; + + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< boost_concepts::RandomAccessTraversalConcept >(); + boost::function_requires< boost::RandomAccessIteratorConcept >(); + boost::function_requires< boost_concepts::InteroperableIteratorConcept >(); + } + + // Many compilers' builtin container iterators don't interoperate well, though + // STLport fixes that problem. +#if defined(__SGI_STL_PORT) \ + || !BOOST_WORKAROUND(__GNUC__, <= 2) \ + && !(BOOST_WORKAROUND(__GNUC__, == 3) && BOOST_WORKAROUND(__GNUC_MINOR__, <= 1)) \ + && !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) \ + && !BOOST_WORKAROUND(__LIBCOMO_VERSION__, BOOST_TESTED_AT(29)) \ + && !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 1) + { + typedef boost::reverse_iterator::iterator> rev_iter; + typedef boost::reverse_iterator::const_iterator> c_rev_iter; + + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + boost::function_requires< boost::BidirectionalIteratorConcept >(); + boost::function_requires< boost_concepts::InteroperableIteratorConcept >(); + } +#endif + + return boost::exit_success; +} diff --git a/libs/iterator/test/iterator_adaptor_test.cpp b/libs/iterator/test/iterator_adaptor_test.cpp new file mode 100644 index 00000000..4b37c14b --- /dev/null +++ b/libs/iterator/test/iterator_adaptor_test.cpp @@ -0,0 +1,304 @@ +// (C) Copyright Thomas Witt 2003. +// 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) + +// See http://www.boost.org for most recent version including documentation. + +#include +#include + +#include +#include +#include + +#include +#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) +# include +# include +#endif +#include + +# include + +#include +#include +#include +#include +#include + +#include "static_assert_same.hpp" + +#include + +using boost::dummyT; + +typedef std::deque storage; +typedef std::deque pointer_deque; +typedef std::set iterator_set; + +template struct foo; + +void blah(int) { } + +struct my_gen +{ + typedef int result_type; + my_gen() : n(0) { } + int operator()() { return ++n; } + int n; +}; + +template +struct ptr_iterator + : boost::iterator_adaptor< + ptr_iterator + , V* + , V + , boost::random_access_traversal_tag +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) + , V& +#endif + > +{ +private: + typedef boost::iterator_adaptor< + ptr_iterator + , V* + , V + , boost::random_access_traversal_tag +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) + , V& +#endif + > super_t; + +public: + ptr_iterator() { } + ptr_iterator(V* d) : super_t(d) { } + + template + ptr_iterator( + const ptr_iterator& x + , typename boost::enable_if_convertible::type* = 0 + ) + : super_t(x.base()) + {} +}; + +// Non-functional iterator for category modification checking +template +struct modify_traversal + : boost::iterator_adaptor< + modify_traversal + , Iter + , boost::use_default + , Traversal + > +{}; + +template +struct fwd_iterator + : boost::iterator_adaptor< + fwd_iterator + , boost::forward_iterator_archetype + > +{ +private: + typedef boost::iterator_adaptor< + fwd_iterator + , boost::forward_iterator_archetype + > super_t; + +public: + fwd_iterator() { } + fwd_iterator(boost::forward_iterator_archetype d) : super_t(d) { } +}; + +template +struct in_iterator + : boost::iterator_adaptor< + in_iterator + , boost::input_iterator_archetype_no_proxy + > +{ +private: + typedef boost::iterator_adaptor< + in_iterator + , boost::input_iterator_archetype_no_proxy + > super_t; + +public: + in_iterator() { } + in_iterator(boost::input_iterator_archetype_no_proxy d) : super_t(d) { } +}; + +template +struct constant_iterator + : boost::iterator_adaptor< + constant_iterator + , Iter + , typename std::iterator_traits::value_type const + > +{ + typedef boost::iterator_adaptor< + constant_iterator + , Iter + , typename std::iterator_traits::value_type const + > base_t; + + constant_iterator() {} + constant_iterator(Iter it) + : base_t(it) {} +}; + +char (& traversal2(boost::incrementable_traversal_tag) )[1]; +char (& traversal2(boost::single_pass_traversal_tag ) )[2]; +char (& traversal2(boost::forward_traversal_tag ) )[3]; +char (& traversal2(boost::bidirectional_traversal_tag) )[4]; +char (& traversal2(boost::random_access_traversal_tag) )[5]; + +template +struct traversal3 +{ + static typename boost::iterator_category_to_traversal::type x; + BOOST_STATIC_CONSTANT(std::size_t, value = sizeof(traversal2(x))); + typedef char (&type)[value]; +}; + +template +typename traversal3::type traversal(Cat); + +template +int static_assert_traversal(Iter* = 0, Trav* = 0) +{ + typedef typename boost::iterator_category_to_traversal< + BOOST_DEDUCED_TYPENAME Iter::iterator_category + >::type t2; + + return static_assert_same::value; +} + +int +main() +{ + dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), + dummyT(3), dummyT(4), dummyT(5) }; + const int N = sizeof(array)/sizeof(dummyT); + + // sanity check, if this doesn't pass the test is buggy + boost::random_access_iterator_test(array, N, array); + + // Test the iterator_adaptor + { + ptr_iterator i(array); + boost::random_access_iterator_test(i, N, array); + + ptr_iterator j(array); + boost::random_access_iterator_test(j, N, array); + boost::const_nonconst_iterator_test(i, ++j); + } + + int test; + // Test the iterator_traits + { + // Test computation of defaults + typedef ptr_iterator Iter1; + // don't use std::iterator_traits here to avoid VC++ problems + test = static_assert_same::value; + test = static_assert_same::value; + test = static_assert_same::value; + test = static_assert_same::value; +#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + BOOST_STATIC_ASSERT((boost::is_convertible::value)); +#endif + } + + { + // Test computation of default when the Value is const + typedef ptr_iterator Iter1; + test = static_assert_same::value; + test = static_assert_same::value; + +#if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) + BOOST_STATIC_ASSERT(boost::is_readable_iterator::value); +# ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value); +# endif +#endif + +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) // borland drops constness + test = static_assert_same::value; +#endif + } + + { + // Test constant iterator idiom + typedef ptr_iterator BaseIter; + typedef constant_iterator Iter; + + test = static_assert_same::value; + test = static_assert_same::value; +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) // borland drops constness + test = static_assert_same::value; +#endif + +#ifndef BOOST_NO_LVALUE_RETURN_DETECTION + BOOST_STATIC_ASSERT(boost::is_non_const_lvalue_iterator::value); + BOOST_STATIC_ASSERT(boost::is_lvalue_iterator::value); +#endif + + typedef modify_traversal IncrementableIter; + + static_assert_traversal(); + static_assert_traversal(); + } + + // Test the iterator_adaptor + { + ptr_iterator i(array); + boost::random_access_iterator_test(i, N, array); + + ptr_iterator j(array); + boost::random_access_iterator_test(j, N, array); + boost::const_nonconst_iterator_test(i, ++j); + } + + // check operator-> with a forward iterator + { + boost::forward_iterator_archetype forward_iter; + + typedef fwd_iterator adaptor_type; + + adaptor_type i(forward_iter); + int zero = 0; + if (zero) // don't do this, just make sure it compiles + BOOST_TEST((*i).m_x == i->foo()); + } + + // check operator-> with an input iterator + { + boost::input_iterator_archetype_no_proxy input_iter; + typedef in_iterator adaptor_type; + adaptor_type i(input_iter); + int zero = 0; + if (zero) // don't do this, just make sure it compiles + BOOST_TEST((*i).m_x == i->foo()); + } + + // check that base_type is correct + { + // Test constant iterator idiom + typedef ptr_iterator BaseIter; + + test = static_assert_same::value; + test = static_assert_same::base_type,BaseIter>::value; + + typedef modify_traversal IncrementableIter; + + test = static_assert_same::value; + } + + std::cout << "test successful " << std::endl; + (void)test; + return boost::report_errors(); +} diff --git a/libs/iterator/test/iterator_archetype_cc.cpp b/libs/iterator/test/iterator_archetype_cc.cpp new file mode 100644 index 00000000..98d32ae7 --- /dev/null +++ b/libs/iterator/test/iterator_archetype_cc.cpp @@ -0,0 +1,61 @@ +// +// Copyright Thomas Witt 2003. +// 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) +// +#include +#include +#include +#include +#include + +int main() +{ + { + typedef boost::iterator_archetype< + int + , boost::iterator_archetypes::readable_iterator_t + , boost::random_access_traversal_tag + > iter; + + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::RandomAccessTraversalConcept >(); + } + { + typedef boost::iterator_archetype< + int + , boost::iterator_archetypes::readable_writable_iterator_t + , boost::random_access_traversal_tag + > iter; + + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::RandomAccessTraversalConcept >(); + } + { + typedef boost::iterator_archetype< + const int // I don't like adding const to Value. It is redundant. -JGS + , boost::iterator_archetypes::readable_lvalue_iterator_t + , boost::random_access_traversal_tag + > iter; + + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< boost_concepts::RandomAccessTraversalConcept >(); + } + { + typedef boost::iterator_archetype< + int + , boost::iterator_archetypes::writable_lvalue_iterator_t + , boost::random_access_traversal_tag + > iter; + + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< boost_concepts::RandomAccessTraversalConcept >(); + } + + return boost::exit_success; +} + diff --git a/libs/iterator/test/iterator_facade.cpp b/libs/iterator/test/iterator_facade.cpp new file mode 100644 index 00000000..7351dd3f --- /dev/null +++ b/libs/iterator/test/iterator_facade.cpp @@ -0,0 +1,263 @@ +// Copyright David Abrahams 2004. 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) + +// This is really an incomplete test; should be fleshed out. + +#include +#include + +#include +#include +#include + +// This is a really, really limited test so far. All we're doing +// right now is checking that the postfix++ proxy for single-pass +// iterators works properly. +template +class counter_iterator + : public boost::iterator_facade< + counter_iterator + , int const + , boost::single_pass_traversal_tag + , Ref + > +{ + public: + counter_iterator() {} + counter_iterator(int* state) : state(state) {} + + void increment() + { + ++*state; + } + + Ref + dereference() const + { + return *state; + } + + bool equal(counter_iterator const& y) const + { + return *this->state == *y.state; + } + + int* state; +}; + +struct proxy +{ + proxy(int& x) : state(x) {} + + operator int const&() const + { + return state; + } + + int& operator=(int x) { state = x; return state; } + + int& state; +}; + +struct value +{ + int increment_count; + int private_mutator_count; + int& shared_mutator_count; + + explicit value(int& shared_mutator_count) : + increment_count(0), + private_mutator_count(0), + shared_mutator_count(shared_mutator_count) + { + } + + // non-const member function + void mutator() + { + ++private_mutator_count; + ++shared_mutator_count; + } +}; + +struct input_iter + : boost::iterator_facade< + input_iter + , value + , boost::single_pass_traversal_tag + , value + > +{ + public: + explicit input_iter(value& val) : state(&val) {} + + void increment() + { + ++(state->increment_count); + } + value + dereference() const + { + return *state; + } + + bool equal(input_iter const&) const + { + return false; + } + + private: + value* state; +}; + +template +struct wrapper +{ + T m_x; + explicit wrapper(typename boost::call_traits::param_type x) + : m_x(x) + { } + template + wrapper(const wrapper& other, + typename boost::enable_if< boost::is_convertible >::type* = 0) + : m_x(other.m_x) + { } +}; + +struct iterator_with_proxy_reference + : boost::iterator_facade< + iterator_with_proxy_reference + , wrapper + , boost::incrementable_traversal_tag + , wrapper + > +{ + int& m_x; + explicit iterator_with_proxy_reference(int& x) + : m_x(x) + { } + + void increment() + { } + wrapper dereference() const + { return wrapper(m_x); } +}; + +template +void same_type(U const&) +{ BOOST_STATIC_ASSERT((boost::is_same::value)); } + +template +struct abstract_iterator + : boost::iterator_facade< + abstract_iterator + , A & + // In order to be value type as a reference, traversal category has + // to satisfy least forward traversal. + , boost::forward_traversal_tag + , A & + > +{ + abstract_iterator(I iter) : iter(iter) {} + + void increment() + { ++iter; } + + A & dereference() const + { return *iter; } + + bool equal(abstract_iterator const& y) const + { return iter == y.iter; } + + I iter; +}; + +struct base +{ + virtual void assign(const base &) = 0; + virtual bool equal(const base &) const = 0; +}; + +struct derived : base +{ + derived(int state) : state(state) { } + derived(const derived &d) : state(d.state) { } + derived(const base &b) { derived::assign(b); } + + virtual void assign(const base &b) + { + state = dynamic_cast(b).state; + } + + virtual bool equal(const base &b) const + { + return state == dynamic_cast(b).state; + } + + int state; +}; + +inline bool operator==(const base &lhs, const base &rhs) +{ + return lhs.equal(rhs); +} + +int main() +{ + { + int state = 0; + boost::readable_iterator_test(counter_iterator(&state), 0); + state = 3; + boost::readable_iterator_test(counter_iterator(&state), 3); + boost::writable_iterator_test(counter_iterator(&state), 9, 7); + BOOST_TEST(state == 8); + } + + { + // test for a fix to http://tinyurl.com/zuohe + // These two lines should be equivalent (and both compile) + int shared_mutator_count = 0; + value val(shared_mutator_count); + input_iter p(val); + (*p).mutator(); + p->mutator(); + BOOST_TEST_EQ(val.increment_count, 0); + BOOST_TEST_EQ(val.private_mutator_count, 0); // mutator() should be invoked on an object returned by value + BOOST_TEST_EQ(shared_mutator_count, 2); + + same_type(p.operator->()); + } + + { + // Test that accessing dereferenced value of a post-incremented iterator works + int shared_mutator_count = 0; + value val(shared_mutator_count); + input_iter p(val); + (*p++).mutator(); + (p++)->mutator(); + BOOST_TEST_EQ(val.increment_count, 2); + BOOST_TEST_EQ(val.private_mutator_count, 0); // mutator() should be invoked on an object returned by value + BOOST_TEST_EQ(shared_mutator_count, 2); + } + + { + int x = 0; + iterator_with_proxy_reference i(x); + BOOST_TEST(x == 0); + BOOST_TEST(i.m_x == 0); + ++(*i).m_x; + BOOST_TEST(x == 1); + BOOST_TEST(i.m_x == 1); + ++i->m_x; + BOOST_TEST(x == 2); + BOOST_TEST(i.m_x == 2); + } + + { + derived d(1); + boost::readable_iterator_test(abstract_iterator(&d), derived(1)); + } + + return boost::report_errors(); +} diff --git a/libs/iterator/test/iterator_traits_test.cpp b/libs/iterator/test/iterator_traits_test.cpp new file mode 100644 index 00000000..40da0497 --- /dev/null +++ b/libs/iterator/test/iterator_traits_test.cpp @@ -0,0 +1,232 @@ +// (C) Copyright David Abrahams 2002. +// 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) + +// See http://www.boost.org for most recent version including documentation. + +// Revision History +// 04 Mar 2001 Patches for Intel C++ (Dave Abrahams) +// 19 Feb 2001 Take advantage of improved iterator_traits to do more tests +// on MSVC. Reordered some #ifdefs for coherency. +// (David Abrahams) +// 13 Feb 2001 Test new VC6 workarounds (David Abrahams) +// 11 Feb 2001 Final fixes for Borland (David Abrahams) +// 11 Feb 2001 Some fixes for Borland get it closer on that compiler +// (David Abrahams) +// 07 Feb 2001 More comprehensive testing; factored out static tests for +// better reuse (David Abrahams) +// 21 Jan 2001 Quick fix to my_iterator, which wasn't returning a +// reference type from operator* (David Abrahams) +// 19 Jan 2001 Initial version with iterator operators (David Abrahams) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// A UDT for which we can specialize std::iterator_traits on +// compilers which don't support partial specialization. There's no +// other reasonable way to test pointers on those compilers. +struct element {}; + +// An iterator for which we can get traits. +struct my_iterator1 + : boost::forward_iterator_helper +{ + my_iterator1(const char* p) : m_p(p) {} + + bool operator==(const my_iterator1& rhs) const + { return this->m_p == rhs.m_p; } + + my_iterator1& operator++() { ++this->m_p; return *this; } + const char& operator*() { return *m_p; } + private: + const char* m_p; +}; + +// Used to prove that we don't require std::iterator<> in the hierarchy under +// MSVC6, and that we can compute all the traits for a standard-conforming UDT +// iterator. +struct my_iterator2 + : boost::equality_comparable > > +{ + typedef char value_type; + typedef long difference_type; + typedef const char* pointer; + typedef const char& reference; + typedef std::forward_iterator_tag iterator_category; + + my_iterator2(const char* p) : m_p(p) {} + + bool operator==(const my_iterator2& rhs) const + { return this->m_p == rhs.m_p; } + + my_iterator2& operator++() { ++this->m_p; return *this; } + const char& operator*() { return *m_p; } + private: + const char* m_p; +}; + +// Used to prove that we're not overly confused by the existence of +// std::iterator<> in the hierarchy under MSVC6 - we should find that +// std::iterator_traits::difference_type is int. +struct my_iterator3 : my_iterator1 +{ + typedef int difference_type; + my_iterator3(const char* p) + : my_iterator1(p) {} +}; + +// +// Assertion tools. Used instead of BOOST_STATIC_ASSERT because that +// doesn't give us a nice stack backtrace +// +template struct assertion; + +template <> struct assertion +{ + typedef char type; +}; + +template +struct assert_same + : assertion<(::boost::is_same::value)> +{ +}; + + +// Iterator tests +template +struct non_portable_tests +{ + typedef typename std::iterator_traits::pointer test_pt; + typedef typename std::iterator_traits::reference test_rt; + typedef typename assert_same::type a1; + typedef typename assert_same::type a2; +}; + +template +struct portable_tests +{ + typedef typename std::iterator_traits::difference_type test_dt; + typedef typename std::iterator_traits::iterator_category test_cat; + typedef typename assert_same::type a1; + typedef typename assert_same::type a2; +}; + +// Test iterator_traits +template +struct input_iterator_test + : portable_tests +{ + typedef typename std::iterator_traits::value_type test_vt; + typedef typename assert_same::type a1; +}; + +template +struct non_pointer_test + : input_iterator_test + , non_portable_tests +{ +}; + +template +struct maybe_pointer_test + : portable_tests + , non_portable_tests +{ +}; + +input_iterator_test, int, std::ptrdiff_t, int*, int&, std::input_iterator_tag> + istream_iterator_test; + +// C++20 changed ostream_iterator::difference_type to ptrdiff_t. +// Note: gcc 10.1 defines __cplusplus to a value less than 202002L, but greater than 201703L in C++20 mode. +#if (__cplusplus > 201703L && ( \ + (defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION >= 100100) || \ + (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 12000) \ + )) || \ + (defined(_MSVC_LANG) && _MSVC_LANG > 201703L && _MSVC_STL_UPDATE >= 202010L) +#define BOOST_ITERATOR_CXX20_OSTREAM_ITERATOR +#endif + +#if BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x564) && !defined(__SGI_STL_PORT) +typedef ::std::char_traits::off_type distance; +non_pointer_test,int, + distance,int*,int&,std::output_iterator_tag> ostream_iterator_test; +#elif defined(BOOST_MSVC_STD_ITERATOR) +non_pointer_test, + int, void, int*, int&, std::output_iterator_tag> + ostream_iterator_test; +#elif BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(70190006)) +non_pointer_test, + int, long, int*, int&, std::output_iterator_tag> + ostream_iterator_test; +#elif defined(BOOST_ITERATOR_CXX20_OSTREAM_ITERATOR) +non_pointer_test, + void, std::ptrdiff_t, void, void, std::output_iterator_tag> + ostream_iterator_test; +#else +non_pointer_test, + void, void, void, void, std::output_iterator_tag> + ostream_iterator_test; +#endif + + +#ifdef __KCC + typedef long std_list_diff_type; +#else + typedef std::ptrdiff_t std_list_diff_type; +#endif + +non_pointer_test::iterator, int, std_list_diff_type, int*, int&, std::bidirectional_iterator_tag> + list_iterator_test; + +maybe_pointer_test::iterator, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag> + vector_iterator_test; + +maybe_pointer_test + int_pointer_test; + +non_pointer_test + my_iterator1_test; + +non_pointer_test + my_iterator2_test; + +non_pointer_test + my_iterator3_test; + +int main() +{ + char chars[100]; + int ints[100]; + + for (int length = 3; length < 100; length += length / 3) + { + std::list l(length); + BOOST_TEST(std::distance(l.begin(), l.end()) == length); + + std::vector v(length); + BOOST_TEST(std::distance(v.begin(), v.end()) == length); + + BOOST_TEST(std::distance(&ints[0], ints + length) == length); + BOOST_TEST(std::distance(my_iterator1(chars), my_iterator1(chars + length)) == length); + BOOST_TEST(std::distance(my_iterator2(chars), my_iterator2(chars + length)) == length); + BOOST_TEST(std::distance(my_iterator3(chars), my_iterator3(chars + length)) == length); + } + return boost::report_errors(); +} diff --git a/libs/iterator/test/lvalue_concept_fail.cpp b/libs/iterator/test/lvalue_concept_fail.cpp new file mode 100644 index 00000000..735bb4ab --- /dev/null +++ b/libs/iterator/test/lvalue_concept_fail.cpp @@ -0,0 +1,20 @@ +// Copyright (C) 2004 Jeremy Siek +// 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) + +#include +#include +#include + +int main() +{ + typedef boost::iterator_archetype< + int + , boost::iterator_archetypes::readable_iterator_t + , boost::single_pass_traversal_tag + > Iter; + boost::function_requires< + boost_concepts::LvalueIteratorConcept >(); + return boost::exit_success; +} diff --git a/libs/iterator/test/minimum_category.cpp b/libs/iterator/test/minimum_category.cpp new file mode 100644 index 00000000..3f89d6c6 --- /dev/null +++ b/libs/iterator/test/minimum_category.cpp @@ -0,0 +1,22 @@ +// Copyright Andrey Semashev 2014. +// +// Use, modification and distribution is subject to +// 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) + +#include +#include +#include +#include + +using boost::is_same; +using boost::iterators::minimum_category; + +int main(int, char*[]) +{ + BOOST_TEST_TRAIT_TRUE((is_same::type, std::forward_iterator_tag>)); + BOOST_TEST_TRAIT_TRUE((is_same::type, std::forward_iterator_tag>)); + BOOST_TEST_TRAIT_TRUE((is_same::type, std::random_access_iterator_tag>)); + + return boost::report_errors(); +} diff --git a/libs/iterator/test/minimum_category_compile_fail.cpp b/libs/iterator/test/minimum_category_compile_fail.cpp new file mode 100644 index 00000000..736cc200 --- /dev/null +++ b/libs/iterator/test/minimum_category_compile_fail.cpp @@ -0,0 +1,19 @@ +// Copyright Andrey Semashev 2014. +// +// Use, modification and distribution is subject to +// 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) + +#include + +using boost::iterators::minimum_category; + +struct A {}; +struct B {}; + +int main(int, char*[]) +{ + minimum_category::type cat; + + return 0; +} diff --git a/libs/iterator/test/next_prior_test.cpp b/libs/iterator/test/next_prior_test.cpp new file mode 100644 index 00000000..c8643f77 --- /dev/null +++ b/libs/iterator/test/next_prior_test.cpp @@ -0,0 +1,112 @@ +// Boost test program for next() and prior() utilities. + +// Copyright 2003 Daniel Walker. Use, modification, and distribution +// are subject to the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt.) + +// See http://www.boost.org/libs/utility for documentation. + +// Revision History 13 Dec 2003 Initial Version (Daniel Walker) + +// next() and prior() are replacements for operator+ and operator- for +// non-random-access iterators. The semantics of these operators are +// such that after executing j = i + n, std::distance(i, j) equals +// n. Tests are provided to ensure next() has the same +// result. Parallel tests are provided for prior(). The tests call +// next() and prior() several times. next() and prior() are very +// simple functions, though, and it would be very strange if these +// tests were to fail. + +#include + +#include +#include + +#include + +template +bool plus_one_test(RandomAccessIterator first, RandomAccessIterator last, ForwardIterator first2) +{ + RandomAccessIterator i = first; + ForwardIterator j = first2; + while(i != last) + i = i + 1, j = boost::next(j); + return std::distance(first, i) == std::distance(first2, j); +} + +template +bool plus_n_test(RandomAccessIterator first, RandomAccessIterator last, ForwardIterator first2) +{ + RandomAccessIterator i = first; + ForwardIterator j = first2; + for(int n = 0; i != last; ++n) + i = first + n, j = boost::next(first2, n); + return std::distance(first, i) == std::distance(first2, j); +} + +template +bool minus_one_test(RandomAccessIterator first, RandomAccessIterator last, BidirectionalIterator last2) +{ + RandomAccessIterator i = last; + BidirectionalIterator j = last2; + while(i != first) + i = i - 1, j = boost::prior(j); + return std::distance(i, last) == std::distance(j, last2); +} + +template +bool minus_n_test(RandomAccessIterator first, RandomAccessIterator last, BidirectionalIterator last2) +{ + RandomAccessIterator i = last; + BidirectionalIterator j = last2; + for(int n = 0; i != first; ++n) + i = last - n, j = boost::prior(last2, n); + return std::distance(i, last) == std::distance(j, last2); +} + +template +bool minus_n_unsigned_test(Iterator first, Iterator last, Distance size) +{ + Iterator i = boost::prior(last, size); + return i == first; +} + +int main(int, char*[]) +{ + std::vector x(8); + std::list y(x.begin(), x.end()); + + // Tests with iterators + BOOST_TEST(plus_one_test(x.begin(), x.end(), y.begin())); + BOOST_TEST(plus_n_test(x.begin(), x.end(), y.begin())); + BOOST_TEST(minus_one_test(x.begin(), x.end(), y.end())); + BOOST_TEST(minus_n_test(x.begin(), x.end(), y.end())); + BOOST_TEST(minus_n_unsigned_test(x.begin(), x.end(), x.size())); + BOOST_TEST(minus_n_unsigned_test(y.begin(), y.end(), y.size())); + + BOOST_TEST(plus_one_test(x.rbegin(), x.rend(), y.begin())); + BOOST_TEST(plus_n_test(x.rbegin(), x.rend(), y.begin())); + BOOST_TEST(minus_one_test(x.rbegin(), x.rend(), y.end())); + BOOST_TEST(minus_n_test(x.rbegin(), x.rend(), y.end())); + BOOST_TEST(minus_n_unsigned_test(x.rbegin(), x.rend(), x.size())); + BOOST_TEST(minus_n_unsigned_test(x.rbegin(), x.rend(), y.size())); + + // Test with pointers + std::vector z(x.size()); + int* p = &z[0]; + BOOST_TEST(plus_one_test(x.begin(), x.end(), p)); + BOOST_TEST(plus_n_test(x.begin(), x.end(), p)); + BOOST_TEST(minus_one_test(x.begin(), x.end(), p + z.size())); + BOOST_TEST(minus_n_test(x.begin(), x.end(), p + z.size())); + BOOST_TEST(minus_n_unsigned_test(p, p + z.size(), z.size())); + + // Tests with integers + BOOST_TEST(boost::next(5) == 6); + BOOST_TEST(boost::next(5, 7) == 12); + BOOST_TEST(boost::prior(5) == 4); + BOOST_TEST(boost::prior(5, 7) == -2); + BOOST_TEST(boost::prior(5, 7u) == -2); + + return boost::report_errors(); +} diff --git a/libs/iterator/test/permutation_iterator_test.cpp b/libs/iterator/test/permutation_iterator_test.cpp new file mode 100644 index 00000000..81cdefed --- /dev/null +++ b/libs/iterator/test/permutation_iterator_test.cpp @@ -0,0 +1,103 @@ +// (C) Copyright Toon Knapen 2001. +// (C) Copyright Roland Richter 2003. +// 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) + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + + +// This test checks for convertibility/interoperability among similar +// permutation iterators. We're not using container iterators +// underneath, as in permutation_test, because of bugs in GCC-3.3's +// __normal_iterator that make is_convertible choke when testing +// convertibility. +void iterop_test() +{ + typedef boost::permutation_iterator< double*, int const* > permutation_type; + typedef boost::permutation_iterator< double const*, int const* > permutation_const_type; + + BOOST_CONCEPT_ASSERT(( + boost_concepts::InteroperableIteratorConcept< + permutation_type + , permutation_const_type + >)); +} + +void permutation_test() +{ + // Example taken from documentation of old permutation_iterator. + typedef std::vector< double > element_range_type; + typedef std::list< int > index_type; + + const int element_range_size = 10; + const int index_size = 7; + + BOOST_STATIC_ASSERT(index_size <= element_range_size); + element_range_type elements( element_range_size ); + for( element_range_type::iterator el_it = elements.begin(); el_it != elements.end(); ++el_it ) + { *el_it = std::distance(elements.begin(), el_it); } + + index_type indices( index_size ); + for( index_type::iterator i_it = indices.begin(); i_it != indices.end(); ++i_it ) + { *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it); } + std::reverse( indices.begin(), indices.end() ); + + typedef boost::permutation_iterator< element_range_type::iterator, index_type::iterator > permutation_type; + permutation_type begin = boost::make_permutation_iterator( elements.begin(), indices.begin() ); + permutation_type it = begin; + permutation_type end = boost::make_permutation_iterator( elements.begin(), indices.end() ); + + BOOST_TEST( it == begin ); + BOOST_TEST( it != end ); + + BOOST_TEST( std::distance( begin, end ) == index_size ); + + for( index_type::iterator i_it1 = indices.begin(); it != end; ++i_it1, ++it ) + { + BOOST_TEST( *it == elements[ *i_it1 ] ); + } + + it = begin; + for( int i1 = 0; i1 < index_size - 1 ; ++++i1, ++++it ) + { + index_type::iterator i_it2 = indices.begin(); + std::advance( i_it2, i1 ); + BOOST_TEST( *it == elements[ *i_it2 ] ); + } + + it = begin; + std::advance(it, index_size); + for( index_type::iterator i_it3 = indices.end(); it != begin; ) + { + BOOST_TEST( *--it == elements[ *--i_it3 ] ); + } + + it = begin; + std::advance(it, index_size); + for( int i2 = 0; i2 < index_size - 1; i2+=2, --it ) + { + index_type::iterator i_it4 = --indices.end(); + std::advance( i_it4, -i2 ); + BOOST_TEST( *--it == elements[ *i_it4 ] ); + } + +} + + +int main() +{ + permutation_test(); + return boost::report_errors(); +} diff --git a/libs/iterator/test/pointee.cpp b/libs/iterator/test/pointee.cpp new file mode 100644 index 00000000..32e34962 --- /dev/null +++ b/libs/iterator/test/pointee.cpp @@ -0,0 +1,83 @@ +// Copyright David Abrahams 2004. Use, modification and distribution is +// subject to 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) + +#include +#include +#include "static_assert_same.hpp" +#include +#include + +template +struct proxy_ptr +{ + typedef T element_type; + struct proxy + { + operator Ref() const; + }; + proxy operator*() const; +}; + +template +struct proxy_ref_ptr : proxy_ptr +{ +}; + +template +struct proxy_value_ptr : proxy_ptr +{ + typedef typename boost::add_const::type element_type; +}; + +struct X { + template X(T const&); + template operator T&() const; +}; + + +int main() +{ + STATIC_ASSERT_SAME(boost::pointee >::type, int); + STATIC_ASSERT_SAME(boost::pointee >::type, X); + + STATIC_ASSERT_SAME(boost::pointee >::type, int const); + STATIC_ASSERT_SAME(boost::pointee >::type, X const); + + STATIC_ASSERT_SAME(boost::pointee >::type, int const); + STATIC_ASSERT_SAME(boost::pointee >::type, X const); + + STATIC_ASSERT_SAME(boost::pointee >::type, int const); + STATIC_ASSERT_SAME(boost::pointee >::type, X const); + + STATIC_ASSERT_SAME(boost::pointee::type, int); + STATIC_ASSERT_SAME(boost::pointee::type, int const); + + STATIC_ASSERT_SAME(boost::pointee::type, X); + STATIC_ASSERT_SAME(boost::pointee::type, X const); + +#if defined(BOOST_NO_CXX11_SMART_PTR) + + STATIC_ASSERT_SAME(boost::pointee >::type, int); + STATIC_ASSERT_SAME(boost::pointee >::type, X); + + STATIC_ASSERT_SAME(boost::pointee >::type, int const); + STATIC_ASSERT_SAME(boost::pointee >::type, X const); + +#else + + STATIC_ASSERT_SAME(boost::pointee >::type, int); + STATIC_ASSERT_SAME(boost::pointee >::type, X); + + STATIC_ASSERT_SAME(boost::pointee >::type, int const); + STATIC_ASSERT_SAME(boost::pointee >::type, X const); + +#endif + + STATIC_ASSERT_SAME(boost::pointee::iterator >::type, int); + STATIC_ASSERT_SAME(boost::pointee::iterator >::type, X); + + STATIC_ASSERT_SAME(boost::pointee::const_iterator >::type, int const); + STATIC_ASSERT_SAME(boost::pointee::const_iterator >::type, X const); + return 0; +} diff --git a/libs/iterator/test/range_distance_compat_test.cpp b/libs/iterator/test/range_distance_compat_test.cpp new file mode 100644 index 00000000..ef7e301d --- /dev/null +++ b/libs/iterator/test/range_distance_compat_test.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2018 Andrey Semashev +// +// 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) + +#include +#include +#include + +int main() +{ + // Test that boost::distance from Boost.Range works with boost::distance from Boost.Iterator + // (https://github.com/boostorg/iterator/commit/b844c8df530c474ec1856870b9b0de5f487b84d4#commitcomment-30603668) + + typedef boost::iterator_range range_type; + range_type range; + + (void)boost::distance(range); + + return 0; +} diff --git a/libs/iterator/test/reverse_iterator_test.cpp b/libs/iterator/test/reverse_iterator_test.cpp new file mode 100644 index 00000000..c2e4a419 --- /dev/null +++ b/libs/iterator/test/reverse_iterator_test.cpp @@ -0,0 +1,174 @@ +// Copyright Thomas Witt 2003, Jeremy Siek 2004. + +// 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) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using boost::dummyT; + +// Test reverse iterator +int main() +{ + dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), + dummyT(3), dummyT(4), dummyT(5) }; + const int N = sizeof(array)/sizeof(dummyT); + + // Concept checks + // Adapting old-style iterators + { + typedef boost::reverse_iterator > Iter; + boost::function_requires< boost::BidirectionalIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } + { + typedef boost::reverse_iterator > Iter; + boost::function_requires< boost::Mutable_BidirectionalIteratorConcept >(); + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } + // Adapting new-style iterators + { + typedef boost::iterator_archetype< + const dummyT + , boost::iterator_archetypes::readable_iterator_t + , boost::bidirectional_traversal_tag + > iter; + typedef boost::reverse_iterator Iter; + boost::function_requires< boost::InputIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } +#if 0 + // It does not seem feasible to make this work. Need to change docs to + // require at lease Readable for the base iterator. -Jeremy + { + typedef boost::iterator_archetype< + dummyT + , boost::iterator_archetypes::writable_iterator_t + , boost::bidirectional_traversal_tag + > iter; + typedef boost::reverse_iterator Iter; + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } +#endif +#if !BOOST_WORKAROUND(BOOST_MSVC, == 1200) // Causes Internal Error in linker. + { + typedef boost::iterator_archetype< + dummyT + , boost::iterator_archetypes::readable_writable_iterator_t + , boost::bidirectional_traversal_tag + > iter; + typedef boost::reverse_iterator Iter; + boost::function_requires< boost::InputIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } + { + typedef boost::iterator_archetype< + const dummyT + , boost::iterator_archetypes::readable_lvalue_iterator_t + , boost::bidirectional_traversal_tag + > iter; + typedef boost::reverse_iterator Iter; + boost::function_requires< boost::BidirectionalIteratorConcept >(); + boost::function_requires< boost_concepts::ReadableIteratorConcept >(); + boost::function_requires< boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } + { + typedef boost::iterator_archetype< + dummyT + , boost::iterator_archetypes::writable_lvalue_iterator_t + , boost::bidirectional_traversal_tag + > iter; + typedef boost::reverse_iterator Iter; + boost::function_requires< boost::BidirectionalIteratorConcept >(); + boost::function_requires< boost_concepts::WritableIteratorConcept >(); + boost::function_requires< boost_concepts::LvalueIteratorConcept >(); + boost::function_requires< boost_concepts::BidirectionalTraversalConcept >(); + } +#endif + + // Test reverse_iterator + { + dummyT reversed[N]; + std::copy(array, array + N, reversed); + std::reverse(reversed, reversed + N); + + typedef boost::reverse_iterator reverse_iterator; + + reverse_iterator i(reversed + N); + boost::random_access_iterator_test(i, N, array); + + boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array); + + typedef boost::reverse_iterator const_reverse_iterator; + + const_reverse_iterator j(reversed + N); + boost::random_access_iterator_test(j, N, array); + + const dummyT* const_reversed = reversed; + + boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array); + + boost::const_nonconst_iterator_test(i, ++j); + } + + // Test reverse_iterator again, with traits fully deducible on all platforms + { + std::deque reversed_container; + std::reverse_copy(array, array + N, std::back_inserter(reversed_container)); + const std::deque::iterator reversed = reversed_container.begin(); + + + typedef boost::reverse_iterator< + std::deque::iterator> reverse_iterator; + typedef boost::reverse_iterator< + std::deque::const_iterator> const_reverse_iterator; + + // MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation + // (e.g. "reversed + N") is used in the constructor below. + const std::deque::iterator finish = reversed_container.end(); + reverse_iterator i(finish); + + boost::random_access_iterator_test(i, N, array); + boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array); + + const_reverse_iterator j = reverse_iterator(finish); + boost::random_access_iterator_test(j, N, array); + + const std::deque::const_iterator const_reversed = reversed; + boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array); + + // Many compilers' builtin deque iterators don't interoperate well, though + // STLport fixes that problem. +#if defined(__SGI_STL_PORT) \ + || !BOOST_WORKAROUND(__GNUC__, <= 2) \ + && !(BOOST_WORKAROUND(__GNUC__, == 3) && BOOST_WORKAROUND(__GNUC_MINOR__, <= 1)) \ + && !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) \ + && !BOOST_WORKAROUND(__LIBCOMO_VERSION__, BOOST_TESTED_AT(29)) \ + && !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 1) + + boost::const_nonconst_iterator_test(i, ++j); + +#endif + } + + return boost::report_errors(); +} diff --git a/libs/iterator/test/shared_iterator_test.cpp b/libs/iterator/test/shared_iterator_test.cpp new file mode 100644 index 00000000..a943d304 --- /dev/null +++ b/libs/iterator/test/shared_iterator_test.cpp @@ -0,0 +1,64 @@ +// Copyright 2003 The Trustees of Indiana University. + +// Use, modification and distribution is subject to 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) + +// Shared container iterator adaptor +// Author: Ronald Garcia +// See http://boost.org/libs/utility/shared_container_iterator.html +// for documentation. + +// +// shared_iterator_test.cpp - Regression tests for shared_container_iterator. +// + + +#include "boost/shared_container_iterator.hpp" +#include "boost/shared_ptr.hpp" +#include +#include + +struct resource { + static int count; + resource() { ++count; } + resource(resource const&) { ++count; } + ~resource() { --count; } +}; +int resource::count = 0; + +typedef std::vector resources_t; + +typedef boost::shared_container_iterator< resources_t > iterator; + + +void set_range(iterator& i, iterator& end) { + + boost::shared_ptr< resources_t > objs(new resources_t()); + + for (int j = 0; j != 6; ++j) + objs->push_back(resource()); + + i = iterator(objs->begin(),objs); + end = iterator(objs->end(),objs); + BOOST_TEST_EQ(resource::count, 6); +} + + +int main() { + + BOOST_TEST_EQ(resource::count, 0); + + { + iterator i; + { + iterator end; + set_range(i,end); + BOOST_TEST_EQ(resource::count, 6); + } + BOOST_TEST_EQ(resource::count, 6); + } + BOOST_TEST_EQ(resource::count, 0); + + return boost::report_errors(); +} diff --git a/libs/iterator/test/static_assert_same.hpp b/libs/iterator/test/static_assert_same.hpp new file mode 100644 index 00000000..5d96da93 --- /dev/null +++ b/libs/iterator/test/static_assert_same.hpp @@ -0,0 +1,20 @@ +// Copyright David Abrahams 2003. +// 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) +#ifndef STATIC_ASSERT_SAME_DWA2003530_HPP +# define STATIC_ASSERT_SAME_DWA2003530_HPP + +#include +#include + +#define STATIC_ASSERT_SAME( T1,T2 ) BOOST_STATIC_ASSERT((::boost::is_same< T1, T2 >::value)) + +template +struct static_assert_same +{ + STATIC_ASSERT_SAME(T1, T2); + enum { value = 1 }; +}; + +#endif // STATIC_ASSERT_SAME_DWA2003530_HPP diff --git a/libs/iterator/test/test_cmake/CMakeLists.txt b/libs/iterator/test/test_cmake/CMakeLists.txt new file mode 100644 index 00000000..be363e78 --- /dev/null +++ b/libs/iterator/test/test_cmake/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright 2023 Andrey Semashev +# +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt +# +# NOTE: This does NOT run the unit tests for Boost.Atomic. +# It only tests if the CMakeLists.txt file in its root works as expected + +cmake_minimum_required(VERSION 3.5) + +project(BoostIteratorCMakeSelfTest) + +# Use experimental superproject to pull library dependencies recursively +set(BOOST_ENABLE_CMAKE 1) +add_subdirectory(../../../.. "${CMAKE_CURRENT_BINARY_DIR}/boost_superproject") + +add_definitions(-DBOOST_ALL_NO_LIB) + +add_executable(boost_iterator_cmake_self_test main.cpp) +target_link_libraries(boost_iterator_cmake_self_test Boost::iterator) diff --git a/libs/iterator/test/test_cmake/main.cpp b/libs/iterator/test/test_cmake/main.cpp new file mode 100644 index 00000000..5cf0e590 --- /dev/null +++ b/libs/iterator/test/test_cmake/main.cpp @@ -0,0 +1,54 @@ +// Copyright (c) 2023 Andrey Semashev +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template< typename Iterator > +class adapted_iterator : + public boost::iterators::iterator_adaptor< adapted_iterator< Iterator >, Iterator > +{ + friend class iterator_core_access; + +private: + typedef boost::iterators::iterator_adaptor< adapted_iterator< Iterator >, Iterator > base_type; + +public: + explicit adapted_iterator(Iterator it) : base_type(it) {} +}; + +int main() +{ + unsigned char buf[8]; + adapted_iterator< unsigned char* > b(buf), e(buf + sizeof(buf)); + return boost::iterators::distance(b, e) == static_cast< adapted_iterator< unsigned char* >::difference_type >(sizeof(buf)); +} diff --git a/libs/iterator/test/transform_iterator_test.cpp b/libs/iterator/test/transform_iterator_test.cpp new file mode 100644 index 00000000..b22cb161 --- /dev/null +++ b/libs/iterator/test/transform_iterator_test.cpp @@ -0,0 +1,284 @@ +// (C) Copyright Jeremy Siek 2002. +// 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) + +// Revision History +// 22 Nov 2002 Thomas Witt +// Added interoperability check. +// 28 Oct 2002 Jeremy Siek +// Updated for new iterator adaptors. +// 08 Mar 2001 Jeremy Siek +// Moved test of transform iterator into its own file. It to +// to be in iterator_adaptor_test.cpp. + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace boost { namespace detail +{ + template<> struct function_object_result + { + typedef int type; + }; +}} +#endif + +struct mult_functor { + // Functors used with transform_iterator must be + // DefaultConstructible, as the transform_iterator must be + // DefaultConstructible to satisfy the requirements for + // TrivialIterator. + mult_functor() { } + mult_functor(int aa) : a(aa) { } + int operator()(int b) const { return a * b; } + int a; +}; + +struct adaptable_mult_functor + : mult_functor +{ + typedef int result_type; + typedef int argument_type; + // Functors used with transform_iterator must be + // DefaultConstructible, as the transform_iterator must be + // DefaultConstructible to satisfy the requirements for + // TrivialIterator. + adaptable_mult_functor() { } + adaptable_mult_functor(int aa) : mult_functor(aa) { } +}; + + +struct const_select_first +{ + typedef int const& result_type; + + int const& operator()(std::pairconst& p) const + { + return p.first; + } +}; + +struct select_first + : const_select_first // derivation to allow conversions +{ + typedef int& result_type; + + int& operator()(std::pair& p) const + { + return p.first; + } +}; + +struct select_second +{ + typedef int& result_type; + + int& operator()(std::pair& p) const + { + return p.second; + } +}; + +struct value_select_first +{ + typedef int result_type; + + int operator()(std::pairconst& p) const + { + return p.first; + } +}; + +int mult_2(int arg) +{ + return arg*2; +} + +struct polymorphic_mult_functor +{ + //Implement result_of protocol + template struct result; + template struct result {typedef T type;}; + template struct result {typedef T type;}; + template struct result {typedef T type;}; + template struct result {typedef void type;}; + template struct result {typedef void type;}; + template struct result {typedef void type;}; + + template + T operator()(const T& _arg) const {return _arg*2;} + template + void operator()(const T& _arg) { BOOST_ASSERT(0); } +}; + +int +main() +{ + const int N = 10; + + // Concept checks + { + typedef boost::transform_iterator iter_t; + typedef boost::transform_iterator c_iter_t; + + boost::function_requires< boost_concepts::InteroperableIteratorConcept >(); + } + + // Test transform_iterator + { + int x[N], y[N]; + for (int k = 0; k < N; ++k) + x[k] = k; + std::copy(x, x + N, y); + + for (int k2 = 0; k2 < N; ++k2) + x[k2] = x[k2] * 2; + + typedef boost::transform_iterator iter_t; + iter_t i(y, adaptable_mult_functor(2)); + boost::input_iterator_test(i, x[0], x[1]); + boost::input_iterator_test(iter_t(&y[0], adaptable_mult_functor(2)), x[0], x[1]); + + boost::random_access_readable_iterator_test(i, N, x); + } + + // Test transform_iterator non adaptable functor + { + int x[N], y[N]; + for (int k = 0; k < N; ++k) + x[k] = k; + std::copy(x, x + N, y); + + for (int k2 = 0; k2 < N; ++k2) + x[k2] = x[k2] * 2; + + typedef boost::transform_iterator iter_t; + iter_t i(y, mult_functor(2)); + boost::input_iterator_test(i, x[0], x[1]); + boost::input_iterator_test(iter_t(&y[0], mult_functor(2)), x[0], x[1]); + + boost::random_access_readable_iterator_test(i, N, x); + } + + // Test transform_iterator default argument handling + { + { + typedef boost::transform_iterator iter_t; + BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + + { + typedef boost::transform_iterator iter_t; + BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + + { + typedef boost::transform_iterator iter_t; + BOOST_STATIC_ASSERT((boost::is_same::value)); + BOOST_STATIC_ASSERT((boost::is_same::value)); + } + } + + // Test transform_iterator with function pointers + { + int x[N], y[N]; + for (int k = 0; k < N; ++k) + x[k] = k; + std::copy(x, x + N, y); + + for (int k2 = 0; k2 < N; ++k2) + x[k2] = x[k2] * 2; + + boost::input_iterator_test( + boost::make_transform_iterator(y, mult_2), x[0], x[1]); + + boost::input_iterator_test( + boost::make_transform_iterator(&y[0], mult_2), x[0], x[1]); + + boost::random_access_readable_iterator_test( + boost::make_transform_iterator(y, mult_2), N, x); + + } + + // Test transform_iterator as projection iterator + { + typedef std::pair pair_t; + + int x[N]; + int y[N]; + pair_t values[N]; + + for(int i = 0; i < N; ++i) { + + x[i] = i; + y[i] = N - (i + 1); + + } + + std::copy( + x + , x + N + , boost::make_transform_iterator((pair_t*)values, select_first()) + ); + + std::copy( + y + , y + N + , boost::make_transform_iterator((pair_t*)values, select_second()) + ); + + boost::random_access_readable_iterator_test( + boost::make_transform_iterator((pair_t*)values, value_select_first()) + , N + , x + ); + + boost::random_access_readable_iterator_test( + boost::make_transform_iterator((pair_t*)values, const_select_first()) + , N, x + ); + + boost::constant_lvalue_iterator_test( + boost::make_transform_iterator((pair_t*)values, const_select_first()), x[0]); + + boost::non_const_lvalue_iterator_test( + boost::make_transform_iterator((pair_t*)values, select_first()), x[0], 17); + + boost::const_nonconst_iterator_test( + ++boost::make_transform_iterator((pair_t*)values, select_first()) + , boost::make_transform_iterator((pair_t*)values, const_select_first()) + ); + } + + // Test transform_iterator with polymorphic object function + { + int x[N], y[N]; + for (int k = 0; k < N; ++k) + x[k] = k; + std::copy(x, x + N, y); + + for (int k2 = 0; k2 < N; ++k2) + x[k2] = x[k2] * 2; + + boost::input_iterator_test( + boost::make_transform_iterator(y, polymorphic_mult_functor()), x[0], x[1]); + + boost::input_iterator_test( + boost::make_transform_iterator(&y[0], polymorphic_mult_functor()), x[0], x[1]); + + boost::random_access_readable_iterator_test( + boost::make_transform_iterator(y, polymorphic_mult_functor()), N, x); + } + + return boost::report_errors(); +} diff --git a/libs/iterator/test/unit_tests.cpp b/libs/iterator/test/unit_tests.cpp new file mode 100644 index 00000000..656e72ff --- /dev/null +++ b/libs/iterator/test/unit_tests.cpp @@ -0,0 +1,107 @@ +// Copyright David Abrahams 2003. +// 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) +#include +#include + +#include "static_assert_same.hpp" + +#include + +struct X { int a; }; + + +struct Xiter : boost::iterator_adaptor +{ + Xiter(); + Xiter(X* p) : boost::iterator_adaptor(p) {} +}; + +void take_xptr(X*) {} +void operator_arrow_test() +{ + // check that the operator-> result is a pointer for lvalue iterators + X x; + take_xptr(Xiter(&x).operator->()); +} + +template +struct static_assert_min_cat + : static_assert_same< + typename boost::iterators::minimum_category::type, Min + > +{}; + +void category_test() +{ + using namespace boost::iterators; + using namespace boost::iterators::detail; + + BOOST_STATIC_ASSERT(( + !boost::is_convertible< + std::input_iterator_tag + , input_output_iterator_tag>::value)); + + BOOST_STATIC_ASSERT(( + !boost::is_convertible< + std::output_iterator_tag + , input_output_iterator_tag>::value)); + + BOOST_STATIC_ASSERT(( + boost::is_convertible< + input_output_iterator_tag + , std::input_iterator_tag>::value)); + + BOOST_STATIC_ASSERT(( + boost::is_convertible< + input_output_iterator_tag + , std::output_iterator_tag>::value)); + +#if 0 // This seems wrong; we're not advertising + // input_output_iterator_tag are we? + BOOST_STATIC_ASSERT(( + boost::is_convertible< + std::forward_iterator_tag + , input_output_iterator_tag>::value)); +#endif + + int test = static_assert_min_cat< + std::input_iterator_tag,input_output_iterator_tag, std::input_iterator_tag + >::value; + + test = static_assert_min_cat< + input_output_iterator_tag,std::input_iterator_tag, std::input_iterator_tag + >::value; + +#if 0 + test = static_assert_min_cat< + input_output_iterator_tag,std::forward_iterator_tag, input_output_iterator_tag + >::value; +#endif + + test = static_assert_min_cat< + std::input_iterator_tag,std::forward_iterator_tag, std::input_iterator_tag + >::value; + + test = static_assert_min_cat< + std::input_iterator_tag,std::random_access_iterator_tag, std::input_iterator_tag + >::value; + +#if 0 // This would be wrong: a random access iterator is not + // neccessarily writable, as is an output iterator. + test = static_assert_min_cat< + std::output_iterator_tag,std::random_access_iterator_tag, std::output_iterator_tag + >::value; +#endif + + (void)test; +} + +int main() +{ + category_test(); + operator_arrow_test(); + return 0; +} + diff --git a/libs/iterator/test/zip_iterator_test.cpp b/libs/iterator/test/zip_iterator_test.cpp new file mode 100644 index 00000000..08c4581e --- /dev/null +++ b/libs/iterator/test/zip_iterator_test.cpp @@ -0,0 +1,8 @@ +#include + +#define ZI_TUPLE boost::tuples::tuple +#define ZI_MAKE_TUPLE boost::make_tuple +#define ZI_TUPLE_GET(n) boost::tuples::get +#define ZI_USE_BOOST_TUPLE + +#include "detail/zip_iterator_test_original.ipp" diff --git a/libs/iterator/test/zip_iterator_test2_fusion_deque.cpp b/libs/iterator/test/zip_iterator_test2_fusion_deque.cpp new file mode 100644 index 00000000..82d3b78a --- /dev/null +++ b/libs/iterator/test/zip_iterator_test2_fusion_deque.cpp @@ -0,0 +1,9 @@ +#include +#include +#include + +#define ZI_TUPLE boost::fusion::deque +#define ZI_MAKE_TUPLE boost::fusion::make_deque +#define ZI_TUPLE_GET(n) boost::fusion::at_c + +#include "detail/zip_iterator_test_original.ipp" diff --git a/libs/iterator/test/zip_iterator_test2_fusion_list.cpp b/libs/iterator/test/zip_iterator_test2_fusion_list.cpp new file mode 100644 index 00000000..d410032e --- /dev/null +++ b/libs/iterator/test/zip_iterator_test2_fusion_list.cpp @@ -0,0 +1,11 @@ +#include + +#include +#include +#include + +#define ZI_TUPLE boost::fusion::list +#define ZI_MAKE_TUPLE boost::fusion::make_list +#define ZI_TUPLE_GET(n) boost::fusion::at_c + +#include "detail/zip_iterator_test_original.ipp" diff --git a/libs/iterator/test/zip_iterator_test2_fusion_vector.cpp b/libs/iterator/test/zip_iterator_test2_fusion_vector.cpp new file mode 100644 index 00000000..d9400b02 --- /dev/null +++ b/libs/iterator/test/zip_iterator_test2_fusion_vector.cpp @@ -0,0 +1,11 @@ +#include + +#include +#include +#include + +#define ZI_TUPLE boost::fusion::vector +#define ZI_MAKE_TUPLE boost::fusion::make_vector +#define ZI_TUPLE_GET(n) boost::fusion::at_c + +#include "detail/zip_iterator_test_original.ipp" diff --git a/libs/iterator/test/zip_iterator_test2_std_tuple.cpp b/libs/iterator/test/zip_iterator_test2_std_tuple.cpp new file mode 100644 index 00000000..91d77485 --- /dev/null +++ b/libs/iterator/test/zip_iterator_test2_std_tuple.cpp @@ -0,0 +1,24 @@ +#include + +// libstdc++ from gcc 4.4 has a broken std::tuple that cannot be constructed from a compatible tuple, +// e.g. std::tuple from std::tuple. +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + (!defined(BOOST_LIBSTDCXX_VERSION) || BOOST_LIBSTDCXX_VERSION >= 40500) + +#include +#include + +#define ZI_TUPLE std::tuple +#define ZI_MAKE_TUPLE std::make_tuple +#define ZI_TUPLE_GET(n) std::get + +#include "detail/zip_iterator_test_original.ipp" + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/libs/iterator/test/zip_iterator_test_fusion.cpp b/libs/iterator/test/zip_iterator_test_fusion.cpp new file mode 100644 index 00000000..542fd882 --- /dev/null +++ b/libs/iterator/test/zip_iterator_test_fusion.cpp @@ -0,0 +1,15 @@ +// Copyright (c) 2014 Kohei Takahashi. +// +// 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) +// +// See http://www.boost.org for most recent version including documentation. + +#include +#include + +#define TUPLE boost::fusion::vector +#define MAKE_TUPLE boost::fusion::make_vector + +#include "detail/zip_iterator_test.ipp" diff --git a/libs/iterator/test/zip_iterator_test_std_pair.cpp b/libs/iterator/test/zip_iterator_test_std_pair.cpp new file mode 100644 index 00000000..4353b6dc --- /dev/null +++ b/libs/iterator/test/zip_iterator_test_std_pair.cpp @@ -0,0 +1,33 @@ +// Copyright (c) 2014 Kohei Takahashi. +// +// 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) +// +// See http://www.boost.org for most recent version including documentation. + +#include +#include +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1600) + +BOOST_PRAGMA_MESSAGE("Skipping test on msvc-9.0 and below") +int main() {} + +#elif defined(BOOST_GCC) && __cplusplus < 201100 + +BOOST_PRAGMA_MESSAGE("Skipping test on g++ in C++03 mode") +int main() {} + +#else + +#include +#include + +#define TUPLE std::pair +#define MAKE_TUPLE std::make_pair + +#include "detail/zip_iterator_test.ipp" + +#endif diff --git a/libs/iterator/test/zip_iterator_test_std_tuple.cpp b/libs/iterator/test/zip_iterator_test_std_tuple.cpp new file mode 100644 index 00000000..02d648d3 --- /dev/null +++ b/libs/iterator/test/zip_iterator_test_std_tuple.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2014 Kohei Takahashi. +// +// 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) +// +// See http://www.boost.org for most recent version including documentation. + +#include + +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +#include +#include + +#define TUPLE std::tuple +#define MAKE_TUPLE std::make_tuple + +#include "detail/zip_iterator_test.ipp" + +#else + +int main() +{ + return 0; +} + +#endif + diff --git a/libs/optional/.drone.star b/libs/optional/.drone.star new file mode 100644 index 00000000..0db25622 --- /dev/null +++ b/libs/optional/.drone.star @@ -0,0 +1,36 @@ +# Use, modification, and distribution are +# subject to the Boost Software License, Version 1.0. (See accompanying +# file LICENSE.txt) +# +# Copyright Rene Rivera 2020. + +# For Drone CI we use the Starlark scripting language to reduce duplication. +# As the yaml syntax for Drone CI is rather limited. +# +# +globalenv={} +linuxglobalimage="cppalliance/droneubuntu1604:1" +windowsglobalimage="cppalliance/dronevs2019" + +def main(ctx): + return [ + linux_cxx("TOOLSET=gcc COMPILER=g++ CXXSTD=03,11 Job 0", "g++", packages="", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++', 'CXXSTD': '03,11', 'DRONE_JOB_UUID': 'b6589fc6ab'}, globalenv=globalenv), + linux_cxx("TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=03,11 Job 1", "g++-4.7", packages="g++-4.7", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.7', 'CXXSTD': '03,11', 'DRONE_JOB_UUID': '356a192b79'}, globalenv=globalenv), + linux_cxx("TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=03,11 Job 2", "g++-4.8", packages="g++-4.8", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.8', 'CXXSTD': '03,11', 'DRONE_JOB_UUID': 'da4b9237ba'}, globalenv=globalenv), + linux_cxx("TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=03,11 Job 3", "g++-4.9", packages="g++-4.9", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.9', 'CXXSTD': '03,11', 'DRONE_JOB_UUID': '77de68daec'}, globalenv=globalenv), + linux_cxx("TOOLSET=gcc COMPILER=g++-5 CXXSTD=03,11,14,1z Job 4", "g++-5", packages="g++-5", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-5', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': '1b64538924'}, globalenv=globalenv), + linux_cxx("TOOLSET=gcc COMPILER=g++-6 CXXSTD=03,11,14,1z Job 5", "g++-6", packages="g++-6", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-6', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': 'ac3478d69a'}, globalenv=globalenv), + linux_cxx("TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 Job 6", "g++-7", packages="g++-7", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-7', 'CXXSTD': '03,11,14,17', 'DRONE_JOB_UUID': 'c1dfd96eea'}, globalenv=globalenv), + linux_cxx("TOOLSET=clang COMPILER=clang++ CXXSTD=03,11 Job 7", "clang++", packages="", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03,11', 'DRONE_JOB_UUID': '902ba3cda1'}, globalenv=globalenv), + linux_cxx("TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=03, Job 8", "clang++-3.5", packages="clang-3.5 libstdc++-4.9-dev", llvm_os="precise", llvm_ver="3.5", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.5', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': 'fe5dbbcea5'}, globalenv=globalenv), + linux_cxx("TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=03, Job 9", "clang++-3.6", packages="clang-3.6", llvm_os="precise", llvm_ver="3.6", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.6', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': '0ade7c2cf9'}, globalenv=globalenv), + linux_cxx("TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=03, Job 10", "clang++-3.7", packages="clang-3.7", llvm_os="precise", llvm_ver="3.7", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.7', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': 'b1d5781111'}, globalenv=globalenv), + linux_cxx("TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=03, Job 11", "clang++-3.8", packages="clang-3.8 libstdc++-4.9-dev", llvm_os="precise", llvm_ver="3.8", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.8', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': '17ba079149'}, globalenv=globalenv), + linux_cxx("TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=03, Job 12", "clang++-3.9", packages="clang-3.9 libstdc++-4.9-dev", llvm_os="precise", llvm_ver="3.9", buildtype="boost", buildscript="drone", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.9', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': '7b52009b64'}, globalenv=globalenv), + linux_cxx("TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=03, Job 13", "clang++-4.0", packages="clang-4.0", llvm_os="trusty", llvm_ver="4.0", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-4.0', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': 'bd307a3ec3'}, globalenv=globalenv), + linux_cxx("TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03, Job 14", "clang++-5.0", packages="clang-5.0", llvm_os="trusty", llvm_ver="5.0", buildtype="boost", buildscript="drone", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-5.0', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': 'fa35e19212'}, globalenv=globalenv), + osx_cxx("TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,1 Job 15", "clang++", packages="", buildtype="boost", buildscript="drone", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03,11,14,1z', 'DRONE_JOB_UUID': 'f1abd67035'}, globalenv=globalenv), + ] + +# from https://github.com/boostorg/boost-ci +load("@boost_ci//ci/drone/:functions.star", "linux_cxx","windows_cxx","osx_cxx","freebsd_cxx") diff --git a/libs/optional/.drone/drone.sh b/libs/optional/.drone/drone.sh new file mode 100644 index 00000000..a10e6eee --- /dev/null +++ b/libs/optional/.drone/drone.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# Copyright 2020 Rene Rivera, Sam Darwin +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.txt or copy at http://boost.org/LICENSE_1_0.txt) + +set -e +export TRAVIS_BUILD_DIR=$(pwd) +export DRONE_BUILD_DIR=$(pwd) +export TRAVIS_BRANCH=$DRONE_BRANCH +export VCS_COMMIT_ID=$DRONE_COMMIT +export GIT_COMMIT=$DRONE_COMMIT +export REPO_NAME=$DRONE_REPO +export PATH=~/.local/bin:/usr/local/bin:$PATH + +if [ "$DRONE_JOB_BUILDTYPE" == "boost" ]; then + +echo '==================================> INSTALL' + +BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true +cd .. +git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root +cd boost-root +git submodule update --init tools/build +git submodule update --init libs/config +git submodule update --init tools/boostdep +cp -r $TRAVIS_BUILD_DIR/* libs/optional +python tools/boostdep/depinst/depinst.py optional +./bootstrap.sh +./b2 headers + +echo '==================================> SCRIPT' + +echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam +./b2 libs/optional/test toolset=$TOOLSET cxxstd=$CXXSTD + +fi diff --git a/libs/optional/.gitattributes b/libs/optional/.gitattributes new file mode 100644 index 00000000..3e84d7c7 --- /dev/null +++ b/libs/optional/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain diff --git a/libs/optional/.github/workflows/ci.yml b/libs/optional/.github/workflows/ci.yml new file mode 100644 index 00000000..1826a08d --- /dev/null +++ b/libs/optional/.github/workflows/ci.yml @@ -0,0 +1,396 @@ +name: GitHub Actions CI + +on: + pull_request: + push: + branches: + - master + - develop + - githubactions* + - feature/** + - fix/** + - pr/** + +concurrency: + group: ${{format('{0}:{1}', github.repository, github.ref)}} + cancel-in-progress: true + +env: + NET_RETRY_COUNT: 5 + +jobs: + posix: + strategy: + fail-fast: false + matrix: + include: + - name: "TOOLSET=gcc COMPILER=g++ CXXSTD=03,11 Job 0" + buildtype: "boost" + packages: "" + packages_to_remove: "" + os: "ubuntu-20.04" + container: "ubuntu:16.04" + cxx: "g++" + sources: "" + llvm_os: "" + llvm_ver: "" + toolset: "gcc" + compiler: "g++" + cxxstd: "03,11" + - name: "TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=03,11 Job 1" + buildtype: "boost" + packages: "g++-4.7" + packages_to_remove: "" + os: "ubuntu-20.04" + container: "ubuntu:16.04" + cxx: "g++-4.7" + sources: "" + llvm_os: "" + llvm_ver: "" + toolset: "gcc" + compiler: "g++-4.7" + cxxstd: "03,11" + - name: "TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=03,11 Job 2" + buildtype: "boost" + packages: "g++-4.8" + packages_to_remove: "" + os: "ubuntu-20.04" + container: "ubuntu:16.04" + cxx: "g++-4.8" + sources: "" + llvm_os: "" + llvm_ver: "" + toolset: "gcc" + compiler: "g++-4.8" + cxxstd: "03,11" + - name: "TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=03,11 Job 3" + buildtype: "boost" + packages: "g++-4.9" + packages_to_remove: "" + os: "ubuntu-20.04" + container: "ubuntu:16.04" + cxx: "g++-4.9" + sources: "" + llvm_os: "" + llvm_ver: "" + toolset: "gcc" + compiler: "g++-4.9" + cxxstd: "03,11" + - name: "TOOLSET=gcc COMPILER=g++-5 CXXSTD=03,11,14,1z Job 4" + buildtype: "boost" + packages: "g++-5" + packages_to_remove: "" + os: "ubuntu-20.04" + container: "ubuntu:16.04" + cxx: "g++-5" + sources: "" + llvm_os: "" + llvm_ver: "" + toolset: "gcc" + compiler: "g++-5" + cxxstd: "03,11,14,1z" + - name: "TOOLSET=gcc COMPILER=g++-6 CXXSTD=03,11,14,1z Job 5" + buildtype: "boost" + packages: "g++-6" + packages_to_remove: "" + os: "ubuntu-20.04" + container: "ubuntu:16.04" + cxx: "g++-6" + sources: "" + llvm_os: "" + llvm_ver: "" + toolset: "gcc" + compiler: "g++-6" + cxxstd: "03,11,14,1z" + - name: "TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 Job 6" + buildtype: "boost" + packages: "g++-7" + packages_to_remove: "" + os: "ubuntu-20.04" + container: "ubuntu:16.04" + cxx: "g++-7" + sources: "" + llvm_os: "" + llvm_ver: "" + toolset: "gcc" + compiler: "g++-7" + cxxstd: "03,11,14,17" + - name: "TOOLSET=clang COMPILER=clang++ CXXSTD=03,11 Job 7" + buildtype: "boost" + packages: "clang" + packages_to_remove: "" + os: "ubuntu-22.04" + container: "ubuntu:18.04" + cxx: "clang++" + sources: "" + llvm_os: "" + llvm_ver: "" + toolset: "clang" + compiler: "clang++" + cxxstd: "03,11" + - name: "TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=03, Job 8" + buildtype: "boost" + packages: "clang-3.5 libstdc++-4.9-dev" + packages_to_remove: "" + os: "ubuntu-20.04" + container: "ubuntu:16.04" + cxx: "clang++-3.5" + sources: "" + llvm_os: "precise" + llvm_ver: "3.5" + toolset: "clang" + compiler: "clang++-3.5" + cxxstd: "03,11,14" + - name: "TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=03, Job 9" + buildtype: "boost" + packages: "clang-3.6" + packages_to_remove: "" + os: "ubuntu-20.04" + container: "ubuntu:16.04" + cxx: "clang++-3.6" + sources: "" + llvm_os: "precise" + llvm_ver: "3.6" + toolset: "clang" + compiler: "clang++-3.6" + cxxstd: "03,11,14" + - name: "TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=03, Job 10" + buildtype: "boost" + packages: "clang-3.7" + packages_to_remove: "" + os: "ubuntu-20.04" + container: "ubuntu:16.04" + cxx: "clang++-3.7" + sources: "" + llvm_os: "precise" + llvm_ver: "3.7" + toolset: "clang" + compiler: "clang++-3.7" + cxxstd: "03,11,14" + - name: "TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=03, Job 11" + buildtype: "boost" + packages: "clang-3.8 libstdc++-4.9-dev" + packages_to_remove: "" + os: "ubuntu-20.04" + container: "ubuntu:16.04" + cxx: "clang++-3.8" + sources: "" + llvm_os: "precise" + llvm_ver: "3.8" + toolset: "clang" + compiler: "clang++-3.8" + cxxstd: "03,11,14" + - name: "TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=03, Job 12" + buildtype: "boost" + packages: "clang-3.9 libstdc++-4.9-dev" + packages_to_remove: "" + os: "ubuntu-20.04" + container: "ubuntu:16.04" + cxx: "clang++-3.9" + sources: "" + llvm_os: "precise" + llvm_ver: "3.9" + toolset: "clang" + compiler: "clang++-3.9" + cxxstd: "03,11,14" + - name: "TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=03, Job 13" + buildtype: "boost" + packages: "clang-4.0" + packages_to_remove: "" + os: "ubuntu-20.04" + container: "ubuntu:14.04" + cxx: "clang++-4.0" + sources: "" + llvm_os: "trusty" + llvm_ver: "4.0" + toolset: "clang" + compiler: "clang++-4.0" + cxxstd: "03,11,14" + - name: "TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03, Job 14" + buildtype: "boost" + packages: "clang-5.0" + packages_to_remove: "" + os: "ubuntu-22.04" + container: "ubuntu:18.04" + cxx: "clang++-5.0" + sources: "" + llvm_os: "" + llvm_ver: "" + toolset: "clang" + compiler: "clang++-5.0" + cxxstd: "03,11,14,1z" + + runs-on: ${{ matrix.os }} + container: ${{ matrix.container }} + + steps: + - name: Check if running in container + if: matrix.container != '' + run: echo "GHA_CONTAINER=${{ matrix.container }}" >> $GITHUB_ENV + - name: If running in container, upgrade packages + if: matrix.container != '' + run: | + if [ -f "/etc/debian_version" ]; then + echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV + export DEBIAN_FRONTEND=noninteractive + apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common curl wget apt-transport-https ca-certificates + # Need (newer) git, and the older Ubuntu container may require requesting the key manually using port 80 + curl -sSL --retry ${NET_RETRY_COUNT:-5} 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xE1DD270288B4E6030699E45FA1715D88E1DF1F24' | sudo gpg --dearmor > /etc/apt/trusted.gpg.d/git-core_ubuntu_ppa.gpg + for i in {1..${NET_RETRY_COUNT:-3}}; do sudo -E add-apt-repository -y ppa:git-core/ppa && break || sleep 10; done + apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y g++ python libpython-dev git unzip libssl-dev build-essential libc++-helpers gcc-multilib g++-multilib pkgconf ccache + fi + + - uses: actions/checkout@v2 + + - name: linux + shell: bash + env: + CXX: ${{ matrix.cxx }} + SOURCES: ${{ matrix.sources }} + LLVM_OS: ${{ matrix.llvm_os }} + LLVM_VER: ${{ matrix.llvm_ver }} + PACKAGES: ${{ matrix.packages }} + PACKAGES_TO_REMOVE: ${{ matrix.packages_to_remove }} + JOB_BUILDTYPE: ${{ matrix.buildtype }} + TOOLSET: ${{ matrix.toolset }} + COMPILER: ${{ matrix.compiler }} + CXXSTD: ${{ matrix.cxxstd }} + TRAVIS_BRANCH: ${{ github.base_ref }} + TRAVIS_OS_NAME: "linux" + run: | + echo '==================================> SETUP' + echo '==================================> PACKAGES' + set -e + if [ -n "$PACKAGES_TO_REMOVE" ]; then sudo apt-get purge -y $PACKAGES_TO_REMOVE; fi + echo ">>>>> APT: REPO.." + for i in {1..3}; do sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test" && break || sleep 2; done + + if test -n "${LLVM_OS}" ; then + wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + if test -n "${LLVM_VER}" ; then + sudo -E apt-add-repository "deb http://apt.llvm.org/${LLVM_OS}/ llvm-toolchain-${LLVM_OS}-${LLVM_VER} main" + else + # Snapshot (i.e. trunk) build of clang + sudo -E apt-add-repository "deb http://apt.llvm.org/${LLVM_OS}/ llvm-toolchain-${LLVM_OS} main" + fi + fi + echo ">>>>> APT: UPDATE.." + sudo -E apt-get -o Acquire::Retries=3 update + if test -n "${SOURCES}" ; then + echo ">>>>> APT: INSTALL SOURCES.." + for SOURCE in $SOURCES; do + sudo -E apt-add-repository ppa:$SOURCE + done + fi + echo ">>>>> APT: INSTALL ${PACKAGES}.." + sudo -E DEBIAN_FRONTEND=noninteractive apt-get -o Acquire::Retries=3 -y --no-install-suggests --no-install-recommends install ${PACKAGES} + + echo '==================================> INSTALL AND COMPILE' + set -e + export TRAVIS_BUILD_DIR=$(pwd) + export TRAVIS_BRANCH=${TRAVIS_BRANCH:-$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')} + export VCS_COMMIT_ID=$GITHUB_SHA + export GIT_COMMIT=$GITHUB_SHA + export REPO_NAME=$(basename $GITHUB_REPOSITORY) + export USER=$(whoami) + export CC=${CC:-gcc} + export PATH=~/.local/bin:/usr/local/bin:$PATH + + if [ "$JOB_BUILDTYPE" == "boost" ]; then + + echo '==================================> INSTALL' + + BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + git submodule update --init tools/build + git submodule update --init libs/config + git submodule update --init tools/boostdep + cp -r $TRAVIS_BUILD_DIR/* libs/optional + python tools/boostdep/depinst/depinst.py optional + ./bootstrap.sh + ./b2 headers + + echo '==================================> SCRIPT' + + echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam + ./b2 libs/optional/test toolset=$TOOLSET cxxstd=$CXXSTD + + fi + osx: + strategy: + fail-fast: false + matrix: + include: + - name: "TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,1 Job 15" + buildtype: "boost" + packages: "" + os: "macos-11" + cxx: "clang++" + sources: "" + llvm_os: "" + llvm_ver: "" + toolset: "clang" + compiler: "clang++" + cxxstd: "03,11,14,17,2a" + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + + - name: "osx" + shell: bash + env: + CXX: ${{ matrix.cxx }} + SOURCES: ${{ matrix.sources }} + LLVM_OS: ${{ matrix.llvm_os }} + LLVM_VER: ${{ matrix.llvm_ver }} + PACKAGES: ${{ matrix.packages }} + JOB_BUILDTYPE: ${{ matrix.buildtype }} + TOOLSET: ${{ matrix.toolset }} + COMPILER: ${{ matrix.compiler }} + CXXSTD: ${{ matrix.cxxstd }} + TRAVIS_BRANCH: ${{ github.base_ref }} + TRAVIS_OS_NAME: "osx" + run: | + echo '==================================> SETUP' + set -e + sudo mv /Library/Developer/CommandLineTools /Library/Developer/CommandLineTools.bck + echo '==================================> PACKAGES' + echo '==================================> INSTALL AND COMPILE' + set -e + export TRAVIS_BUILD_DIR=$(pwd) + export TRAVIS_BRANCH=${TRAVIS_BRANCH:-$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }')} + export VCS_COMMIT_ID=$GITHUB_SHA + export GIT_COMMIT=$GITHUB_SHA + export REPO_NAME=$(basename $GITHUB_REPOSITORY) + export USER=$(whoami) + export CC=${CC:-gcc} + export PATH=~/.local/bin:/usr/local/bin:$PATH + + if [ "$JOB_BUILDTYPE" == "boost" ]; then + + echo '==================================> INSTALL' + + BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + git submodule update --init tools/build + git submodule update --init libs/config + git submodule update --init tools/boostdep + cp -r $TRAVIS_BUILD_DIR/* libs/optional + python tools/boostdep/depinst/depinst.py optional + ./bootstrap.sh + ./b2 headers + + echo '==================================> SCRIPT' + + echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam + ./b2 libs/optional/test toolset=$TOOLSET cxxstd=$CXXSTD + + fi diff --git a/libs/optional/.travis.yml b/libs/optional/.travis.yml new file mode 100644 index 00000000..b6055859 --- /dev/null +++ b/libs/optional/.travis.yml @@ -0,0 +1,201 @@ +# Copyright 2016, 2017 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +language: cpp + +sudo: false + +python: "2.7" + +branches: + only: + - master + - develop + - /feature\/.*/ + +env: + matrix: + - BOGUS_JOB=true + +matrix: + + exclude: + - env: BOGUS_JOB=true + + include: + - os: linux + compiler: g++ + env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11 + + - os: linux + compiler: g++-4.7 + env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=03,11 + addons: + apt: + packages: + - g++-4.7 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-4.8 + env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=03,11 + addons: + apt: + packages: + - g++-4.8 + sources: + - ubuntu-toolchain-r-test + - os: linux + compiler: g++-4.9 + env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=03,11 + addons: + apt: + packages: + - g++-4.9 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-5 + env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=03,11,14,1z + addons: + apt: + packages: + - g++-5 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-6 + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=03,11,14,1z + addons: + apt: + packages: + - g++-6 + sources: + - ubuntu-toolchain-r-test + + - os: linux + dist: trusty + compiler: g++-7 + env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 + addons: + apt: + packages: + - g++-7 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++ + env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11 + + - os: linux + compiler: clang++-3.5 + env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-3.5 + - libstdc++-4.9-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.5 + + - os: linux + compiler: clang++-3.6 + env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-3.6 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.6 + + - os: linux + compiler: clang++-3.7 + env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-3.7 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.7 + + - os: linux + compiler: clang++-3.8 + env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-3.8 + - libstdc++-4.9-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.8 + + - os: linux + compiler: clang++-3.9 + env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-3.9 + - libstdc++-4.9-dev + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.9 + + - os: linux + dist: trusty + compiler: clang++-4.0 + env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-4.0 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-4.0 + + - os: linux + dist: trusty + compiler: clang++-5.0 + env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-5.0 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-5.0 + + - os: osx + compiler: clang++ + env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z + +install: + - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true + - cd .. + - git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + - cd boost-root + - git submodule update --init tools/build + - git submodule update --init libs/config + - git submodule update --init tools/boostdep + - cp -r $TRAVIS_BUILD_DIR/* libs/optional + - python tools/boostdep/depinst/depinst.py optional + - ./bootstrap.sh + - ./b2 headers + +script: + - |- + echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam + - ./b2 libs/optional/test toolset=$TOOLSET cxxstd=$CXXSTD + +notifications: + email: + on_success: always diff --git a/libs/optional/CMakeLists.txt b/libs/optional/CMakeLists.txt new file mode 100644 index 00000000..f60acf55 --- /dev/null +++ b/libs/optional/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright 2019 Mike Dev +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required( VERSION 3.5...3.20 ) +project( boost_optional VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX ) + +add_library( boost_optional INTERFACE ) +add_library( Boost::optional ALIAS boost_optional ) + +target_include_directories( boost_optional INTERFACE include ) + +target_link_libraries( boost_optional + INTERFACE + Boost::assert + Boost::config + Boost::core + Boost::detail + Boost::move + Boost::predef + Boost::static_assert + Boost::throw_exception + Boost::type_traits + Boost::utility +) diff --git a/libs/optional/README.md b/libs/optional/README.md new file mode 100644 index 00000000..4f73388d --- /dev/null +++ b/libs/optional/README.md @@ -0,0 +1,15 @@ +optional +======== + +A library for representing optional (nullable) objects in C++. + +```cpp +optional readInt(); // this function may return either an int or a not-an-int + +if (optional oi = readInt()) // did I get a real int + cout << "my int is: " << *oi; // use my int +else + cout << "I have no int"; +``` + +For more information refer to the documentation provided with this library. diff --git a/libs/optional/doc/00_optional.qbk b/libs/optional/doc/00_optional.qbk new file mode 100644 index 00000000..b99f8dc5 --- /dev/null +++ b/libs/optional/doc/00_optional.qbk @@ -0,0 +1,105 @@ +[library Boost.Optional + [quickbook 1.4] + [authors [Cacciola Carballal, Fernando Luis]] + [copyright 2003-2007 Fernando Luis Cacciola Carballal] + [copyright 2014-2023 Andrzej Krzemieński] + [category miscellaneous] + [id optional] + [dirname optional] + [purpose + Discriminated-union wrapper for optional values + ] + [source-mode c++] + [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]) + ] +] + +[/ Macros will be used for links so we have a central place to change them ] + + +[/ Cited Boost resources ] + +[def __BOOST_VARIANT__ [@../../../variant/index.html Boost.Variant]] +[def __BOOST_TUPLE__ [@../../../tuple/index.html Boost.Tuple]] +[def __BOOST_TRIBOOL__ [@../../../../doc/html/tribool.html boost::tribool]] + +[def __OPTIONAL_POINTEE__ [@../../../utility/OptionalPointee.html `OptionalPointee`]] +[def __COPY_CONSTRUCTIBLE__ [@../../../utility/CopyConstructible.html `CopyConstructible`]] +[def __MOVE_CONSTRUCTIBLE__ `MoveConstructible`] +[def __FUNCTION_EQUAL_POINTEES__ [@../../../utility/OptionalPointee.html#equal `equal_pointees()`]] +[def __FUNCTION_LESS_POINTEES__ [@../../../utility/OptionalPointee.html#less `less_pointees()`]] + +[def __IN_PLACE_FACTORY_HPP__ [@../../../../boost/utility/in_place_factory.hpp in_place_factory.hpp]] +[def __TYPED_IN_PLACE_FACTORY_HPP__ [@../../../../boost/utility/typed_in_place_factory.hpp typed_in_place_factory.hpp]] + +[/ Other web resources ] + +[def __HASKELL__ [@http://www.haskell.org/ Haskell]] +[def __STD_DEFAULT_CONSTRUCTIBLE__ [@https://en.cppreference.com/w/cpp/named_req/DefaultConstructible `DefaultConstructible`]] +[def __STD_LESS_THAN_COMPARABLE__ [@https://en.cppreference.com/w/cpp/named_req/LessThanComparable `LessThanComparable`]] +[def __STD_EQUALITY_COMPARABLE__ [@https://en.cppreference.com/w/cpp/named_req/EqualityComparable `EqualityComparable`]] +[def __SGI_GENERATOR__ [@http://www.rrsd.com/software_development/stl/stl/Generator.html `Generator`]] + + +[/ Icons ] + +[def __SPACE__ [$images/space.png]] +[def __GO_TO__ [$images/callouts/R.png]] + + +[section Introduction] +Class template `optional` is a wrapper for representing 'optional' (or 'nullable') objects who may not (yet) contain a valid value. Optional objects offer full value semantics; they are good for passing by value and usage inside STL containers. This is a header-only library. + +[heading Problem] +Suppose we want to read a parameter form a config file which represents some integral value, let's call it `"MaxValue"`. It is possible that this parameter is not specified; such situation is no error. It is valid to not specify the parameter and in that case the program is supposed to behave slightly differently. Also, suppose that any possible value of type `int` is a valid value for `"MaxValue"`, so we cannot just use `-1` to represent the absence of the parameter in the config file. + +[heading Solution] + +This is how you solve it with `boost::optional`: + + #include + + boost::optional getConfigParam(std::string name); // return either an int or a `not-an-int` + + int main() + { + if (boost::optional oi = getConfigParam("MaxValue")) // did I get a real int? + runWithMax(*oi); // use my int + else + runWithNoMax(); + } + +[endsect] + +[include 01_quick_start.qbk] +[section Tutorial] +[include 10_motivation.qbk] +[include 11_development.qbk] +[include 12_when_to_use.qbk] +[include 13_relational_operators.qbk] +[include 14_monadic_interface.qbk] +[include 15_io.qbk] +[include 16_optional_references.qbk] +[include 17_in_place_factories.qbk] +[include 18_gotchas.qbk] +[include 19_exception_safety.qbk] +[include 1A_type_requirements.qbk] +[include 1B_on_performance.qbk] +[endsect] +[section:reference Reference] +[include 21_ref_none.qbk] +[include 22_ref_bad_optional_access.qbk] +[include 23_ref_optional_io.qbk] +[include 24_ref_optional_fwd.qbk] +[section Header ] +[include 27_ref_optional_synopsis.qbk] +[include 28_ref_optional_semantics.qbk] +[endsect] +[include 29_ref_optional_convenience.qbk] +[endsect] +[include 90_dependencies.qbk] +[include 91_relnotes.qbk] +[include 92_acknowledgments.qbk] diff --git a/libs/optional/doc/01_quick_start.qbk b/libs/optional/doc/01_quick_start.qbk new file mode 100644 index 00000000..223603dd --- /dev/null +++ b/libs/optional/doc/01_quick_start.qbk @@ -0,0 +1,160 @@ +[/ + Boost.Optional + + Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal + Copyright (c) 2014 Andrzej Krzemienski + + 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) +] + + +[section Quick Start] + +[section Optional return values] + +Let's write and use a converter function that converts a `std::string` to an `int`. It is possible that for a given string (e.g. `"cat"`) there exists no value of type `int` capable of representing the conversion result. We do not consider such situation an error. We expect that the converter can be used only to check if the conversion is possible. A natural signature for this function can be: + + #include + boost::optional convert(const std::string& text); + +All necessary functionality can be included with one header ``. The above function signature means that the function can either return a value of type `int` or a flag indicating that no value of `int` is available. This does not indicate an error. It is like one additional value of `int`. This is how we can use our function: + + const std::string& text = /*... */; + boost::optional oi = convert(text); // move-construct + if (oi) // contextual conversion to bool + int i = *oi; // operator* + +In order to test if `optional` contains a value, we use the contextual conversion to type `bool`. Because of this we can combine the initialization of the optional object and the test into one instruction: + + if (boost::optional oi = convert(text)) + int i = *oi; + +We extract the contained value with `operator*` (and with `operator->` where it makes sense). An attempt to extract the contained value of an uninitialized optional object is an ['undefined behaviour] (UB). This implementation guards the call with `BOOST_ASSERT`. Therefore you should be sure that the contained value is there before extracting. For instance, the following code is reasonably UB-safe: + + int i = *convert("100"); + +This is because we know that string value `"100"` converts to a valid value of `int`. If you do not like this potential UB, you can use an alternative way of extracting the contained value: + + try { + int j = convert(text).value(); + } + catch (const boost::bad_optional_access&) { + // deal with it + } + +This version throws an exception upon an attempt to access a nonexistent contained value. If your way of dealing with the missing value is to use some default, like `0`, there exists a yet another alternative: + + int k = convert(text).value_or(0); + +This uses the `atoi`-like approach to conversions: if `text` does not represent an integral number just return `0`. Finally, you can provide a callback to be called when trying to access the contained value fails: + + int fallback_to_default() + { + cerr << "could not convert; using -1 instead" << endl; + return -1; + } + + int l = convert(text).value_or_eval(fallback_to_default); + +This will call the provided callback and return whatever the callback returns. The callback can have side effects: they will only be observed when the optional object does not contain a value. + +Now, let's consider how function `convert` can be implemented. + + boost::optional convert(const std::string& text) + { + std::stringstream s(text); + int i; + if ((s >> i) && s.get() == std::char_traits::eof()) + return i; + else + return boost::none; + } + +Observe the two return statements. `return i` uses the converting constructor that can create `optional` from `T`. Thus constructed optional object is initialized and its value is a copy of `i`. The other return statement uses another converting constructor from a special tag `boost::none`. It is used to indicate that we want to create an uninitialized optional object. + +[endsect] + +[section Optional automatic variables] + +We could write function `convert` in a slightly different manner, so that it has a single `return`-statement: + + boost::optional convert(const std::string& text) + { + boost::optional ans; + std::stringstream s(text); + int i; + if ((s >> i) && s.get() == std::char_traits::eof()) + ans = i; + + return ans; + } + +The default constructor of `optional` creates an uninitialized optional object. Unlike with `int`s you cannot have an `optional` in an indeterminate state. Its state is always well defined. Instruction `ans = i` initializes the optional object. It uses the 'mixed' assignment from `int`. In general, for `optional`, when an assignment from `T` is invoked, it can do two things. If the optional object is not initialized (our case here), it initializes the contained value using `T`'s copy constructor. If the optional object is already initialized, it assigns the new value to it using `T`'s copy assignment. +[endsect] + +[section Optional data members] + +Suppose we want to implement a ['lazy load] optimization. This is because we do not want to perform an expensive initialization of our `Resource` until (if at all) it is really used. We can do it this way: + + class Widget + { + mutable boost::optional resource_; + + public: + Widget() {} + + const Resource& getResource() const // not thread-safe + { + if (resource_ == boost::none) + resource_.emplace("resource", "arguments"); + + return *resource_; + } + }; + +`optional`'s default constructor creates an uninitialized optional. No call to `Resource`'s default constructor is attempted. `Resource` doesn't have to be __STD_DEFAULT_CONSTRUCTIBLE__. In function `getResource` we first check if `resource_` is initialized. This time we do not use the contextual conversion to `bool`, but a comparison with `boost::none`. These two ways are equivalent. Function `emplace` initializes the optional in-place by perfect-forwarding the arguments to the constructor of `Resource`. No copy- or move-construction is involved here. `Resource` doesn't even have to be `MoveConstructible`. + +[note Function `emplace` is only available on compilers that support rvalue references and variadic templates. If your compiler does not support these features and you still need to avoid any move-constructions, use [link boost_optional.tutorial.in_place_factories In-Place Factories].] + +[endsect] + +[section Bypassing unnecessary default construction] + +Suppose we have class `Date`, which does not have a default constructor: there is no good candidate for a default date. We have a function that returns two dates in form of a `boost::tuple`: + + boost::tuple getPeriod(); + +In other place we want to use the result of `getPeriod`, but want the two dates to be named: `begin` and `end`. We want to implement something like 'multiple return values': + + Date begin, end; // Error: no default ctor! + boost::tie(begin, end) = getPeriod(); + +The second line works already, this is the capability of __BOOST_TUPLE__ library, but the first line won't work. We could set some invented initial dates, but it is confusing and may be an unacceptable cost, given that these values will be overwritten in the next line anyway. This is where `optional` can help: + + boost::optional begin, end; + boost::tie(begin, end) = getPeriod(); + +It works because inside `boost::tie` a move-assignment from `T` is invoked on `optional`, which internally calls a move-constructor of `T`. +[endsect] + +[section Storage in containers] + +Suppose you want to ask users to choose some number (an `int`). One of the valid responses is to choose nothing, which is represented by an uninitialized `optional`. You want to make a histogram showing how many times each choice was made. You can use an `std::map`: + + std::map, int> choices; + + for (int i = 0; i < LIMIT; ++i) { + boost::optional choice = readChoice(); + ++choices[choice]; + } + +This works because `optional` is __STD_LESS_THAN_COMPARABLE__ whenever `T` is __STD_LESS_THAN_COMPARABLE__. +In this case the state of being uninitialized is treated as a yet another value of `T`, +which is compared less than any value of `T`. +`optional` can also be stored as a key in `std::unordered_map` and `std::unordered_set` +as it provides specializations for `std::hash`. +[endsect] + +[endsect] diff --git a/libs/optional/doc/10_motivation.qbk b/libs/optional/doc/10_motivation.qbk new file mode 100644 index 00000000..fe5b6dac --- /dev/null +++ b/libs/optional/doc/10_motivation.qbk @@ -0,0 +1,80 @@ +[/ + Boost.Optional + + Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal + Copyright (c) 2014 Andrzej Krzemienski + + 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) +] + +[section Motivation] + +Consider these functions which should return a value but which might not have +a value to return: + +* (A) `double sqrt(double n );` +* (B) `char get_async_input();` +* (C) `point polygon::get_any_point_effectively_inside();` + +There are different approaches to the issue of not having a value to return. + +A typical approach is to consider the existence of a valid return value as a +postcondition, so that if the function cannot compute the value to return, it +has either undefined behavior (and can use assert in a debug build) or uses a +runtime check and throws an exception if the postcondition is violated. This +is a reasonable choice for example, for function (A), because the lack of a +proper return value is directly related to an invalid parameter (out of domain +argument), so it is appropriate to require the callee to supply only parameters +in a valid domain for execution to continue normally. + +However, function (B), because of its asynchronous nature, does not fail just +because it can't find a value to return; so it is incorrect to consider such +a situation an error and assert or throw an exception. This function must +return, and somehow, must tell the callee that it is not returning a meaningful +value. + +A similar situation occurs with function (C): it is conceptually an error to +ask a ['null-area] polygon to return a point inside itself, but in many +applications, it is just impractical for performance reasons to treat this as +an error (because detecting that the polygon has no area might be too expensive +to be required to be tested previously), and either an arbitrary point +(typically at infinity) is returned, or some efficient way to tell the callee +that there is no such point is used. + +There are various mechanisms to let functions communicate that the returned +value is not valid. One such mechanism, which is quite common since it has +zero or negligible overhead, is to use a special value which is reserved to +communicate this. Classical examples of such special values are `EOF`, +`string::npos`, points at infinity, etc... + +When those values exist, i.e. the return type can hold all meaningful values +['plus] the ['signal] value, this mechanism is quite appropriate and well known. +Unfortunately, there are cases when such values do not exist. In these cases, +the usual alternative is either to use a wider type, such as `int` in place of +`char`; or a compound type, such as `std::pair`. + +Returning a `std::pair`, thus attaching a boolean flag to the result +which indicates if the result is meaningful, has the advantage that can be +turned into a consistent idiom since the first element of the pair can be +whatever the function would conceptually return. For example, the last two +functions could have the following interface: + + std::pair get_async_input(); + std::pair polygon::get_any_point_effectively_inside(); + +These functions use a consistent interface for dealing with possibly nonexistent +results: + + std::pair p = poly.get_any_point_effectively_inside(); + if ( p.second ) + flood_fill(p.first); + +However, not only is this quite a burden syntactically, it is also error prone +since the user can easily use the function result (first element of the pair) +without ever checking if it has a valid value. + +Clearly, we need a better idiom. + +[endsect] diff --git a/libs/optional/doc/11_development.qbk b/libs/optional/doc/11_development.qbk new file mode 100644 index 00000000..758619cc --- /dev/null +++ b/libs/optional/doc/11_development.qbk @@ -0,0 +1,251 @@ +[/ + Boost.Optional + + Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal + + 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) +] + +[section Design Overview] + +[section The models] + +In C++, we can ['declare] an object (a variable) of type `T`, and we can give this +variable an ['initial value] (through an ['initializer]. (cf. 8.5)). +When a declaration includes a non-empty initializer (an initial value is given), +it is said that the object has been initialized. +If the declaration uses an empty initializer (no initial value is given), and +neither default nor value initialization applies, it is said that the object is +[*uninitialized]. Its actual value exist but has an ['indeterminate initial value] +(cf. 8.5/11). +`optional` intends to formalize the notion of initialization (or lack of it) +allowing a program to test whether an object has been initialized and stating +that access to the value of an uninitialized object is undefined behavior. That +is, when a variable is declared as `optional` and no initial value is given, +the variable is ['formally] uninitialized. A formally uninitialized optional object +has conceptually no value at all and this situation can be tested at runtime. It +is formally ['undefined behavior] to try to access the value of an uninitialized +optional. An uninitialized optional can be assigned a value, in which case its initialization state changes to initialized. Furthermore, given the formal +treatment of initialization states in optional objects, it is even possible to +reset an optional to ['uninitialized]. + +In C++ there is no formal notion of uninitialized objects, which means that +objects always have an initial value even if indeterminate. +As discussed on the previous section, this has a drawback because you need +additional information to tell if an object has been effectively initialized. +One of the typical ways in which this has been historically dealt with is via +a special value: `EOF`, `npos`, -1, etc... This is equivalent to adding the +special value to the set of possible values of a given type. This super set of +`T` plus some ['nil_t]—where `nil_t` is some stateless POD—can be modeled in modern +languages as a [*discriminated union] of T and nil_t. Discriminated unions are +often called ['variants]. A variant has a ['current type], which in our case is either +`T` or `nil_t`. +Using the __BOOST_VARIANT__ library, this model can be implemented in terms of `boost::variant`. +There is precedent for a discriminated union as a model for an optional value: +the __HASKELL__ [*Maybe] built-in type constructor. Thus, a discriminated union +`T+nil_t` serves as a conceptual foundation. + +A `variant` follows naturally from the traditional idiom of extending +the range of possible values adding an additional sentinel value with the +special meaning of ['Nothing]. However, this additional ['Nothing] value is largely +irrelevant for our purpose since our goal is to formalize the notion of +uninitialized objects and, while a special extended value can be used to convey +that meaning, it is not strictly necessary in order to do so. + +The observation made in the last paragraph about the irrelevant nature of the +additional `nil_t` with respect to [_purpose] of `optional` suggests an +alternative model: a ['container] that either has a value of `T` or nothing. + +As of this writing I don't know of any precedent for a variable-size +fixed-capacity (of 1) stack-based container model for optional values, yet I +believe this is the consequence of the lack of practical implementations of +such a container rather than an inherent shortcoming of the container model. + +In any event, both the discriminated-union or the single-element container +models serve as a conceptual ground for a class representing optional—i.e. +possibly uninitialized—objects. +For instance, these models show the ['exact] semantics required for a wrapper +of optional values: + +Discriminated-union: + +* [*deep-copy] semantics: copies of the variant implies copies of the value. +* [*deep-relational] semantics: comparisons between variants matches both +current types and values +* If the variant's current type is `T`, it is modeling an ['initialized] optional. +* If the variant's current type is not `T`, it is modeling an ['uninitialized] +optional. +* Testing if the variant's current type is `T` models testing if the optional +is initialized +* Trying to extract a `T` from a variant when its current type is not `T`, models +the undefined behavior of trying to access the value of an uninitialized optional + +Single-element container: + +* [*deep-copy] semantics: copies of the container implies copies of the value. +* [*deep-relational] semantics: comparisons between containers compare container +size and if match, contained value +* If the container is not empty (contains an object of type `T`), it is modeling +an ['initialized] optional. +* If the container is empty, it is modeling an ['uninitialized] optional. +* Testing if the container is empty models testing if the optional is +initialized +* Trying to extract a `T` from an empty container models the undefined behavior +of trying to access the value of an uninitialized optional + +[endsect] + +[section The semantics] + +Objects of type `optional` are intended to be used in places where objects of +type `T` would but which might be uninitialized. Hence, `optional`'s purpose is +to formalize the additional possibly uninitialized state. +From the perspective of this role, `optional` can have the same operational +semantics of `T` plus the additional semantics corresponding to this special +state. +As such, `optional` could be thought of as a ['supertype] of `T`. Of course, we +can't do that in C++, so we need to compose the desired semantics using a +different mechanism. +Doing it the other way around, that is, making `optional` a ['subtype] of `T` +is not only conceptually wrong but also impractical: it is not allowed to +derive from a non-class type, such as a built-in type. + +We can draw from the purpose of `optional` the required basic semantics: + +* [*Default Construction:] To introduce a formally uninitialized wrapped +object. +* [*Direct Value Construction via copy:] To introduce a formally initialized +wrapped object whose value is obtained as a copy of some object. +* [*Deep Copy Construction:] To obtain a new yet equivalent wrapped object. +* [*Direct Value Assignment (upon initialized):] To assign a value to the +wrapped object. +* [*Direct Value Assignment (upon uninitialized):] To initialize the wrapped +object with a value obtained as a copy of some object. +* [*Assignment (upon initialized):] To assign to the wrapped object the value +of another wrapped object. +* [*Assignment (upon uninitialized):] To initialize the wrapped object with +value of another wrapped object. +* [*Deep Relational Operations (when supported by the type T):] To compare +wrapped object values taking into account the presence of uninitialized states. +* [*Value access:] To unwrap the wrapped object. +* [*Initialization state query:] To determine if the object is formally +initialized or not. +* [*Swap:] To exchange wrapped objects. (with whatever exception safety +guarantees are provided by `T`'s swap). +* [*De-initialization:] To release the wrapped object (if any) and leave the +wrapper in the uninitialized state. + +Additional operations are useful, such as converting constructors and +converting assignments, in-place construction and assignment, and safe +value access via a pointer to the wrapped object or null. + +[endsect] + +[section The Interface] + +Since the purpose of optional is to allow us to use objects with a formal +uninitialized additional state, the interface could try to follow the +interface of the underlying `T` type as much as possible. In order to choose +the proper degree of adoption of the native `T` interface, the following must +be noted: Even if all the operations supported by an instance of type `T` are +defined for the entire range of values for such a type, an `optional` +extends such a set of values with a new value for which most +(otherwise valid) operations are not defined in terms of `T`. + +Furthermore, since `optional` itself is merely a `T` wrapper (modeling a `T` +supertype), any attempt to define such operations upon uninitialized optionals +will be totally artificial w.r.t. `T`. + +This library chooses an interface which follows from `T`'s interface only for +those operations which are well defined (w.r.t the type `T`) even if any of the +operands are uninitialized. These operations include: construction, +copy-construction, assignment, swap and relational operations. + +For the value access operations, which are undefined (w.r.t the type `T`) when +the operand is uninitialized, a different interface is chosen (which will be +explained next). + +Also, the presence of the possibly uninitialized state requires additional +operations not provided by `T` itself which are supported by a special interface. + +[heading Lexically-hinted Value Access in the presence of possibly +uninitialized optional objects: The operators * and ->] + +A relevant feature of a pointer is that it can have a [*null pointer value]. +This is a ['special] value which is used to indicate that the pointer is not +referring to any object at all. In other words, null pointer values convey +the notion of nonexistent objects. + +This meaning of the null pointer value allowed pointers to became a ['de +facto] standard for handling optional objects because all you have to do +to refer to a value which you don't really have is to use a null pointer +value of the appropriate type. Pointers have been used for decades—from +the days of C APIs to modern C++ libraries—to ['refer] to optional (that is, +possibly nonexistent) objects; particularly as optional arguments to a +function, but also quite often as optional data members. + +The possible presence of a null pointer value makes the operations that +access the pointee's value possibly undefined, therefore, expressions which +use dereference and access operators, such as: `( *p = 2 )` and `( p->foo() )`, +implicitly convey the notion of optionality, and this information is tied to +the ['syntax] of the expressions. That is, the presence of operators `*` and `->` +tell by themselves —without any additional context— that the expression will +be undefined unless the implied pointee actually exist. + +Such a ['de facto] idiom for referring to optional objects can be formalized +in the form of a concept: the __OPTIONAL_POINTEE__ concept. +This concept captures the syntactic usage of operators `*`, `->` and +contextual conversion to `bool` to convey the notion of optionality. + +However, pointers are good to [_refer] to optional objects, but not particularly +good to handle the optional objects in all other respects, such as initializing +or moving/copying them. The problem resides in the shallow-copy of pointer +semantics: if you need to effectively move or copy the object, pointers alone +are not enough. The problem is that copies of pointers do not imply copies of +pointees. For example, as was discussed in the motivation, pointers alone +cannot be used to return optional objects from a function because the object +must move outside from the function and into the caller's context. + +A solution to the shallow-copy problem that is often used is to resort to +dynamic allocation and use a smart pointer to automatically handle the details +of this. For example, if a function is to optionally return an object `X`, it can +use `shared_ptr` as the return value. However, this requires dynamic allocation +of `X`. If `X` is a built-in or small POD, this technique is very poor in terms of +required resources. Optional objects are essentially values so it is very +convenient to be able to use automatic storage and deep-copy semantics to +manipulate optional values just as we do with ordinary values. Pointers do +not have this semantics, so are inappropriate for the initialization and +transport of optional values, yet are quite convenient for handling the access +to the possible undefined value because of the idiomatic aid present in the +__OPTIONAL_POINTEE__ concept incarnated by pointers. + + +[heading Optional as a model of OptionalPointee] + +For value access operations `optional<>` uses operators `*` and `->` to +lexically warn about the possibly uninitialized state appealing to the +familiar pointer semantics w.r.t. to null pointers. + +[caution +However, it is particularly important to note that `optional<>` objects +are not pointers. [_`optional<>` is not, and does not model, a pointer]. +] + +For instance, `optional<>` does not have shallow-copy so does not alias: +two different optionals never refer to the ['same] value unless `T` itself is +a reference (but may have ['equivalent] values). +The difference between an `optional` and a pointer must be kept in mind, +particularly because the semantics of relational operators are different: +since `optional` is a value-wrapper, relational operators are deep: they +compare optional values; but relational operators for pointers are shallow: +they do not compare pointee values. +As a result, you might be able to replace `optional` by `T*` on some +situations but not always. Specifically, on generic code written for both, +you cannot use relational operators directly, and must use the template +functions __FUNCTION_EQUAL_POINTEES__ and __FUNCTION_LESS_POINTEES__ instead. + +[endsect] + +[endsect] diff --git a/libs/optional/doc/12_when_to_use.qbk b/libs/optional/doc/12_when_to_use.qbk new file mode 100644 index 00000000..095079ce --- /dev/null +++ b/libs/optional/doc/12_when_to_use.qbk @@ -0,0 +1,37 @@ + +[section When to use Optional] + +It is recommended to use `optional` in situations where there is exactly one, clear (to all parties) reason for having no value of type `T`, and where the lack of value is as natural as having any regular value of `T`. One example of such situation is asking the user in some GUI form to optionally specify some limit on an `int` value, but the user is allowed to say 'I want the number not to be constrained by the maximum'. +For another example, consider a config parameter specifying how many threads the application should launch. Leaving this parameter unspecified means that the application should decide itself. For yet another example, consider a function returning the index of the smallest element in a `vector`. We need to be prepared for the situation, where the `vector` is empty. Therefore a natural signature for such function would be: + + template + optional find_smallest_elem(const std::vector& vec); + +Here, having received an empty `vec` and having no `size_t` to return is not a ['failure] but a ['normal], albeit irregular, situation. + +Another typical situation is to indicate that we do not have a value yet, but we expect to have it later. This notion can be used in implementing solutions like lazy initialization or a two-phase initialization. + +`optional` can be used to take a non-__STD_DEFAULT_CONSTRUCTIBLE__ type `T` and create a sibling type with a default constructor. This is a way to add a ['null-state] to any type that doesn't have it already. + +Sometimes type `T` already provides a built-in null-state, but it may still be useful to wrap it into `optional`. Consider `std::string`. When you read a piece of text from a GUI form or a DB table, it is hardly ever that the empty string indicates anything else but a missing text. And some data bases do not even distinguish between a null string entry and a non-null string of length 0. Still, it may be practical to use `optional` to indicate in the returned type that we want to treat the empty string in a special dedicated program path: + + if(boost::optional name = ask_user_name()) { + assert(*name != ""); + logon_as(*name); + } + else { + skip_logon(); + } + +In the example above, the assertion indicates that if we choose to use this technique, we must translate the empty string state to an optional object with no contained value (inside function `ask_user_name`). + +[heading Not recommended usages] + +It is not recommended to use `optional` to indicate that we were not able to compute a value because of a ['failure]. It is difficult to define what a failure is, but it usually has one common characteristic: an associated information on the cause of the failure. This can be the type and member data of an exception object, or an error code. It is a bad design to signal a failure and not inform about the cause. If you do not want to use exceptions, and do not like the fact that by returning error codes you cannot return the computed value, you can use [@https://github.com/ptal/Boost.Expected Expected] library. It is sort of __BOOST_VARIANT__ that contains either a computed value or a reason why the computation failed. + +Sometimes the distinction into what is a failure and what is a valid but irregular result is blurry and depends on a particular usage and personal preference. Consider a function that converts a `string` to an `int`. Is it a failure that you cannot convert? It might in some cases, but in other you may call it exactly for the purpose of figuring out if a given `string` is convertible, and you are not even interested in the resulting value. Sometimes when a conversion fails you may not consider it a failure, but you need to know why it cannot be converted; for instance at which character it is determined that the conversion is impossible. In this case returning `optional` will not suffice. Finally, there is a use case where an input string that does not represent an `int` is not a failure condition, but during the conversion we use resources whose acquisition may fail. In that case the natural representation is to both return `optional` and signal failure: + + optional convert1(const string& str); // throws + expected> convert2(const string& str); // return either optional or error + +[endsect] diff --git a/libs/optional/doc/13_relational_operators.qbk b/libs/optional/doc/13_relational_operators.qbk new file mode 100644 index 00000000..614690af --- /dev/null +++ b/libs/optional/doc/13_relational_operators.qbk @@ -0,0 +1,37 @@ + +[section Relational operators] + +Type `optional` is __STD_EQUALITY_COMPARABLE__ whenever `T` is __STD_EQUALITY_COMPARABLE__. Two optional objects containing a value compare in the same way as their contained values. The uninitialized state of `optional` is treated as a distinct value, equal to itself, and unequal to any value of type `T`: + + boost::optional oN = boost::none; + boost::optional o0 = 0; + boost::optional o1 = 1; + + assert(oN != o0); + assert(o1 != oN); + assert(o0 != o1); + assert(oN == oN); + assert(o0 == o0); + +The converting constructor from `T` as well as from `boost::none` implies the existence and semantics of the mixed comparison between `T` and `optional` as well as between `none_t` and `optional`: + + assert(oN != 0); + assert(o1 != boost::none); + assert(o0 != 1); + assert(oN == boost::none); + assert(o0 == 0); + +This mixed comparison has a practical interpretation, which is occasionally useful: + + boost::optional choice = ask_user(); + if (choice == 2) + start_procedure_2(); + +In the above example, the meaning of the comparison is 'user chose number 2'. If user chose nothing, he didn't choose number 2. + +In case where `optional` is compared to `none`, it is not required that `T` be __STD_EQUALITY_COMPARABLE__. + +In a similar manner, type `optional` is __STD_LESS_THAN_COMPARABLE__ whenever `T` is __STD_LESS_THAN_COMPARABLE__. The optional object containing no value is compared less than any value of `T`. To illustrate this, if the default ordering of `size_t` is {`0`, `1`, `2`, ...}, the default ordering of `optional` is {`boost::none`, `0`, `1`, `2`, ...}. This order does not have a practical interpretation. The goal is to have any semantically correct default ordering in order for `optional` to be usable in ordered associative containers (wherever `T` is usable). + +Mixed relational operators are the only case where the contained value of an optional object can be inspected without the usage of value accessing function (`operator*`, `value`, `value_or`). +[endsect] diff --git a/libs/optional/doc/14_monadic_interface.qbk b/libs/optional/doc/14_monadic_interface.qbk new file mode 100644 index 00000000..21731e48 --- /dev/null +++ b/libs/optional/doc/14_monadic_interface.qbk @@ -0,0 +1,45 @@ +[section Monadic interface] + +The monadic interface of `optional` allows the application of functions +to optional values without resorting to the usage of explicit `if`-statements. + +Function `map` takes a function mapping type `T` onto type `U` and maps an `optional` +onto an `optional` using the provided function. + + int length(const string& s){ return s.size(); }; + + optional null{}, thin{""}, word{"word"}; + assert (null.map(length) == none); + assert (thin.map(length) == 0); + assert (word.map(length) == 4); + +Function `flat_map` is similar, but it requires the function to return an +`optional` for some type `V`. This `optional` becomes the return type of +`flat_map`. + + optional first_char(const string& s) { + if (s.empty()) return none; + else return s[0]; + }; + + optional null{}, thin{""}, word{"word"}; + assert (null.flat_map(first_char) == none); + assert (thin.flat_map(first_char) == none); + assert (word.flat_map(first_char) == 'w'); + +These functions can be combined in one expression reflecting a chain of computations: + + auto get_contents(path p) -> optional; + auto trim(string) -> string; + auto length(string) -> int; + + auto trimmed_size_of(optional p) -> int + { + return p.flat_map(get_contents) + .map(trim) + .map(length) + .value_or(0); + } + + +[endsect] diff --git a/libs/optional/doc/15_io.qbk b/libs/optional/doc/15_io.qbk new file mode 100644 index 00000000..b6484d8c --- /dev/null +++ b/libs/optional/doc/15_io.qbk @@ -0,0 +1,37 @@ + +[section IO operators] + +It is possible to use `optional` with IO streams, provided that `T` can be used with streams. IOStream operators are defined in a separate header. + +`` +#include +#include + +int main() +{ + boost::optional o1 = 1, oN = boost::none; + std::cout << o1; + std::cin >> oN; +} +`` + +The current implementation does not guarantee any particular output. What it guarantees is that if streaming out and then back in `T` gives the same value, then streaming out and then back in `optional` will also give back the same result: + +`` +#include +#include +#include + +int main() +{ + boost::optional o1 = 1, oN = boost::none; + boost::optional x1, x2; + std::stringstream s; + s << o1 << oN; + s >> x1 >> x2; + assert (o1 == x1); + assert (oN == x2); +} +`` + +[endsect] diff --git a/libs/optional/doc/16_optional_references.qbk b/libs/optional/doc/16_optional_references.qbk new file mode 100644 index 00000000..cdb541ad --- /dev/null +++ b/libs/optional/doc/16_optional_references.qbk @@ -0,0 +1,123 @@ + +[section Optional references] + +[section Overview] + +This library allows the template parameter `T` to be of reference type: +`T&`, and to some extent, `T const&`. + +However, since references are not real objects some restrictions apply and +some operations are not available in this case: + +* Converting constructors +* Converting assignment +* InPlace construction +* InPlace assignment +* Value-access via pointer + +Also, even though `optional` treats it wrapped pseudo-object much as +a real value, a true real reference is stored so aliasing will occur: + +* Copies of `optional` will copy the references but all these references +will nonetheless refer to the same object. +* Value-access will actually provide access to the referenced object +rather than the reference itself. + +[caution On compilers that do not conform to Standard C++ rules of reference binding, some operations on optional references are disabled in order to prevent subtle bugs. For more details see [link boost_optional.dependencies_and_portability.optional_reference_binding Dependencies and Portability section].] + +[heading Rvalue references] + +Rvalue references and lvalue references to const have the ability in C++ to extend the life time of a temporary they bind to. Optional references do not have this capability, therefore to avoid surprising effects it is not possible to initialize an optional references from a temporary. Optional rvalue references are disabled altogether. Also, the initialization and assignment of an optional reference to const from rvalue reference is disabled. + + const int& i = 1; // legal + optional oi = 1; // illegal + +[endsect] + +[section Rebinding semantics for assignment of optional references] + +If you assign to an ['uninitialized ] `optional` the effect is to bind (for +the first time) to the object. Clearly, there is no other choice. + + int x = 1 ; + int& rx = x ; + optional ora ; + optional orb(x) ; + ora = orb ; // now 'ora' is bound to 'x' through 'rx' + *ora = 2 ; // Changes value of 'x' through 'ora' + assert(x==2); + +If you assign to a bare C++ reference, the assignment is forwarded to the +referenced object; its value changes but the reference is never rebound. + + int a = 1 ; + int& ra = a ; + int b = 2 ; + int& rb = b ; + ra = rb ; // Changes the value of 'a' to 'b' + assert(a==b); + b = 3 ; + assert(ra!=b); // 'ra' is not rebound to 'b' + +Now, if you assign to an ['initialized ] `optional`, the effect is to +[*rebind] to the new object instead of assigning the referee. This is unlike +bare C++ references. + + int a = 1 ; + int b = 2 ; + int& ra = a ; + int& rb = b ; + optional ora(ra) ; + optional orb(rb) ; + ora = orb ; // 'ora' is rebound to 'b' + *ora = 3 ; // Changes value of 'b' (not 'a') + assert(a==1); + assert(b==3); + +[heading Rationale] + +Rebinding semantics for the assignment of ['initialized ] `optional` references has +been chosen to provide [*consistency among initialization states] even at the +expense of lack of consistency with the semantics of bare C++ references. +It is true that `optional` strives to behave as much as possible as `U` +does whenever it is initialized; but in the case when `U` is `T&`, doing so would +result in inconsistent behavior w.r.t to the lvalue initialization state. + +Imagine `optional` forwarding assignment to the referenced object (thus +changing the referenced object value but not rebinding), and consider the +following code: + + optional a = get(); + int x = 1 ; + int& rx = x ; + optional b(rx); + a = b ; + +What does the assignment do? + +If `a` is ['uninitialized], the answer is clear: it binds to `x` (we now have +another reference to `x`). +But what if `a` is already ['initialized]? it would change the value of the +referenced object (whatever that is); which is inconsistent with the other +possible case. + +If `optional` would assign just like `T&` does, you would never be able to +use Optional's assignment without explicitly handling the previous +initialization state unless your code is capable of functioning whether +after the assignment, `a` aliases the same object as `b` or not. + +That is, you would have to discriminate in order to be consistent. + +If in your code rebinding to another object is not an option, then it is very +likely that binding for the first time isn't either. In such case, assignment +to an ['uninitialized ] `optional` shall be prohibited. It is quite possible +that in such a scenario it is a precondition that the lvalue must be already +initialized. If it isn't, then binding for the first time is OK +while rebinding is not which is IMO very unlikely. +In such a scenario, you can assign the value itself directly, as in: + + assert(!!opt); + *opt=value; + +[endsect] +[endsect] diff --git a/libs/optional/doc/17_in_place_factories.qbk b/libs/optional/doc/17_in_place_factories.qbk new file mode 100644 index 00000000..1a18f22b --- /dev/null +++ b/libs/optional/doc/17_in_place_factories.qbk @@ -0,0 +1,139 @@ + +[section In-Place Factories] + +One of the typical problems with wrappers and containers is that their +interfaces usually provide an operation to initialize or assign the +contained object as a copy of some other object. This not only requires the +underlying type to be __COPY_CONSTRUCTIBLE__, but also requires the existence of +a fully constructed object, often temporary, just to follow the copy from: + + struct X + { + X ( int, std::string ) ; + } ; + + class W + { + X wrapped_ ; + + public: + + W ( X const& x ) : wrapped_(x) {} + } ; + + void foo() + { + // Temporary object created. + W ( X(123,"hello") ) ; + } + +A solution to this problem is to support direct construction of the +contained object right in the container's storage. +In this scheme, the user only needs to supply the arguments to the +constructor to use in the wrapped object construction. + + class W + { + X wrapped_ ; + + public: + + W ( X const& x ) : wrapped_(x) {} + W ( int a0, std::string a1) : wrapped_(a0,a1) {} + } ; + + void foo() + { + // Wrapped object constructed in-place + // No temporary created. + W (123,"hello") ; + } + +A limitation of this method is that it doesn't scale well to wrapped +objects with multiple constructors nor to generic code were the constructor +overloads are unknown. + +The solution presented in this library is the family of [*InPlaceFactories] +and [*TypedInPlaceFactories]. +These factories are a family of classes which encapsulate an increasing +number of arbitrary constructor parameters and supply a method to construct +an object of a given type using those parameters at an address specified by +the user via placement new. + +For example, one member of this family looks like: + + template + class TypedInPlaceFactory2 + { + A0 m_a0 ; A1 m_a1 ; + + public: + + TypedInPlaceFactory2( A0 const& a0, A1 const& a1 ) : m_a0(a0), m_a1(a1) {} + + void construct ( void* p ) { new (p) T(m_a0,m_a1) ; } + } ; + +A wrapper class aware of this can use it as: + + class W + { + X wrapped_ ; + + public: + + W ( X const& x ) : wrapped_(x) {} + W ( TypedInPlaceFactory2 const& fac ) { fac.construct(&wrapped_) ; } + } ; + + void foo() + { + // Wrapped object constructed in-place via a TypedInPlaceFactory. + // No temporary created. + W ( TypedInPlaceFactory2(123,"hello")) ; + } + +The factories are divided in two groups: + +* [_TypedInPlaceFactories]: those which take the target type as a primary +template parameter. +* [_InPlaceFactories]: those with a template `construct(void*)` member +function taking the target type. + +Within each group, all the family members differ only in the number of +parameters allowed. + +This library provides an overloaded set of helper template functions to +construct these factories without requiring unnecessary template parameters: + + template + InPlaceFactoryN in_place ( A0 const& a0, ..., AN const& aN) ; + + template + TypedInPlaceFactoryN in_place ( T const& a0, A0 const& a0, ..., AN const& aN) ; + +In-place factories can be used generically by the wrapper and user as follows: + + class W + { + X wrapped_ ; + + public: + + W ( X const& x ) : wrapped_(x) {} + + template< class InPlaceFactory > + W ( InPlaceFactory const& fac ) { fac.template construct(&wrapped_) ; } + + } ; + + void foo() + { + // Wrapped object constructed in-place via a InPlaceFactory. + // No temporary created. + W ( in_place(123,"hello") ) ; + } + +The factories are implemented in the headers: __IN_PLACE_FACTORY_HPP__ and __TYPED_IN_PLACE_FACTORY_HPP__ + +[endsect] diff --git a/libs/optional/doc/18_gotchas.qbk b/libs/optional/doc/18_gotchas.qbk new file mode 100644 index 00000000..d38abf33 --- /dev/null +++ b/libs/optional/doc/18_gotchas.qbk @@ -0,0 +1,111 @@ +[section Gotchas] + +[section A note about optional] + +`optional` should be used with special caution and consideration. + +First, it is functionally similar to a tristate boolean (false, maybe, true) +—such as __BOOST_TRIBOOL__— except that in a tristate boolean, the maybe state +[_represents a valid value], unlike the corresponding state of an uninitialized +`optional`. +It should be carefully considered if an `optional` instead of a `tribool` +is really needed. + +Second, although `optional<>` provides a contextual conversion to `bool` in C++11, + this falls back to an implicit conversion on older compilers. This conversion refers + to the initialization state and not to the contained value. Using `optional` + can lead to subtle errors due to the implicit `bool` conversion: + + void foo ( bool v ) ; + void bar() + { + optional v = try(); + + // The following intended to pass the value of 'v' to foo(): + foo(v); + // But instead, the initialization state is passed + // due to a typo: it should have been foo(*v). + } + +The only implicit conversion is to `bool`, and it is safe in the sense that +typical integral promotions don't apply (i.e. if `foo()` takes an `int` +instead, it won't compile). + +Third, mixed comparisons with `bool` work differently than similar mixed comparisons between pointers and `bool`, so the results might surprise you: + + optional oEmpty(none), oTrue(true), oFalse(false); + + if (oEmpty == none); // renders true + if (oEmpty == false); // renders false! + if (oEmpty == true); // renders false! + + if (oFalse == none); // renders false + if (oFalse == false); // renders true! + if (oFalse == true); // renders false + + if (oTrue == none); // renders false + if (oTrue == false); // renders false + if (oTrue == true); // renders true + +In other words, for `optional<>`, the following assertion does not hold: + + assert((opt == false) == (!opt)); +[endsect] + +[section Moved-from `optional`] + +When an optional object that contains a value is moved from (is a source of move constructor or assignment) it still contains a value and its contained value is left in a moved-from state. This can be illustrated with the following example. + + optional> opi {std::make_unique(1)}; + optional> opj = std::move(opi); + assert (opi); + assert (*opi == nullptr); + +Quite a lot of people expect that when an object that contains a value is moved from, its contained value should be destroyed. This is not so, for performance reasons. Current semantics allow the implementation of `boost::optional` to be trivially copyable when `T` is trivial. +[endsect] + +[section Mixed relational comparisons] + +Because `T` is convertible to `optional` and because `optional` is __STD_LESS_THAN_COMPARABLE__ when `T` is __STD_LESS_THAN_COMPARABLE__, +you can sometimes get an unexpected runtime result where you would rather expect a compiler error: + + optional Flight_plan::weight(); // sometimes no weight can be returned + + bool is_aircraft_too_heavy(Flight_plan const& p) + { + return p.weight() > p.aircraft().max_weight(); // compiles! + } // returns false when the optional contains no value + +[endsect] + +[section False positive with -Wmaybe-uninitialized] + +Sometimes on GCC compilers below version 5.1 you may get an -Wmaybe-uninitialized warning when compiling with option -02 on a perfectly valid `boost::optional` usage. For instance in this program: + + #include + + boost::optional getitem(); + + int main(int argc, const char *[]) + { + boost::optional a = getitem(); + boost::optional b; + + if (argc > 0) + b = argc; + + if (a != b) + return 1; + + return 0; + } + +This is a bug in the compiler. As a workaround (provided in [@http://stackoverflow.com/questions/21755206/how-to-get-around-gcc-void-b-4-may-be-used-uninitialized-in-this-funct this Stack Overflow question]) use the following way of initializing an optional containing no value: + + boost::optional b = boost::make_optional(false, int()); + +This is obviously redundant, but makes the warning disappear. + +[endsect] + +[endsect] diff --git a/libs/optional/doc/19_exception_safety.qbk b/libs/optional/doc/19_exception_safety.qbk new file mode 100644 index 00000000..98c4f13c --- /dev/null +++ b/libs/optional/doc/19_exception_safety.qbk @@ -0,0 +1,57 @@ + +[section Exception Safety Guarantees] + +This library assumes that `T`'s destructor does not throw exceptions. If it does, the behaviour of many operations on `optional` is undefined. + +The following mutating operations never throw exceptions: + +* `optional::operator= ( none_t ) noexcept` +* `optional::reset() noexcept` + +In addition, the following constructors and the destructor never throw exceptions: + +* `optional::optional() noexcept` +* `optional::optional( none_t ) noexcept` + + +Regarding the following assignment functions: + +* `optional::operator= ( optional const& )` +* `optional::operator= ( T const& )` +* `template optional::operator= ( optional const& )` +* `template optional::operator= ( InPlaceFactory const& )` +* `template optional::operator= ( TypedInPlaceFactory const& ) ` +* `optional::reset( T const& )` + +They forward calls to the corresponding `T`'s constructors or assignments (depending on whether the optional object is initialized or not); so if both `T`'s constructor and the assignment provide strong exception safety guarantee, `optional`'s assignment also provides strong exception safety guarantee; otherwise we only get the basic guarantee. Additionally, if both involved `T`'s constructor and the assignment never throw, `optional`'s assignment also never throws. + +Unless `T`'s constructor or assignment throws, assignments to `optional` do not throw anything else on its own. A throw during assignment never changes the initialization state of any optional object involved: + + + optional opt1(val1); + optional opt2(val2); + assert(opt1); + assert(opt2); + + try + { + opt1 = opt2; // throws + } + catch(...) + { + assert(opt1); + assert(opt2); + } + +This also applies to move assignments/constructors. However, move operations are made no-throw more often. + +Operation `emplace` provides basic exception safety guarantee. If it throws, the optional object becomes uninitialized regardless of its initial state, and its previous contained value (if any) is destroyed. It doesn't call any assignment or move/copy constructor on `T`. + +[heading Swap] + +Unless `swap` on optional is customized, its primary implementation forwards calls to `T`'s `swap` or move constructor (depending on the initialization state of the optional objects). Thus, if both `T`'s `swap` and move constructor never throw, `swap` on `optional` never throws. similarly, if both `T`'s `swap` and move constructor offer strong guarantee, `swap` on `optional` also offers a strong guarantee. + +In case `swap` on optional is customized, the call to `T`'s move constructor are replaced with the calls to `T`'s default constructor followed by `swap`. (This is more useful on older compilers that do not support move semantics, when one wants to achieve stronger exception safety guarantees.) In this case the exception safety guarantees for `swap` are reliant on the guarantees of `T`'s `swap` and default constructor +[endsect] + + diff --git a/libs/optional/doc/1A_type_requirements.qbk b/libs/optional/doc/1A_type_requirements.qbk new file mode 100644 index 00000000..c7182cc2 --- /dev/null +++ b/libs/optional/doc/1A_type_requirements.qbk @@ -0,0 +1,38 @@ + +[section Type requirements] + +The very minimum requirement of `optional` is that `T` is a complete type and that it has a publicly accessible destructor. `T` doesn't even need to be constructible. You can use a very minimum interface: + + optional o; // uninitialized + assert(o == none); // check if initialized + assert(!o); // + o.value(); // always throws + +But this is practically useless. In order for `optional` to be able to do anything useful and offer all the spectrum of ways of accessing the contained value, `T` needs to have at least one accessible constructor. In that case you need to initialize the optional object with function `emplace()`, or if your compiler does not support it, resort to [link boost_optional.tutorial.in_place_factories In-Place Factories]: + + optional o; + o.emplace("T", "ctor", "params"); + +If `T` is __MOVE_CONSTRUCTIBLE__, `optional` is also __MOVE_CONSTRUCTIBLE__ and can be easily initialized from an rvalue of type `T` and be passed by value: + + optional o = make_T(); + optional p = optional(); + +If `T` is __COPY_CONSTRUCTIBLE__, `optional` is also __COPY_CONSTRUCTIBLE__ and can be easily initialized from an lvalue of type `T`: + + T v = make_T(); + optional o = v; + optional p = o; + +If `T` is not `MoveAssignable`, it is still possible to reset the value of `optional` using function `emplace()`: + + optional o = make_T(); + o.emplace(make_another_T()); + +If `T` is `Moveable` (both __MOVE_CONSTRUCTIBLE__ and `MoveAssignable`) then `optional` is also `Moveable` and additionally can be constructed and assigned from an rvalue of type `T`. + +Similarly, if `T` is `Copyable` (both __COPY_CONSTRUCTIBLE__ and `CopyAssignable`) then `optional` is also `Copyable` and additionally can be constructed and assigned from an lvalue of type `T`. + +`T` ['is not] required to be __STD_DEFAULT_CONSTRUCTIBLE__. + +[endsect] diff --git a/libs/optional/doc/1B_on_performance.qbk b/libs/optional/doc/1B_on_performance.qbk new file mode 100644 index 00000000..6b4b3e70 --- /dev/null +++ b/libs/optional/doc/1B_on_performance.qbk @@ -0,0 +1,156 @@ + +[section Performance considerations] + +Technical details aside, the memory layout of `optional` for a generic `T` is more-less this: + + template + class optional + { + bool _initialized; + std::aligned_storage_t _storage; + }; + +Lifetime of the `T` inside `_storage` is manually controlled with placement-`new`s and pseudo-destructor calls. However, for scalar `T`s we use a different way of storage, by simply holding a `T`: + + template + class optional + { + bool _initialized; + T _storage; + }; + +We call it a ['direct] storage. This makes `optional` a trivially-copyable type for scalar `T`s. This only works for compilers that support defaulted functions (including defaulted move assignment and constructor). On compilers without defaulted functions we still use the direct storage, but `optional` is no longer recognized as trivially-copyable. Apart from scalar types, we leave the programmer a way of customizing her type, so that it is recognized by `optional` as candidate for optimized storage, by specializing type trait `boost::optional_config::optional_uses_direct_storage_for`: + + struct X // not trivial + { + X() {} + }; + + namespace boost { namespace optional_config { + + template <> struct optional_uses_direct_storage_for : boost::true_type {}; + + }} + + +[heading Controlling the size] + +For the purpose of the following analysis, considering memory layouts, we can think of it as: + + template + class optional + { + bool _initialized; + T _storage; + }; + +Given type `optional`, and assuming that `sizeof(int) == 4`, we will get `sizeof(optional) == 8`. This is so because of the alignment rules, for our two members we get the following alignment: + +[$images/opt_align1.png] + +This means you can fit twice as many `int`s as `optional`s into the same space of memory. Therefore, if the size of the objects is critical for your application (e.g., because you want to utilize your CPU cache in order to gain performance) and you have determined you are willing to trade the code clarity, it is recommended that you simply go with type `int` and use some 'magic value' to represent ['not-an-int], or use something like [@https://github.com/akrzemi1/markable `markable`] library. + +Even if you cannot spare any value of `int` to represent ['not-an-int] (e.g., because every value is useful, or you do want to signal ['not-an-int] explicitly), at least for `Trivial` types you should consider storing the value and the `bool` flag representing the ['null-state] separately. Consider the following class: + + struct Record + { + optional _min; + optional _max; + }; + +Its memory layout can be depicted as follows: + +[$images/opt_align2.png] + +This is exactly the same as if we had the following members: + + struct Record + { + bool _has_min; + int _min; + bool _has_max; + int _max; + }; + +But when they are stored separately, we at least have an option to reorder them like this: + + struct Record + { + bool _has_min; + bool _has_max; + int _min; + int _max; + }; + +Which gives us the following layout (and smaller total size): + +[$images/opt_align3.png] + +Sometimes it requires detailed consideration what data we make optional. In our case above, if we determine that both minimum and maximum value can be provided or not provided together, but one is never provided without the other, we can make only one optional member: + + struct Limits + { + int _min; + int _max; + }; + + struct Record + { + optional _limits; + }; + +This would give us the following layout: + +[$images/opt_align4.png] + +[heading Optional function parameters] + +Having function parameters of type `const optional&` may incur certain unexpected run-time cost connected to copy construction of `T`. Consider the following code. + + void fun(const optional& v) + { + if (v) doSomethingWith(*v); + else doSomethingElse(); + } + + int main() + { + optional ov; + Big v; + fun(none); + fun(ov); // no copy + fun(v); // copy constructor of Big + } + +No copy elision or move semantics can save us from copying type `Big` here. Not that we need any copy, but this is how `optional` works. In order to avoid copying in this case, one could provide second overload of `fun`: + + void fun(const Big& v) + { + doSomethingWith(v); + } + + int main() + { + optional ov; + Big v; + fun(ov); // no copy + fun(v); // no copy: second overload selected + } + +Alternatively, you could consider using an optional reference instead: + + void fun(optional v) // note where the reference is + { + if (v) doSomethingWith(*v); + else doSomethingElse(); + } + + int main() + { + optional ov; + Big v; + fun(none); + fun(ov); // doesn't compile + fun(v); // no copy + } +[endsect] diff --git a/libs/optional/doc/21_ref_none.qbk b/libs/optional/doc/21_ref_none.qbk new file mode 100644 index 00000000..65eaa81f --- /dev/null +++ b/libs/optional/doc/21_ref_none.qbk @@ -0,0 +1,31 @@ +[/ + Boost.Optional + + Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal + Copyright (c) 2015 Andrzej Krzemienski + + 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) +] + +[section Header ] + +[section Synopsis] +``` +namespace boost { + +class none_t {/* see below */}; + +inline constexpr none_t none (/* see below */); + +} // namespace boost +``` + +Class `none_t` is meant to serve as a tag for selecting appropriate overloads of from `optional`'s interface. It is an empty, trivially copyable class with disabled default constructor. + +Constant `none` is used to indicate an optional object that does not contain a value in initialization, assignment and relational operations of `optional`. + +[endsect] + +[endsect] diff --git a/libs/optional/doc/22_ref_bad_optional_access.qbk b/libs/optional/doc/22_ref_bad_optional_access.qbk new file mode 100644 index 00000000..e9291347 --- /dev/null +++ b/libs/optional/doc/22_ref_bad_optional_access.qbk @@ -0,0 +1,40 @@ +[/ + Boost.Optional + + Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal + Copyright (c) 2015 Andrzej Krzemienski + + 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) +] + +[section Header ] + +[section Synopsis] +``` +namespace boost { + +class bad_optional_access : public std::logic_error +{ +public: + bad_optional_access(); ``[link reference_bad_optional_access_constructor __GO_TO__]`` +}; + +} // namespace boost +``` +[endsect] + +[section Detailed semantics] + +__SPACE__ + +[#reference_bad_optional_access_constructor] + +`bad_optional_access();` + +* [*Effect:] Constructs an object of class `bad_optional_access`. +* [*Postconditions:] `what()` returns an implementation-defined NTBS. + +[endsect] +[endsect] diff --git a/libs/optional/doc/23_ref_optional_io.qbk b/libs/optional/doc/23_ref_optional_io.qbk new file mode 100644 index 00000000..22b25833 --- /dev/null +++ b/libs/optional/doc/23_ref_optional_io.qbk @@ -0,0 +1,74 @@ +[/ + Boost.Optional + + Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal + Copyright (c) 2015 Andrzej Krzemienski + + 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) +] + +[section:io_header Header ] + +[section:io_synop Synopsis] +``` +#include +#include +#include + +namespace boost { + +template + std::basic_ostream& + operator<<(std::basic_ostream& out, optional const& v); ``[link reference_operator_ostream __GO_TO__]`` + + template + std::basic_ostream& + operator<<(std::basic_ostream& out, none_t const&); ``[link reference_operator_ostream_none __GO_TO__]`` + +template + std::basic_istream& + operator>>(std::basic_istream& in, optional& v); ``[link reference_operator_istream __GO_TO__]`` + +} // namespace boost +``` + +[endsect] + +[section:io_semantics Detailed semantics] + + +[#reference_operator_ostream] + + +`template ` [br] + std::basic_ostream&` [br] + operator<<(std::basic_ostream& out, optional const& v);` + +* [*Effect:] Outputs an implementation-defined string. The output contains the information about whether the optional object contains a value or not. If `v` contains a value, the output contains result of calling `out << *v`. +* [*Returns:] `out`. + +__SPACE__ +[#reference_operator_ostream_none] + +`template ` [br] + std::basic_ostream&` [br] + operator<<(std::basic_ostream& out, none_t);` + +* [*Effect:] Outputs an implementation-defined string. +* [*Returns:] `out`. + +__SPACE__ +[#reference_operator_istream] + +`template ` [br] + std::basic_ostream&` [br] + operator>>(std::basic_istream& in, optional& v);` + +* [*Requires:] `T` is __STD_DEFAULT_CONSTRUCTIBLE__ and __MOVE_CONSTRUCTIBLE__. +* [*Effect:] Reads the value of optional object from `in`. If the string representation indicates that the optional object should contain a value, `v` contains a value and its contained value is obtained as if by default-constructing an object `o` of type `T` and then calling `in >> o`; otherwise `v` does not contain a value, and the previously contained value (if any) has been destroyed. +* [*Returns:] `out`. + +[endsect] +[endsect] diff --git a/libs/optional/doc/24_ref_optional_fwd.qbk b/libs/optional/doc/24_ref_optional_fwd.qbk new file mode 100644 index 00000000..03187f94 --- /dev/null +++ b/libs/optional/doc/24_ref_optional_fwd.qbk @@ -0,0 +1,32 @@ +[/ + Boost.Optional + + Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal + Copyright (c) 2015 Andrzej Krzemienski + + 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) +] + +[section Header ] + +[section Synopsis] +``` +namespace boost { + +template class optional ; + +template void swap ( optional& , optional& ); + +template struct optional_swap_should_use_default_constructor ; + +} // namespace boost +``` + +This header only contains declarations. + +[endsect] + + +[endsect] diff --git a/libs/optional/doc/27_ref_optional_synopsis.qbk b/libs/optional/doc/27_ref_optional_synopsis.qbk new file mode 100644 index 00000000..d86967bd --- /dev/null +++ b/libs/optional/doc/27_ref_optional_synopsis.qbk @@ -0,0 +1,303 @@ +[/ + Boost.Optional + + Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal + + 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) +] + + +[#ref_header_optional_optional_hpp] [section:header_optional_optional Synopsis] + + ```// In Header: <`[@boost:/boost/optional/optional.hpp boost/optional/optional.hpp]'''>'''`` + + namespace boost { + + class in_place_init_t { /* see below */ } ; ``[link reference_in_place_init __GO_TO__]`` + const in_place_init_t in_place_init ( /* see below */ ) ; + + class in_place_init_if_t { /*see below*/ } ; ``[link reference_in_place_init_if __GO_TO__]`` + const in_place_init_if_t in_place_init_if ( /*see below*/ ) ; + + template + class optional ; ``[link reference_operator_template __GO_TO__]`` + + template + class optional ; ``[link reference_operator_template_spec __GO_TO__]`` + + template inline bool operator == ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_equal_optional_optional __GO_TO__]`` + + template inline bool operator != ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_not_equal_optional_optional __GO_TO__]`` + + template inline bool operator < ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_less_optional_optional __GO_TO__]`` + + template inline bool operator > ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_greater_optional_optional __GO_TO__]`` + + template inline bool operator <= ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_less_or_equal_optional_optional __GO_TO__]`` + + template inline bool operator >= ( optional const& x, optional const& y ) ; ``[link reference_operator_compare_greater_or_equal_optional_optional __GO_TO__]`` + + template inline bool operator == ( optional const& x, none_t ) noexcept ; ``[link reference_operator_compare_equal_optional_none __GO_TO__]`` + + template inline bool operator != ( optional const& x, none_t ) noexcept ; ``[link reference_operator_compare_not_equal_optional_none __GO_TO__]`` + + template inline optional make_optional ( T const& v ) ; ``[link reference_make_optional_value __GO_TO__]`` + + template inline optional> make_optional ( T && v ) ; ``[link reference_make_optional_rvalue __GO_TO__]`` + + template inline optional make_optional ( bool condition, T const& v ) ; ``[link reference_make_optional_bool_value __GO_TO__]`` + + template inline optional> make_optional ( bool condition, T && v ) ; ``[link reference_make_optional_bool_rvalue __GO_TO__]`` + + template inline auto get_optional_value_or ( optional const& opt, typename optional::reference_const_type def ) -> typename optional::reference_const_type; ``[link reference_free_get_value_or __GO_TO__]`` + + template inline auto get_optional_value_or ( optional const& opt, typename optional::reference_type def ) -> typename optional::reference_type ; ``[link reference_free_get_value_or __GO_TO__]`` + + template inline T const& get ( optional const& opt ) ; ``[link reference_optional_get __GO_TO__]`` + + template inline T& get ( optional & opt ) ; ``[link reference_optional_get __GO_TO__]`` + + template inline T const* get ( optional const* opt ) ; ``[link reference_optional_get __GO_TO__]`` + + template inline T* get ( optional* opt ) ; ``[link reference_optional_get __GO_TO__]`` + + template inline auto get_pointer ( optional const& opt ) -> ``['see below]``; ``[link reference_free_get_pointer __GO_TO__]`` + + template inline auto get_pointer ( optional & opt ) -> ``['see below]``; ``[link reference_free_get_pointer __GO_TO__]`` + + template inline void swap( optional& x, optional& y ) ; ``[link reference_swap_optional_optional __GO_TO__]`` + + template inline void swap( optional& x, optional& y ) ; ``[link reference_swap_optional_reference __GO_TO__]`` + + } // namespace boost + + namespace std { + + template + struct hash > ; ``[link reference_std_hash_spec __GO_TO__]`` + + template + struct hash > ; ``[link reference_std_hash_spec __GO_TO__]`` + + } // namespace std + + +[endsect] + + +[section:header_optional_in_place_init Initialization tags] + +[#reference_in_place_init] +[#reference_in_place_init_if] + + namespace boost { + + class in_place_init_t { /* see below */ } ; + const in_place_init_t in_place_init ( /* see below */ ) ; + + class in_place_init_if_t { /*see below*/ } ; + const in_place_init_if_t in_place_init_if ( /*see below*/ ) ; + + } + +Classes `in_place_init_t` and `in_place_init_if_t` are empty classes. Their purpose is to control overload resolution in the initialization of optional objects. +They are empty, trivially copyable classes with disabled default constructor. + +[endsect] + +[section:header_optional_optional_values Optional Values] + +[#reference_operator_template] + + template + class optional + { + public : + + typedef T value_type ; + typedef T & reference_type ; + typedef T const& reference_const_type ; + typedef T && rval_reference_type ; + typedef T * pointer_type ; + typedef T const* pointer_const_type ; + + optional () noexcept ; ``[link reference_optional_constructor __GO_TO__]`` + + optional ( none_t ) noexcept ; ``[link reference_optional_constructor_none_t __GO_TO__]`` + + optional ( T const& v ) ; ``[link reference_optional_constructor_value __GO_TO__]`` + + optional ( T&& v ) ; ``[link reference_optional_constructor_move_value __GO_TO__]`` + + optional ( bool condition, T const& v ) ; ``[link reference_optional_constructor_bool_value __GO_TO__]`` + + optional ( optional const& rhs ) ; ``[link reference_optional_constructor_optional __GO_TO__]`` + + optional ( optional&& rhs ) noexcept(``['see below]``) ; ``[link reference_optional_move_constructor_optional __GO_TO__]`` + + template explicit optional ( optional const& rhs ) ; ``[link reference_optional_constructor_other_optional __GO_TO__]`` + + template explicit optional ( optional&& rhs ) ; ``[link reference_optional_move_constructor_other_optional __GO_TO__]`` + + template explicit optional ( in_place_init_t, Args&&... args ) ; ``[link reference_optional_in_place_init __GO_TO__]`` + + template explicit optional ( in_place_init_if_t, bool condition, Args&&... args ) ; ``[link reference_optional_in_place_init_if __GO_TO__]`` + + template explicit optional ( InPlaceFactory const& f ) ; ``[link reference_optional_constructor_factory __GO_TO__]`` + + template explicit optional ( TypedInPlaceFactory const& f ) ; ``[link reference_optional_constructor_factory __GO_TO__]`` + + optional& operator = ( none_t ) noexcept ; ``[link reference_optional_operator_equal_none_t __GO_TO__]`` + + optional& operator = ( T const& v ) ; ``[link reference_optional_operator_equal_value __GO_TO__]`` + + optional& operator = ( T&& v ) ; ``[link reference_optional_operator_move_equal_value __GO_TO__]`` + + optional& operator = ( optional const& rhs ) ; ``[link reference_optional_operator_equal_optional __GO_TO__]`` + + optional& operator = ( optional&& rhs ) noexcept(``['see below]``) ; ``[link reference_optional_operator_move_equal_optional __GO_TO__]`` + + template optional& operator = ( optional const& rhs ) ; ``[link reference_optional_operator_equal_other_optional __GO_TO__]`` + + template optional& operator = ( optional&& rhs ) ; ``[link reference_optional_operator_move_equal_other_optional __GO_TO__]`` + + template void emplace ( Args&&... args ) ; ``[link reference_optional_emplace __GO_TO__]`` + + template optional& operator = ( InPlaceFactory const& f ) ; ``[link reference_optional_operator_equal_factory __GO_TO__]`` + + template optional& operator = ( TypedInPlaceFactory const& f ) ; ``[link reference_optional_operator_equal_factory __GO_TO__]`` + + T const& get() const ; ``[link reference_optional_get __GO_TO__]`` + T& get() ; ``[link reference_optional_get __GO_TO__]`` + + T const* operator ->() const ; ``[link reference_optional_operator_arrow __GO_TO__]`` + T* operator ->() ; ``[link reference_optional_operator_arrow __GO_TO__]`` + + T const& operator *() const& ; ``[link reference_optional_operator_asterisk __GO_TO__]`` + T& operator *() & ; ``[link reference_optional_operator_asterisk __GO_TO__]`` + T&& operator *() && ; ``[link reference_optional_operator_asterisk_move __GO_TO__]`` + + T const& value() const& ; ``[link reference_optional_value __GO_TO__]`` + T& value() & ; ``[link reference_optional_value __GO_TO__]`` + T&& value() && ; ``[link reference_optional_value_move __GO_TO__]`` + + template T value_or( U && v ) const& ; ``[link reference_optional_value_or __GO_TO__]`` + template T value_or( U && v ) && ; ``[link reference_optional_value_or_move __GO_TO__]`` + + template T value_or_eval( F f ) const& ; ``[link reference_optional_value_or_call __GO_TO__]`` + template T value_or_eval( F f ) && ; ``[link reference_optional_value_or_call_move __GO_TO__]`` + + template auto map( F f ) const& -> ``['see below]``; ``[link reference_optional_map __GO_TO__]`` + template auto map( F f ) & -> ``['see below]``; ``[link reference_optional_map __GO_TO__]`` + template auto map( F f ) && -> ``['see below]``; ``[link reference_optional_map_move __GO_TO__]`` + + template auto flat_map( F f ) const& -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]`` + template auto flat_map( F f ) & -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]`` + template auto flat_map( F f ) && -> ``['see below]``; ``[link reference_optional_flat_map_move __GO_TO__]`` + + T const* get_ptr() const ; ``[link reference_optional_get_ptr __GO_TO__]`` + T* get_ptr() ; ``[link reference_optional_get_ptr __GO_TO__]`` + + bool has_value() const noexcept ; ``[link reference_optional_operator_bool __GO_TO__]`` + + explicit operator bool() const noexcept ; ``[link reference_optional_operator_bool __GO_TO__]`` + + bool operator!() const noexcept ; ``[link reference_optional_operator_not __GO_TO__]`` + + void reset() noexcept ; ``[link reference_optional_reset __GO_TO__]`` + + // deprecated methods + + // (deprecated) + void reset ( T const& ) ; ``[link reference_optional_reset_value __GO_TO__]`` + + // (deprecated) + bool is_initialized() const ; ``[link reference_optional_is_initialized __GO_TO__]`` + + // (deprecated) + T const& get_value_or( T const& default ) const ; ``[link reference_optional_get_value_or_value __GO_TO__]`` + }; + + +[endsect] + + +[section:header_optional_optional_refs Optional References] + +[#reference_operator_template_spec] + template + class optional // specialization for lvalue references + { + public : + + typedef T& value_type; + typedef T& reference_type; + typedef T& reference_const_type; // no const propagation + typedef T& rval_reference_type; + typedef T* pointer_type; + typedef T* pointer_const_type; // no const propagation + + optional () noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]`` + + optional ( none_t ) noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]`` + + template optional(R&& r) noexcept ; ``[link reference_optional_ref_value_ctor __GO_TO__]`` + + template optional(bool cond, R&& r) noexcept ; ``[link reference_optional_ref_cond_value_ctor __GO_TO__]`` + + optional ( optional const& rhs ) noexcept ; ``[link reference_optional_ref_copy_ctor __GO_TO__]`` + + template explicit optional ( optional const& rhs ) noexcept ; ``[link reference_optional_ref_ctor_from_opt_U __GO_TO__]`` + + optional& operator = ( none_t ) noexcept ; ``[link reference_optional_ref_assign_none_t __GO_TO__]`` + + optional& operator = ( optional const& rhs ) noexcept; ``[link reference_optional_ref_copy_assign __GO_TO__]`` + + template optional& operator = ( optional const& rhs ) noexcept ; ``[link reference_optional_ref_assign_optional_U __GO_TO__]`` + + template optional& operator = (R&& r) noexcept ; ``[link reference_optional_ref_assign_R __GO_TO__]`` + + template void emplace ( R&& r ) noexcept ; ``[link reference_optional_ref_emplace_R __GO_TO__]`` + + T& get() const ; ``[link reference_optional_ref_get __GO_TO__]`` + T& operator *() const ; ``[link reference_optional_ref_get __GO_TO__]`` + + T* operator ->() const ; ``[link reference_optional_ref_arrow __GO_TO__]`` + + T& value() const& ; ``[link reference_optional_ref_value __GO_TO__]`` + + template T& value_or( R && r ) const noexcept ; ``[link reference_optional_ref_value_or __GO_TO__]`` + + template T& value_or_eval( F f ) const ; ``[link reference_optional_ref_value_or_eval __GO_TO__]`` + + template auto map( F f ) const -> ``['see below]``; ``[link reference_optional_ref_map __GO_TO__]`` + + template auto flat_map( F f ) const -> ``['see below]``; ``[link reference_optional_ref_flat_map __GO_TO__]`` + + T* get_ptr() const noexcept ; ``[link reference_optional_ref_get_ptr __GO_TO__]`` + + bool has_value() const noexcept ; ``[link reference_optional_ref_operator_bool __GO_TO__]`` + + explicit operator bool() const noexcept ; ``[link reference_optional_ref_operator_bool __GO_TO__]`` + + bool operator!() const noexcept ; ``[link reference_optional_ref_operator_not __GO_TO__]`` + + void reset() noexcept ; ``[link reference_optional_ref_reset __GO_TO__]`` + + // deprecated methods + + // (deprecated) + template void reset ( R && r ) noexcept ; ``[link reference_optional_ref_reset_value __GO_TO__]`` + + // (deprecated) + bool is_initialized() const noexcept ; ``[link reference_optional_ref_is_initialized __GO_TO__]`` + + // (deprecated) + template T& get_value_or( R && r ) constnoexcept; ``[link reference_optional_ref_get_value_or_value __GO_TO__]`` + + private: + T* ref; // exposition only + }; +[endsect] diff --git a/libs/optional/doc/28_ref_optional_semantics.qbk b/libs/optional/doc/28_ref_optional_semantics.qbk new file mode 100644 index 00000000..947592d5 --- /dev/null +++ b/libs/optional/doc/28_ref_optional_semantics.qbk @@ -0,0 +1,1444 @@ +[/ + Boost.Optional + + Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal + + 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) +] + + +[section Detailed Semantics - Optional Values] + +[note +The following section contains various `assert()` which are used only to show +the postconditions as sample code. It is not implied that the type `T` must +support each particular expression but that if the expression is supported, +the implied condition holds. +] + + +__SPACE__ + +[#reference_optional_constructor] + +[: `optional::optional() noexcept;`] + +* [*Effect:] Default-Constructs an `optional`. +* [*Postconditions:] `*this` is [_uninitialized]. +* [*Notes:] T's default constructor [_is not] called. +* [*Example:] +`` +optional def ; +assert ( !def ) ; +`` + +__SPACE__ + +[#reference_optional_constructor_none_t] + +[: `optional::optional( none_t ) noexcept;`] + +* [*Effect:] Constructs an `optional` uninitialized. +* [*Postconditions:] `*this` is [_uninitialized]. +* [*Notes:] `T`'s default constructor [_is not] called. The expression +`boost::none` denotes an instance of `boost::none_t` that can be used as +the parameter. +* [*Example:] +`` +#include +optional n(none) ; +assert ( !n ) ; +`` + +__SPACE__ + +[#reference_optional_constructor_value] + +[: `optional::optional( T const& v )`] + +* [*Requires:] `is_copy_constructible::value` is `true`. +* [*Effect:] Directly-Constructs an `optional`. +* [*Postconditions:] `*this` is [_initialized] and its value is a ['copy] +of `v`. +* [*Throws:] Whatever `T::T( T const& )` throws. +* [*Notes: ] `T::T( T const& )` is called. +* [*Exception Safety:] Exceptions can only be thrown during +`T::T( T const& );` in that case, this constructor has no effect. +* [*Example:] +`` +T v; +optional opt(v); +assert ( *opt == v ) ; +`` + + +__SPACE__ + +[#reference_optional_constructor_move_value] + +[: `optional::optional( T&& v )`] + +* [*Requires:] `is_move_constructible::value` is `true`. +* [*Effect:] Directly-Move-Constructs an `optional`. +* [*Postconditions:] `*this` is [_initialized] and its value is move-constructed from `v`. +* [*Throws:] Whatever `T::T( T&& )` throws. +* [*Notes: ] `T::T( T&& )` is called. +* [*Exception Safety:] Exceptions can only be thrown during +`T::T( T&& );` in that case, the state of `v` is determined by exception safety guarantees for `T::T(T&&)`. +* [*Example:] +`` +T v1, v2; +optional opt(std::move(v1)); +assert ( *opt == v2 ) ; +`` + + +__SPACE__ + +[#reference_optional_constructor_bool_value] + +[: `optional::optional( bool condition, T const& v ) ;` ] + +* If condition is true, same as: + +[: `optional::optional( T const& v )`] + +* otherwise, same as: + +[: `optional::optional()`] + + +__SPACE__ + +[#reference_optional_constructor_optional] + +[: `optional::optional( optional const& rhs );`] + +* [*Requires:] `is_copy_constructible::value` is `true`. +* [*Effect:] Copy-Constructs an `optional`. +* [*Postconditions:] If rhs is initialized, `*this` is initialized and +its value is a ['copy] of the value of `rhs`; else `*this` is uninitialized. +* [*Throws:] Whatever `T::T( T const& )` throws. +* [*Notes:] If rhs is initialized, `T::T(T const& )` is called. +* [*Exception Safety:] Exceptions can only be thrown during +`T::T( T const& );` in that case, this constructor has no effect. +* [*Example:] +`` +optional uninit ; +assert (!uninit); + +optional uinit2 ( uninit ) ; +assert ( uninit2 == uninit ); + +optional init( T(2) ); +assert ( *init == T(2) ) ; + +optional init2 ( init ) ; +assert ( init2 == init ) ; +`` + + +__SPACE__ + +[#reference_optional_move_constructor_optional] + +[: `optional::optional( optional&& rhs ) noexcept(`['see below]`);`] + +* [*Requires:] `is_move_constructible::value` is `true`. +* [*Effect:] Move-constructs an `optional`. +* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and +its value is move constructed from `rhs`; else `*this` is uninitialized. +* [*Throws:] Whatever `T::T( T&& )` throws. +* [*Remarks:] The expression inside `noexcept` is equivalent to `is_nothrow_move_constructible::value`. +* [*Notes:] If `rhs` is initialized, `T::T( T && )` is called. +* [*Exception Safety:] Exceptions can only be thrown during +`T::T( T&& );` in that case, `rhs` remains initialized and the value of `*rhs` is determined by exception safety of `T::T(T&&)`. +* [*Example:] +`` +optional> uninit ; +assert (!uninit); + +optional> uinit2 ( std::move(uninit) ) ; +assert ( uninit2 == uninit ); + +optional> init( std::unique_ptr(new T(2)) ); +assert ( **init == T(2) ) ; + +optional> init2 ( std::move(init) ) ; +assert ( init ); +assert ( *init == nullptr ); +assert ( init2 ); +assert ( **init2 == T(2) ) ; +`` + + +__SPACE__ + +[#reference_optional_constructor_other_optional] + +[: `template explicit optional::optional( optional const& rhs );`] + +* [*Effect:] Copy-Constructs an `optional`. +* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and its +value is a ['copy] of the value of rhs converted to type `T`; else `*this` is +uninitialized. +* [*Throws:] Whatever `T::T( U const& )` throws. +* [*Notes: ] `T::T( U const& )` is called if `rhs` is initialized, which requires a +valid conversion from `U` to `T`. +* [*Exception Safety:] Exceptions can only be thrown during `T::T( U const& );` +in that case, this constructor has no effect. +* [*Example:] +`` +optional x(123.4); +assert ( *x == 123.4 ) ; + +optional y(x) ; +assert( *y == 123 ) ; +`` + +__SPACE__ + +[#reference_optional_move_constructor_other_optional] + +[: `template explicit optional::optional( optional&& rhs );`] + +* [*Effect:] Move-constructs an `optional`. +* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and its +value is move-constructed from `*rhs`; else `*this` is +uninitialized. +* [*Throws:] Whatever `T::T( U&& )` throws. +* [*Notes: ] `T::T( U&& )` is called if `rhs` is initialized, which requires a +valid conversion from `U` to `T`. +* [*Exception Safety:] Exceptions can only be thrown during `T::T( U&& );` +in that case, `rhs` remains initialized and the value of `*rhs` is determined by exception safety guarantee of `T::T( U&& )`. +* [*Example:] +`` +optional x(123.4); +assert ( *x == 123.4 ) ; + +optional y(std::move(x)) ; +assert( *y == 123 ) ; +`` + +__SPACE__ + +[#reference_optional_in_place_init] + +[: `template explicit optional::optional( in_place_init_t, Args&&... ars );`] + +* [*Requires:] `is_constructible_v` is `true`. +* [*Effect:] Initializes the contained value as if direct-non-list-initializing an object of type `T` with the +arguments `std::forward(args)...`. +* [*Postconditions:] `*this` is initialized. +* [*Throws:] Any exception thrown by the selected constructor of `T`. +* [*Notes: ] `T` need not be __MOVE_CONSTRUCTIBLE__. On compilers that do not support variadic templates or rvalue references, this constuctor is available in limited functionality. For details [link optional_emplace_workaround see here]. + +* [*Example:] +`` +// creates an std::mutex using its default constructor +optional om {in_place_init}; +assert (om); + +// creates a unique_lock by calling unique_lock(*om, std::defer_lock) +optional> ol {in_place_init, *om, std::defer_lock}; +assert (ol); +assert (!ol->owns_lock()); +`` + +__SPACE__ + +[#reference_optional_in_place_init_if] + +[: `template explicit optional::optional( in_place_init_if_t, bool condition, Args&&... ars );`] + +* [*Requires:] `is_constructible_v` is `true`. +* [*Effect:] If `condition` is `true`, initializes the contained value as if direct-non-list-initializing an object of type `T` with the arguments `std::forward(args)...`. +* [*Postconditions:] `bool(*this) == condition`. +* [*Throws:] Any exception thrown by the selected constructor of `T`. +* [*Notes: ] `T` need not be __MOVE_CONSTRUCTIBLE__. On compilers that do not support variadic templates or rvalue references, this constuctor is available in limited functionality. For details [link optional_emplace_workaround see here]. + +* [*Example:] +`` +optional> ov1 {in_place_init_if, false, 3, "A"}; +assert (!ov1); + +optional> ov2 {in_place_init_if, true, 3, "A"}; +assert (ov2); +assert (ov2->size() == 3); +`` + +__SPACE__ + +[#reference_optional_constructor_factory] + +[: `template explicit optional::optional( InPlaceFactory const& f );`] +[: `template explicit optional::optional( TypedInPlaceFactory const& f );`] + +* [*Effect:] Constructs an `optional` with a value of `T` obtained from the +factory. +* [*Postconditions: ] `*this` is [_initialized] and its value is ['directly given] +from the factory `f` (i.e., the value [_is not copied]). +* [*Throws:] Whatever the `T` constructor called by the factory throws. +* [*Notes:] See [link boost_optional.tutorial.in_place_factories In-Place Factories] +* [*Exception Safety:] Exceptions can only be thrown during the call to +the `T` constructor used by the factory; in that case, this constructor has +no effect. +* [*Example:] +`` +class C { C ( char, double, std::string ) ; } ; + +C v('A',123.4,"hello"); + +optional x( in_place ('A', 123.4, "hello") ); // InPlaceFactory used +optional y( in_place('A', 123.4, "hello") ); // TypedInPlaceFactory used + +assert ( *x == v ) ; +assert ( *y == v ) ; +`` + +__SPACE__ + +[#reference_optional_operator_equal_none_t] + +[: `optional& optional::operator= ( none_t ) noexcept;`] + +* [*Effect:] If `*this` is initialized destroys its contained value. +* [*Postconditions: ] `*this` is uninitialized. + +__SPACE__ + +[#reference_optional_operator_equal_value] + +[: `optional& optional::operator= ( T const& rhs ) ;`] + +* [*Effect:] Assigns the value `rhs` to an `optional`. +* [*Postconditions: ] `*this` is initialized and its value is a ['copy] of `rhs`. +* [*Throws:] Whatever `T::operator=( T const& )` or `T::T(T const&)` throws. +* [*Notes:] If `*this` was initialized, `T`'s assignment operator is used, +otherwise, its copy-constructor is used. +* [*Exception Safety:] In the event of an exception, the initialization +state of `*this` is unchanged and its value unspecified as far as `optional` +is concerned (it is up to `T`'s `operator=()`). If `*this` is initially +uninitialized and `T`'s ['copy constructor] fails, `*this` is left properly +uninitialized. +* [*Example:] +`` +T x; +optional def ; +optional opt(x) ; + +T y; +def = y ; +assert ( *def == y ) ; +opt = y ; +assert ( *opt == y ) ; +`` + + +__SPACE__ + +[#reference_optional_operator_move_equal_value] + +[: `optional& optional::operator= ( T&& rhs ) ;`] + +* [*Effect:] Moves the value `rhs` to an `optional`. +* [*Postconditions: ] `*this` is initialized and its value is moved from `rhs`. +* [*Throws:] Whatever `T::operator=( T&& )` or `T::T(T &&)` throws. +* [*Notes:] If `*this` was initialized, `T`'s move-assignment operator is used, +otherwise, its move-constructor is used. +* [*Exception Safety:] In the event of an exception, the initialization +state of `*this` is unchanged and its value unspecified as far as `optional` +is concerned (it is up to `T`'s `operator=()`). If `*this` is initially +uninitialized and `T`'s ['move constructor] fails, `*this` is left properly +uninitialized. +* [*Example:] +`` +T x; +optional def ; +optional opt(x) ; + +T y1, y2, yR; +def = std::move(y1) ; +assert ( *def == yR ) ; +opt = std::move(y2) ; +assert ( *opt == yR ) ; +`` + + +__SPACE__ + +[#reference_optional_operator_equal_optional] + +[: `optional& optional::operator= ( optional const& rhs ) ;`] + +* [*Requires:] `T` is __COPY_CONSTRUCTIBLE__ and `CopyAssignable`. +* [*Effects:] +[table + [] + [[][[*`*this` contains a value]][[*`*this` does not contain a value]]] + [[[*`rhs` contains a value]][assigns `*rhs` to the contained value][initializes the contained value as if direct-initializing an object of type `T` with `*rhs`]] + [[[*`rhs` does not contain a value]][destroys the contained value by calling `val->T::~T()`][no effect]] +] +* [*Returns:] `*this`; +* [*Postconditions:] `bool(rhs) == bool(*this)`. +* [*Exception Safety:] If any exception is thrown, the initialization state of `*this` and `rhs` remains unchanged. +If an exception is thrown during the call to `T`'s copy constructor, no effect. +If an exception is thrown during the call to `T`'s copy assignment, the state of its contained value is as defined by the exception safety guarantee of `T`'s copy assignment. +* [*Example:] +`` +T v; +optional opt(v); +optional def ; + +opt = def ; +assert ( !def ) ; +// previous value (copy of 'v') destroyed from within 'opt'. +`` + + +__SPACE__ + +[#reference_optional_operator_move_equal_optional] + +[: `optional& optional::operator= ( optional&& rhs ) noexcept(`['see below]`);`] + +* [*Requires:] `T` is __MOVE_CONSTRUCTIBLE__ and `MoveAssignable`. +* [*Effects:] +[table + [] + [[][[*`*this` contains a value]][[*`*this` does not contain a value]]] + [[[*`rhs` contains a value]][assigns `std::move(*rhs)` to the contained value][initializes the contained value as if direct-initializing an object of type `T` with `std::move(*rhs)`]] + [[[*`rhs` does not contain a value]][destroys the contained value by calling `val->T::~T()`][no effect]] +] +* [*Returns:] `*this`; +* [*Postconditions:] `bool(rhs) == bool(*this)`. +* [*Remarks:] The expression inside `noexcept` is equivalent to `is_nothrow_move_constructible::value && is_nothrow_move_assignable::value`. +* [*Exception Safety:] If any exception is thrown, the initialization state of `*this` and `rhs` remains unchanged. If an exception is +thrown during the call to `T`'s move constructor, the state of `*rhs` is determined by the exception safety guarantee +of `T`'s move constructor. If an exception is thrown during the call to T's move-assignment, the state of `**this` and `*rhs` is determined by the exception safety guarantee of T's move assignment. +* [*Example:] +`` +optional opt(T(2)) ; +optional def ; + +opt = def ; +assert ( def ) ; +assert ( opt ) ; +assert ( *opt == T(2) ) ; +`` + + +__SPACE__ + + +[#reference_optional_operator_equal_other_optional] + +[: `template optional& optional::operator= ( optional const& rhs ) ;`] + +* [*Effect:] +[table + [] + [[][[*`*this` contains a value]][[*`*this` does not contain a value]]] + [[[*`rhs` contains a value]][assigns `*rhs` to the contained value][initializes the contained value as if direct-initializing an object of type `T` with `*rhs`]] + [[[*`rhs` does not contain a value]][destroys the contained value by calling `val->T::~T()`][no effect]] +] +* [*Returns:] `*this`. +* [*Postconditions:] `bool(rhs) == bool(*this)`. +* [*Exception Safety:] If any exception is thrown, the result of the expression `bool(*this)` remains unchanged. +If an exception is thrown during the call to `T`'s constructor, no effect. +If an exception is thrown during the call to `T`'s assignment, the state of its contained value is as defined by the exception safety guarantee of `T`'s copy assignment. +* [*Example:] +`` +T v; +optional opt0(v); +optional opt1; + +opt1 = opt0 ; +assert ( *opt1 == static_cast(v) ) ; +`` + +__SPACE__ + +[#reference_optional_operator_move_equal_other_optional] + +[: `template optional& optional::operator= ( optional&& rhs ) ;`] + +* [*Effect:] +[table + [] + [[][[*`*this` contains a value]][[*`*this` does not contain a value]]] + [[[*`rhs` contains a value]][assigns `std::move(*rhs)` to the contained value][initializes the contained value as if direct-initializing an object of type `T` with `std::move(*rhs)`]] + [[[*`rhs` does not contain a value]][destroys the contained value by calling `val->T::~T()`][no effect]] +] +* [*Returns:] `*this`. +* [*Postconditions:] `bool(rhs) == bool(*this)`. +* [*Exception Safety:] If any exception is thrown, the result of the expression `bool(*this)` remains unchanged. +If an exception is thrown during the call to `T`'s constructor, no effect. +If an exception is thrown during the call to `T`'s assignment, the state of its contained value is as defined by the exception safety guarantee of `T`'s copy assignment. +* [*Example:] +`` +T v; +optional opt0(v); +optional opt1; + +opt1 = std::move(opt0) ; +assert ( opt0 ); +assert ( opt1 ) +assert ( *opt1 == static_cast(v) ) ; +`` + +__SPACE__ + +[#reference_optional_emplace] + +[: `template void optional::emplace( Args&&... args );`] + +* [*Requires:] The compiler supports rvalue references and variadic templates. +* [*Effect:] If `*this` is initialized calls `*this = none`. + Then initializes in-place the contained value as if direct-initializing an object + of type `T` with `std::forward(args)...`. +* [*Postconditions: ] `*this` is [_initialized]. +* [*Throws:] Whatever the selected `T`'s constructor throws. +* [*Exception Safety:] If an exception is thrown during the initialization of `T`, `*this` is ['uninitialized]. +* [*Notes:] `T` need not be __MOVE_CONSTRUCTIBLE__ or `MoveAssignable`. On compilers that do not support variadic templates or rvalue references, this function is available in limited functionality. For details [link optional_emplace_workaround see here]. +* [*Example:] +`` +T v; +optional opt; +opt.emplace(0); // create in-place using ctor T(int) +opt.emplace(); // destroy previous and default-construct another T +opt.emplace(v); // destroy and copy-construct in-place (no assignment called) +`` + +__SPACE__ + +[#reference_optional_operator_equal_factory] + +[: `template optional& optional::operator=( InPlaceFactory const& f );`] +[: `template optional& optional::operator=( TypedInPlaceFactory const& f );`] + +* [*Effect:] Assigns an `optional` with a value of `T` obtained from the +factory. +* [*Postconditions: ] `*this` is [_initialized] and its value is ['directly given] +from the factory `f` (i.e., the value [_is not copied]). +* [*Throws:] Whatever the `T` constructor called by the factory throws. +* [*Notes:] See [link boost_optional.tutorial.in_place_factories In-Place Factories] +* [*Exception Safety:] Exceptions can only be thrown during the call to +the `T` constructor used by the factory; in that case, the `optional` object +will be reset to be ['uninitialized]. + +__SPACE__ + +[#reference_optional_reset_value] + +[: `void optional::reset( T const& v ) ;`] +* [*Deprecated:] same as `operator= ( T const& v) ;` + +__SPACE__ + +[#reference_optional_reset] + +[: `void optional::reset() noexcept ;`] +* [*Effects:] Same as `operator=( none_t );` + +__SPACE__ + +[#reference_optional_get] + +[: `T const& optional::get() const ;`] +[: `T& optional::get() ;`] + +[: `inline T const& get ( optional const& ) ;`] +[: `inline T& get ( optional &) ;`] + +* [*Requires:] `*this` is initialized +* [*Returns:] A reference to the contained value +* [*Throws:] Nothing. +* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`. + + +__SPACE__ + +[#reference_optional_operator_asterisk] + +[: `T const& optional::operator*() const& ;`] +[: `T& optional::operator*() &;`] + +* [*Requires:] `*this` is initialized +* [*Returns:] A reference to the contained value +* [*Throws:] Nothing. +* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`. On compilers that do not support ref-qualifiers on member functions these two overloads are replaced with the classical two: a `const` and non-`const` member functions. +* [*Example:] +`` +T v ; +optional opt ( v ); +T const& u = *opt; +assert ( u == v ) ; +T w ; +*opt = w ; +assert ( *opt == w ) ; +`` + +__SPACE__ + +[#reference_optional_operator_asterisk_move] + +[: `T&& optional::operator*() &&;`] + +* [*Requires:] `*this` contains a value. +* [*Effects:] Equivalent to `return std::move(*val);`. +* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`. On compilers that do not support ref-qualifiers on member functions this overload is not present. + + +__SPACE__ + +[#reference_optional_value] + +[: `T const& optional::value() const& ;`] +[: `T& optional::value() & ;`] + +* [*Effects:] Equivalent to `return bool(*this) ? *val : throw bad_optional_access();`. +* [*Notes:] On compilers that do not support ref-qualifiers on member functions these two overloads are replaced with the classical two: a `const` and non-`const` member functions. +* [*Example:] +`` +T v ; +optional o0, o1 ( v ); +assert ( o1.value() == v ); + +try { + o0.value(); // throws + assert ( false ); +} +catch(bad_optional_access&) { + assert ( true ); +} +`` + +__SPACE__ + +[#reference_optional_value_move] + +[: `T&& optional::value() && ;`] + +* [*Effects:] Equivalent to `return bool(*this) ? std::move(*val) : throw bad_optional_access();`. +* [*Notes:] On compilers that do not support ref-qualifiers on member functions this overload is not present. + +__SPACE__ + + +[#reference_optional_value_or] + +[: `template T optional::value_or(U && v) const& ;`] + +* [*Effects:] Equivalent to `if (*this) return **this; else return std::forward(v);`. +* [*Remarks:] If `T` is not __COPY_CONSTRUCTIBLE__ or `U &&` is not convertible to `T`, the program is ill-formed. +* [*Notes:] On compilers that do not support ref-qualifiers on member functions this overload is replaced with the `const`-qualified member function. On compilers without rvalue reference support the type of `v` becomes `U const&`. + +__SPACE__ + +[#reference_optional_value_or_move] + +[: `template T optional::value_or(U && v) && ;`] + +* [*Effects:] Equivalent to `if (*this) return std::move(**this); else return std::forward(v);`. +* [*Remarks:] If `T` is not __MOVE_CONSTRUCTIBLE__ or `U &&` is not convertible to `T`, the program is ill-formed. +* [*Notes:] On compilers that do not support ref-qualifiers on member functions this overload is not present. + +__SPACE__ + +[#reference_optional_value_or_call] + +[: `template T optional::value_or_eval(F f) const& ;`] + +* [*Requires:] `T` is __COPY_CONSTRUCTIBLE__ and `F` models a __SGI_GENERATOR__ whose result type is convertible to `T`. +* [*Effects:] `if (*this) return **this; else return f();`. +* [*Notes:] On compilers that do not support ref-qualifiers on member functions this overload is replaced with the `const`-qualified member function. +* [*Example:] +`` +int complain_and_0() +{ + clog << "no value returned, using default" << endl; + return 0; +} + +optional o1 = 1; +optional oN = none; + +int i = o1.value_or_eval(complain_and_0); // fun not called +assert (i == 1); + +int j = oN.value_or_eval(complain_and_0); // fun called +assert (i == 0); +`` + +__SPACE__ + +[#reference_optional_value_or_call_move] + +[: `template T optional::value_or_eval(F f) && ;`] + +* [*Requires:] `T` is __MOVE_CONSTRUCTIBLE__ and `F` models a __SGI_GENERATOR__ whose result type is convertible to `T`. +* [*Effects:] `if (*this) return std::move(**this); else return f();`. +* [*Notes:] On compilers that do not support ref-qualifiers on member functions this overload is not present. + +__SPACE__ + +[#reference_optional_map] + +[: `template auto optional::map(F f) const& -> `['see below]` ;`] +[: `template auto optional::map(F f) & -> `['see below]` ;`] + +* [*Effects:] `if (*this) return f(**this); else return none;` +* [*Notes:] The return type of these overloads is `optional`. On compilers that do not support ref-qualifiers on member functions, these two (as well as the next one) overloads are replaced with good old const and non-const overloads. +* [*Example:] +`` +auto length = [](const string& s){ return s.size(); }; +optional o1 {}, o2 {"cat"}; +optional os1 = o1.map(length), os2 = o2.map(length); +assert ( !os1 ) ; +assert ( os2 ) ; +assert ( *os2 == 3 ) ; +`` + +__SPACE__ + +[#reference_optional_map_move] + +[: `template auto optional::map(F f) && -> `['see below]` ;`] + +* [*Effects:] `if (*this) return f(std::move(**this)); else return none;` +* [*Notes:] The return type of this overload is `optional`. + +__SPACE__ + +[#reference_optional_flat_map] + +[: `template auto optional::flat_map(F f) const& -> `['see below]` ;`] +[: `template auto optional::flat_map(F f) & -> `['see below]` ;`] + +* [*Requires:] The return type of expression `f(**this)` is `optional` for some object or reference type `U`. +* [*Effects:] `if (*this) return f(**this); else return none;` +* [*Notes:] The return type of these overloads is `optional`. On compilers that do not support ref-qualifiers on member functions, these two (as well as the next one) overloads are replaced with good old const and non-const overloads. +* [*Example:] +`` +optional first_char(const string& s) { + return s.empty() ? none : optional(s[0]); +}; +optional o1 {}, o2 {"cat"}; +optional os1 = o1.flat_map(first_char), os2 = o2.flat_map(first_char); +assert ( !os1 ) ; +assert ( os2 ) ; +assert ( *os2 == 'c' ) ; +`` +__SPACE__ + +[#reference_optional_flat_map_move] + +[: `template auto optional::flat_map(F f) && -> `['see below]` ;`] + +* [*Requires:] The return type of expression `f(std::move(**this))` is `optional` for some object or reference type `U`. +* [*Effects:] `if (*this) return f(std::move(**this)); else return none;` +* [*Notes:] The return type of this overload is `optional`. + +__SPACE__ + +[#reference_optional_get_value_or_value] + +[: `T const& optional::get_value_or( T const& default) const ;`] +[: `T& optional::get_value_or( T& default ) ;`] + +* [*Deprecated:] Use `value_or()` instead. +* [*Returns:] A reference to the contained value, if any, or `default`. +* [*Throws:] Nothing. +* [*Example:] +`` +T v, z ; +optional def; +T const& y = def.get_value_or(z); +assert ( y == z ) ; + +optional opt ( v ); +T const& u = opt.get_value_or(z); +assert ( u == v ) ; +assert ( u != z ) ; +`` + + +__SPACE__ + +[#reference_optional_get_ptr] + +[: `T const* optional::get_ptr() const ;`] +[: `T* optional::get_ptr() ;`] + +* [*Returns:] If `*this` is initialized, a pointer to the contained value; +else `0` (['null]). +* [*Throws:] Nothing. +* [*Notes:] The contained value is permanently stored within `*this`, so you +should not hold nor delete this pointer +* [*Example:] +`` +T v; +optional opt(v); +optional const copt(v); +T* p = opt.get_ptr() ; +T const* cp = copt.get_ptr(); +assert ( p == get_pointer(opt) ); +assert ( cp == get_pointer(copt) ) ; +`` + +__SPACE__ + +[#reference_optional_operator_arrow] + +[: `T const* optional::operator ->() const ;`] +[: `T* optional::operator ->() ;`] + +* [*Requires: ] `*this` is initialized. +* [*Returns:] A pointer to the contained value. +* [*Throws:] Nothing. +* [*Notes:] The requirement is asserted via `BOOST_ASSERT()`. +* [*Example:] +`` +struct X { int mdata ; } ; +X x ; +optional opt (x); +opt->mdata = 2 ; +`` + +__SPACE__ + +[#reference_optional_operator_bool] + +[: `explicit optional::operator bool() const noexcept ;`] +[: `bool optional::has_value() const noexcept ;`] + +* [*Returns:] `get_ptr() != 0`. +* [*Notes:] On compilers that do not support explicit conversion operators this falls back to safe-bool idiom. +* [*Example:] +`` +optional def ; +assert ( def == 0 ); +optional opt ( v ) ; +assert ( opt ); +assert ( opt != 0 ); +`` + +__SPACE__ + +[#reference_optional_operator_not] + +[: `bool optional::operator!() noexcept ;`] + +* [*Returns:] If `*this` is uninitialized, `true`; else `false`. +* [*Notes:] This operator is provided for those compilers which can't +use the ['unspecified-bool-type operator] in certain boolean contexts. +* [*Example:] +`` +optional opt ; +assert ( !opt ); +*opt = some_T ; + +// Notice the "double-bang" idiom here. +assert ( !!opt ) ; +`` + +__SPACE__ + +[#reference_optional_is_initialized] + +[: `bool optional::is_initialized() const ;`] + +* [*Deprecated:] Same as `explicit operator bool () ;` + + +[endsect] + +[section Detailed Semantics - Optional References] + +__SPACE__ + +[#reference_optional_ref_default_ctor] + +[: `optional::optional() noexcept;`] +[: `optional::optional(none_t) noexcept;`] + +* [*Postconditions:] `bool(*this) == false`; `*this` refers to nothing. + + +__SPACE__ + +[#reference_optional_ref_value_ctor] + +[: `template optional::optional(R&& r) noexcept;`] +* [*Postconditions:] `bool(*this) == true`; `addressof(**this) == addressof(r)`. +* [*Remarks:] Unless `R` is an lvalue reference, the program is ill-formed. This constructor does not participate in overload resolution if `decay` is an instance of `boost::optional`. +* [*Notes:] This constructor is declared `explicit` on compilers that do not correctly support binding to const lvalues of integral types. For more details [link optional_reference_binding see here]. +* [*Example:] +`` +T v; +T& vref = v ; +optional opt(vref); +assert ( *opt == v ) ; +++ v ; // mutate referee +assert (*opt == v); +`` + +__SPACE__ + +[#reference_optional_ref_cond_value_ctor] + +[: `template optional::optional(bool cond, R&& r) noexcept;`] +* [*Effects: ] Initializes `ref` with expression `cond ? addressof(r) : nullptr`. +* [*Postconditions:] `bool(*this) == cond`; If `bool(*this)`, `addressof(**this) == addressof(r)`. +* [*Remarks:] Unless `R` is an lvalue reference, the program is ill-formed. This constructor does not participate in overload resolution if `decay` is an instance of `boost::optional`. + +__SPACE__ + +[#reference_optional_ref_copy_ctor] + +[: `optional::optional ( optional const& rhs ) noexcept ;`] + +* [*Effects: ] Initializes `ref` with expression `rhs.ref`. + +* [*Postconditions:] `bool(*this) == bool(rhs)`. + +* [*Example:] +`` +optional uninit ; +assert (!uninit); + +optional uinit2 ( uninit ) ; +assert ( uninit2 == uninit ); + +T v = 2 ; T& ref = v ; +optional init(ref); +assert ( *init == v ) ; + +optional init2 ( init ) ; +assert ( *init2 == v ) ; + +v = 3 ; + +assert ( *init == 3 ) ; +assert ( *init2 == 3 ) ; +`` + +__SPACE__ + +[#reference_optional_ref_ctor_from_opt_U] + +[: `template explicit optional::optional ( optional const& rhs ) noexcept ;`] + +* [*Requires:] `is_convertible::value` is `true`. + +* [*Effects: ] Initializes `ref` with expression `rhs.ref`. + +* [*Postconditions:] `bool(*this) == bool(rhs)`. + + +__SPACE__ + +[#reference_optional_ref_assign_none_t] + +[: `optional::operator= ( none_t ) noexcept ;`] + +* [*Effects: ] Assigns `ref` with expression `nullptr`. + +* [*returns:] `*this`. + +* [*Postconditions:] `bool(*this) == false`. + + + +[#reference_optional_ref_copy_assign] + +[: `optional& optional::operator= ( optional const& rhs ) noexcept ;`] + +* [*Effects: ] Assigns `ref` with expression `rhs.ref`. + +* [*returns:] `*this`. + +* [*Postconditions:] `bool(*this) == bool(rhs)`. + +* [*Notes:] This behaviour is called ['rebinding semantics]. See [link boost_optional.tutorial.optional_references.rebinding_semantics_for_assignment_of_optional_references here] for details. + +* [*Example:] +`` +int a = 1 ; +int b = 2 ; +T& ra = a ; +T& rb = b ; +optional def ; +optional ora(ra) ; +optional orb(rb) ; + +def = orb ; // binds 'def' to 'b' through 'rb' wrapped within 'orb' +assert ( *def == b ) ; +*def = ora ; // changes the value of 'b' to a copy of the value of 'a' +assert ( b == a ) ; +int c = 3; +int& rc = c ; +optional orc(rc) ; +ora = orc ; // REBINDS ora to 'c' through 'rc' +c = 4 ; +assert ( *ora == 4 ) ; +`` + + +[#reference_optional_ref_assign_optional_U] + +[: `template optional& optional::operator= ( optional const& rhs ) noexcept ;`] + +* [*Requires:] `is_convertible::value` is `true`. + +* [*Effects: ] Assigns `ref` with expression `rhs.ref`. + +* [*returns:] `*this`. + +* [*Postconditions:] `bool(*this) == bool(rhs)`. + + +__SPACE__ + +[#reference_optional_ref_assign_R] + +[: `template optional& optional::operator= ( R&& r ) noexcept ;`] + +* [*Effects: ] Assigns `ref` with expression `r`. + +* [*returns:] `*this`. + +* [*Postconditions:] `bool(*this) == true`. + +* [*Remarks:] Unless `R` is an lvalue reference, the program is ill-formed. This function does not participate in overload resolution if `decay` is an instance of `boost::optional`. + +* [*Example:] +`` +int a = 1 ; +int b = 2 ; +T& ra = a ; +T& rb = b ; +optional def ; +optional opt(ra) ; + +def = rb ; // binds 'def' to 'b' through 'rb' +assert ( *def == b ) ; +*def = a ; // changes the value of 'b' to a copy of the value of 'a' +assert ( b == a ) ; +int c = 3; +int& rc = c ; +opt = rc ; // REBINDS to 'c' through 'rc' +c = 4 ; +assert ( *opt == 4 ) ; +`` + +__SPACE__ + +[#reference_optional_ref_emplace_R] + +[: `void optional::emplace( R&& r ) noexcept ;`] +* [*Effects: ] Assigns `ref` with expression `r`. +* [*Postconditions:] `bool(*this) == true`. +* [*Remarks:] Unless `R` is an lvalue reference, the program is ill-formed. This function does not participate in overload resolution if `decay` is an instance of `boost::optional`. + +__SPACE__ + +[#reference_optional_ref_get] +[: `T& optional::get() const ;`] +[: `T& optional::operator *() const ;`] +* [*Requires:] `bool(*this) == true`. +* [*Effects: ] Returns `*ref`. +* [*Throws: ] Nothing. +* [*Example:] +`` +T v ; +T& vref = v ; +optional opt ( vref ); +T const& vref2 = *opt; +assert ( vref2 == v ) ; +++ v ; +assert ( *opt == v ) ; +`` + +__SPACE__ + +[#reference_optional_ref_arrow] +[: `T* optional::operator -> () const ;`] +* [*Requires:] `bool(*this) == true`. +* [*Effects: ] Returns `ref`. +* [*Throws: ] Nothing. + +__SPACE__ + +[#reference_optional_ref_value] +[: `T& optional::value() const ;`] +* [*Effects:] Equivalent to `return bool(*this) ? *val : throw bad_optional_access();`. + +__SPACE__ + +[#reference_optional_ref_value_or] +[: `template T& optional::value_or( R&& r ) const noexcept;`] +* [*Effects:] Equivalent to `if (*this) return **this; else return r;`. +* [*Remarks:] Unless `R` is an lvalue reference, the program is ill-formed. + +__SPACE__ + +[#reference_optional_ref_value_or_eval] +[: `template T& optional::value_or( F f ) const ;`] +* [*Effects:] Equivalent to `if (*this) return **this; else return f();`. +* [*Remarks:] Unless `decltype(f())` is an lvalue reference, the program is ill-formed. + +__SPACE__ + +[#reference_optional_ref_map] +[: `template auto optional::map( F f ) const -> `['see below]`;`] +* [*Effects:] Equivalent to `if (*this) return f(**this); else return none;`. +* [*Remarks:] The return type of this function is `optional`. + +__SPACE__ + +[#reference_optional_ref_flat_map] +[: `template auto optional::flat_map( F f ) const -> `['see below]`;`] +* [*Requires:] The return type of expression `f(**this)` is `optional` for some object or reference type `U`. +* [*Effects:] Equivalent to `if (*this) return f(**this); else return none;`. +* [*Remarks:] The return type of this function is `optional`. + +__SPACE__ + +[#reference_optional_ref_get_ptr] +[: `T* optional::get_ptr () const noexcept;`] +* [*Returns:] `ref`. + +__SPACE__ + +[#reference_optional_ref_operator_bool] +[: `bool has_value() const noexcept;`] +[: `optional::operator bool () const noexcept;`] +* [*Returns:] `bool(ref)`. + +__SPACE__ + +[#reference_optional_ref_operator_not] +[: `optional::operator ! () const noexcept;`] +* [*Returns:] `!bool(ref)`. + +__SPACE__ + +[#reference_optional_ref_reset] +[: `void optional::reset() noexcept;`] +* [*Effects:] Same as `*this = none`. + +__SPACE__ + +[#reference_optional_ref_reset_value] +[: `template void optional::reset ( R&& r) noexcept;`] +* [*Effects:] Equivalent to `*this = std::forward(r)`. +* [*Remarks:] This function is deprecated. + +__SPACE__ + +[#reference_optional_ref_is_initialized] +[: `bool optional::is_initialized() const noexcept;`] +* [*Effects:] Equivalent to `return bool(*this)`. +* [*Remarks:] This function is deprecated. + +__SPACE__ + +[#reference_optional_ref_get_value_or_value] +[: `template T& optional::get_value_or( R&& r ) const noexcept;`] +* [*Effects:] Equivalent to `return value_or(std::forward(r);`. +* [*Remarks:] This function is deprecated. + +[endsect] + + +[section Detailed Semantics - Free Functions] + + +__SPACE__ + +[#reference_make_optional_value] + +[: `optional make_optional( T const& v )`] + +* [*Returns: ] `optional(v)` for the ['deduced] type `T` of `v`. +* [*Example:] +`` +template void foo ( optional const& opt ) ; + +foo ( make_optional(1+1) ) ; // Creates an optional +`` + +__SPACE__ + +[#reference_make_optional_rvalue] + +[: `optional> make_optional( T && v )`] + +* [*Returns: ] `optional>(std::move(v))` for the ['deduced] type `T` of `v`. + + +__SPACE__ + +[#reference_make_optional_bool_value] + +[: `optional make_optional( bool condition, T const& v )`] + +* [*Returns: ] `optional(condition, v)` for the ['deduced] type `T` of `v`. +* [*Example:] +`` +optional calculate_foo() +{ + double val = compute_foo(); + return make_optional(is_not_nan_and_finite(val),val); +} + +optional v = calculate_foo(); +if ( !v ) + error("foo wasn't computed"); +`` + +__SPACE__ + +[#reference_make_optional_bool_rvalue] + +[: `optional> make_optional( bool condition, T && v )`] + +* [*Returns: ] `optional>(condition, std::move(v))` for the ['deduced] type `T` of `v`. + + +__SPACE__ + +[#reference_operator_compare_equal_optional_optional] + +[: `bool operator == ( optional const& x, optional const& y );`] + +* [*Requires:] `T` shall meet requirements of __STD_EQUALITY_COMPARABLE__. +* [*Returns:] If both `x` and `y` are initialized, `(*x == *y)`. If only +`x` or `y` is initialized, `false`. If both are uninitialized, `true`. +* [*Notes:] This definition guarantees that `optional` not containing a value is compared unequal to any `optional` containing any value, and equal to any other `optional` not containing a value. +Pointers have shallow relational operators while `optional` has deep relational operators. Do not use `operator==` directly in generic code which expect to be given either an `optional` or a pointer; use +__FUNCTION_EQUAL_POINTEES__ instead +* [*Example:] +`` +optional oN, oN_; +optional o1(T(1)), o1_(T(1)); +optional o2(T(2)); + +assert ( oN == oN ); // Identity implies equality +assert ( o1 == o1 ); // + +assert ( oN == oN_ ); // Both uninitialized compare equal + +assert ( oN != o1 ); // Initialized unequal to initialized. + +assert ( o1 == o1_ ); // Both initialized compare as (*lhs == *rhs) +assert ( o1 != o2 ); // +`` + +__SPACE__ + +[#reference_operator_compare_less_optional_optional] + +[: `bool operator < ( optional const& x, optional const& y );`] + +* [*Requires:] Expression `*x < *y` shall be well-formed and its result shall be convertible to `bool`. +* [*Returns:] `(!y) ? false : (!x) ? true : *x < *y`. +* [*Notes:] This definition guarantees that `optional` not containing a value is ordered as less than any `optional` containing any value, and equivalent to any other `optional` not containing a value. +Pointers have shallow relational operators while `optional` has deep relational operators. Do not use `operator<` directly in generic code +which expect to be given either an `optional` or a pointer; use __FUNCTION_LESS_POINTEES__ instead. `T` need not be __STD_LESS_THAN_COMPARABLE__. Only single `operator<` is required. Other relational operations are defined in terms of this one. If `T`'s `operator<` satisfies the axioms of __STD_LESS_THAN_COMPARABLE__ (transitivity, antisymmetry and irreflexivity), `optional` is __STD_LESS_THAN_COMPARABLE__. +* [*Example:] +`` +optional oN, oN_; +optional o0(T(0)); +optional o1(T(1)); + +assert ( !(oN < oN) ); // Identity implies equivalence +assert ( !(o1 < o1) ); + +assert ( !(oN < oN_) ); // Two uninitialized are equivalent +assert ( !(oN_ < oN) ); + +assert ( oN < o0 ); // Uninitialized is less than initialized +assert ( !(o0 < oN) ); + +assert ( o1 < o2 ) ; // Two initialized compare as (*lhs < *rhs) +assert ( !(o2 < o1) ) ; +assert ( !(o2 < o2) ) ; +`` + +__SPACE__ + +[#reference_operator_compare_not_equal_optional_optional] + +[: `bool operator != ( optional const& x, optional const& y );`] + +* [*Returns: ] `!( x == y );` + +__SPACE__ + +[#reference_operator_compare_greater_optional_optional] + +[: `bool operator > ( optional const& x, optional const& y );`] + +* [*Returns: ] `( y < x );` + +__SPACE__ + +[#reference_operator_compare_less_or_equal_optional_optional] + +[: `bool operator <= ( optional const& x, optional const& y );`] + +* [*Returns: ] `!( y < x );` + +__SPACE__ + +[#reference_operator_compare_greater_or_equal_optional_optional] + +[: `bool operator >= ( optional const& x, optional const& y );`] + +* [*Returns: ] `!( x < y );` + +__SPACE__ + +[#reference_operator_compare_equal_optional_none] + +[: `bool operator == ( optional const& x, none_t ) noexcept;`] +[: `bool operator == ( none_t, optional const& x ) noexcept;`] + +* [*Returns:] `!x`. +* [*Notes:] `T` need not meet requirements of __STD_EQUALITY_COMPARABLE__. + + +__SPACE__ + +[#reference_operator_compare_not_equal_optional_none] + +[: `bool operator != ( optional const& x, none_t ) noexcept;`] +[: `bool operator != ( none_t, optional const& x ) noexcept;`] + +* [*Returns: ] `bool(x);` + + +__SPACE__ + + +[#reference_free_get_pointer] +[: `auto get_pointer ( optional& o ) -> typename optional::pointer_type ;`] +[: `auto get_pointer ( optional const& o ) -> typename optional::pointer_const_type ;`] +* [*Returns:] `o.get_ptr()`. +* [*Throws:] Nothing. + +__SPACE__ + + +[#reference_free_get_value_or] +[: `auto get_optional_value_or ( optional& o, typename optional::reference_type def ) -> typename optional::reference_type ;`] +[: `auto get_optional_value_or ( optional const& o, typename optional::reference_const_type def ) -> typename optional::reference_const_type ;`] +* [*Returns:] `o.get_value_or(def)`. +* [*Throws:] Nothing. +* [*Remarks:] This function is deprecated. + +__SPACE__ + +[#reference_swap_optional_optional] + +[: `void swap ( optional& x, optional& y ) ;`] + +* [*Requires:] Lvalues of type `T` shall be swappable and `T` shall be __MOVE_CONSTRUCTIBLE__. +* [*Effects:] +[table + [] + [[][[*`*this` contains a value]][[*`*this` does not contain a value]]] + [[[*`rhs` contains a value]][calls `swap(*(*this), *rhs)`][initializes the contained value of `*this` as if direct-initializing an object of type `T` with the expression `std::move(*rhs)`, followed by `rhs.val->T::~T()`, `*this` contains a value and `rhs` does not contain a value]] + [[[*`rhs` does not contain a value]][initializes the contained value of `rhs` as if direct-initializing an object of type `T` with the expression `std::move(*(*this))`, followed by `val->T::~T()`, `*this` does not contain a value and `rhs` contains a value][no effect]] +] +* [*Postconditions:] The states of `x` and `y` interchanged. +* [*Throws:] If both are initialized, whatever `swap(T&,T&)` throws. If only +one is initialized, whatever `T::T ( T&& )` throws. +* [*Example:] +`` +T x(12); +T y(21); +optional def0 ; +optional def1 ; +optional optX(x); +optional optY(y); + +boost::swap(def0,def1); // no-op + +boost::swap(def0,optX); +assert ( *def0 == x ); +assert ( !optX ); + +boost::swap(def0,optX); // Get back to original values + +boost::swap(optX,optY); +assert ( *optX == y ); +assert ( *optY == x ); +`` + +__SPACE__ + +[#reference_swap_optional_reference] +[: `void swap ( optional& x, optional& y ) noexcept ;`] + +* [*Postconditions:] `x` refers to what `y` referred to before the swap (if anything). `y` refers to whatever `x` referred to before the swap. + +* [*Example:] +`` +T x(12); +T y(21); + +optional opt0; +optional optX (x); +optional optY (y); + +boost::swap(optX, optY); +assert (addressof(*optX) == addressof(y)); +assert (addressof(*optY) == addressof(x)); + +boost::swap(opt0, optX); +assert ( opt0 ); +assert ( !optX ); +assert (addressof(*opt0) == addressof(y)); +`` + +[endsect] + + +[section Detailed Semantics - std::hash Specializations] + +__SPACE__ +[#reference_std_hash_spec] + +`` +namespace std { + +template +struct hash > ; + +template +struct hash > ; + +} // namespace std +`` + +The specialization `hash>` is enabled if and only if +`hash>` is enabled. When enabled, for an object `o` +of type `optional`, if `o.has_­value() == true`, then `hash>()(o)` + evaluates to the same value as `hash>()(*o)`; otherwise it +evaluates to an unspecified value. +The member functions are not guaranteed to be `noexcept`. + +[caution +You may get compiler errors when your program provides specializations for +`std::hash>`. If this happens, define macro +`BOOST_OPTIONAL_CONFIG_DO_NOT_SPECIALIZE_STD_HASH` to suppress the specializations +of `std::hash` in this library. +] + +[endsect] diff --git a/libs/optional/doc/29_ref_optional_convenience.qbk b/libs/optional/doc/29_ref_optional_convenience.qbk new file mode 100644 index 00000000..63b4732a --- /dev/null +++ b/libs/optional/doc/29_ref_optional_convenience.qbk @@ -0,0 +1,17 @@ +[/ + Boost.Optional + + Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal + Copyright (c) 2015 Andrzej Krzemienski + + 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) +] + +[section Header ] + +This is an alias for header [link boost_optional.reference.header__boost_optional_optional_hpp_.header_optional_optional ``]. + + +[endsect] diff --git a/libs/optional/doc/90_dependencies.qbk b/libs/optional/doc/90_dependencies.qbk new file mode 100644 index 00000000..d383905c --- /dev/null +++ b/libs/optional/doc/90_dependencies.qbk @@ -0,0 +1,116 @@ +[/ + Boost.Optional + + Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal + + 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) +] + + +[section Dependencies and Portability] + +[section Dependencies] +The implementation uses the following other Boost modules: + +# assert +# config +# core +# detail +# move +# mpl +# static_assert +# throw_exception +# type_traits +# utility + +[endsect] + +[section Emplace operations in older compilers][#optional_emplace_workaround] + +Certain constructors and functions in the interface of `optional` perform a 'perfect forwarding' of arguments: + + template optional(in_place_init_t, Args&&... args); + template optional(in_place_init_if_t, bool condition, Args&&... args); + template void emplace(Args&&... args); + +On compilers that do not support variadic templates, each of these functions is substituted with two overloads, one forwarding a single argument, the other forwarding zero arguments. This forms the following set: + + template optional(in_place_init_t, Arg&& arg); + optional(in_place_init_t); + + template optional(in_place_init_if_t, bool condition, Arg&& arg); + optional(in_place_init_if_t, bool condition); + + template void emplace(Arg&& arg); + void emplace(); + +On compilers that do not support rvalue references, each of these functions is substituted with three overloads: taking `const` and non-`const` lvalue reference, and third forwarding zero arguments. This forms the following set: + + template optional(in_place_init_t, const Arg& arg); + template optional(in_place_init_t, Arg& arg); + optional(in_place_init_t); + + template optional(in_place_init_if_t, bool condition, const Arg& arg); + template optional(in_place_init_if_t, bool condition, Arg& arg); + optional(in_place_init_if_t, bool condition); + + template void emplace(const Arg& arg); + template void emplace(Arg& arg); + void emplace(); + +This workaround addresses about 40% of all use cases. If this is insufficient, you need to resort to using [link boost_optional.tutorial.in_place_factories In-Place Factories]. +[endsect] + +[section Optional Reference Binding][#optional_reference_binding] + +A number of compilers incorrectly treat const lvalues of integral type as rvalues, and create an illegal temporary when binding to an lvalue reference to const in some expressions. This could result in creating an optional lvalue reference that is in fact bound to an unexpected temporary rather than to the intended object. In order to prevent hard to find run-time bugs, this library performs compile-time checks to prevent expressions that would otherwise bind an optional reference to an unexpected temporary. As a consequence, on certain compilers certain pieces of functionality in optional references are missing. In order to maintain a portability of your code across different compilers, it is recommended that you only stick to the minimum portable interface of optional references: prefer direct-initialization and copy assignment of optional references to copy-initialization and assignment from `T&`: + + const int i = 0; + optional or1; + optional or2 = i; // caution: not portable + or1 = i; // caution: not portable + + optional or3(i); // portable + or1 = optional(i); // portable + +Compilers known to have these deficiencies include GCC versions 4.2, 4.3, 4.4, 4.5, 5.1, 5.2; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, 11.0, 12.0. In order to check if your compiler correctly implements reference binding use this test program. + + #include + + const int global_i = 0; + + struct TestingReferenceBinding + { + TestingReferenceBinding(const int& ii) + { + assert(&ii == &global_i); + } + + void operator=(const int& ii) + { + assert(&ii == &global_i); + } + + void operator=(int&&) // remove this if your compiler doesn't have rvalue refs + { + assert(false); + } + }; + + int main() + { + const int& iref = global_i; + assert(&iref == &global_i); + + TestingReferenceBinding ttt = global_i; + ttt = global_i; + + TestingReferenceBinding ttt2 = iref; + ttt2 = iref; + } + +[endsect] + +[endsect] \ No newline at end of file diff --git a/libs/optional/doc/91_relnotes.qbk b/libs/optional/doc/91_relnotes.qbk new file mode 100644 index 00000000..4460688b --- /dev/null +++ b/libs/optional/doc/91_relnotes.qbk @@ -0,0 +1,138 @@ +[/ + Boost.Optional + + Copyright (c) 2015 - 2022 Andrzej Krzemienski + + 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) +] + + +[section:relnotes Release Notes] + +[heading Boost Release 1.83] + +* Deprecated support for C++03 and earlier, C++11 will be required in release 1.86. + +[heading Boost Release 1.80] + +* [*Breaking change:] Added specializations for `std::hash>`. This fixes [@https://github.com/boostorg/optional/issues/55 issue #55]. You may get compiler errors when your program provides specializations for `std::hash>`. If this happens, define macro `BOOST_OPTIONAL_CONFIG_DO_NOT_SPECIALIZE_STD_HASH` to suppress the specializations of `std::hash` in this library. + +[heading Boost Release 1.79] + +* Fixed [@https://github.com/boostorg/optional/issues/98 issue #98]. +* Fixed [@https://github.com/boostorg/optional/issues/92 issue #92]. +* Added support for `BOOST_NO_IOSTREAM`. +* Now aligned storage uses `unsigned char` rather than `char` to avoid UB. +* Now using cv-unqualified `value_type` with placement `new` to avoid UB. + +[heading Boost Release 1.76] + +* Fixed MSVC warning C4702. + +[heading Boost Release 1.75] + +* `boost::none` is `constexpr`-declared. + +* Fixed [@https://github.com/boostorg/optional/issues/78 issue #78]. + +[heading Boost Release 1.73] + +* Fixed [@https://github.com/boostorg/optional/issues/78 issue #78]. +* `boost::none` is now declared as an inline variable (on compilers that support it): there is only one instance of `boost::none` across all translation units. +* Fixed a number of compilation errors in GCC 4.4.7 in `optional` for trivial `T`s. Thanks to Robert Leahy for the fix. For details see [@https://github.com/boostorg/optional/pull/80 pr #78]. +* Now suppressing warning `-Wweak-vtables`. + +[heading Boost Release 1.69] + +* Remove deprecation mark from `reset()` method (without arguments). +* Fixed [@https://github.com/boostorg/optional/issues/59 issue #59]. +* Fixed bug with initialization of certain wrapper types in clang with -std=c++03. See [@https://github.com/boostorg/optional/pull/64 pr #64]. + +[heading Boost Release 1.68] + +* Added member function `has_value()` for compatibility with `std::optional` ([@https://github.com/boostorg/optional/issues/52 issue #52]). +* Added member function `map()` for transforming `optional` into `optional` using a function of type `T -> U`. +* Added member function `flat_map()` for transforming `optional` into `optional` using a function of type `T -> optional`. + + +[heading Boost Release 1.67] + +* Fixed [@https://github.com/boostorg/optional/issues/46 issue #46]. +* Fixed `-Wzero-as-null-pointer-constant` warnings. + + +[heading Boost Release 1.66] + +* On newer compilers `optional` is now trivially-copyable for scalar `T`s. This uses a different storage (just `T` rather than `aligned_storage`). We require the compiler to support defaulted functions. +* Changed the implementation of `operator==` to get rid of the `-Wmaybe-uninitialized` false-positive warning from GCC. + +[heading Boost Release 1.63] +* Added two new in-place constructors. They work similarly to `emplace()` functions: they initialize the contained value by perfect-forwarding the obtained arguments. One constructor always initializes the contained value, the other based on a boolean condition. +* Syntax `o = {}` now correctly un-initializes optional, just like in `std::optional`. +* Fixed [@https://svn.boost.org/trac/boost/ticket/12203 Trac #12203]. +* Fixed [@https://svn.boost.org/trac/boost/ticket/12563 Trac #12563]. + + +[heading Boost Release 1.62] + +* Fixed [@https://svn.boost.org/trac/boost/ticket/12179 Trac #12179]. + + +[heading Boost Release 1.61] + +* Now `boost::optional` is specialized for reference parameters. This addresses a couple of issues: + * the `sizeof` of optional reference is that of a pointer, + * some bugs connected to copying optional references are gone, + * all run-time bugs caused by incorrect reference binding on some compilers are now turned into compile-time errors, + * you can swap optional references: it is like swapping pointers: shallow, underlying objects are not affected, + * optional references to abstract types work. +* Documented nested typedefs ([@https://svn.boost.org/trac/boost/ticket/5193 Trac #5193]). +* Made the perfect-forwarding constructor SFINAE-friendly, which fixes [@https://svn.boost.org/trac/boost/ticket/12002 Trac #12002]. However, this only works in the newer platforms that correctly implement C++11 ``. +* Fixed [@https://svn.boost.org/trac/boost/ticket/10445 Trac #10445]. + + +[heading Boost Release 1.60] + +* Changed the implementation of `boost::none` again. Now it is a const object with internal linkage (as any other tag). This fixes [@https://svn.boost.org/trac/boost/ticket/11203 Trac #11203]. + + +[heading Boost Release 1.59] + +* For C++03 compilers, added 0-argument overload for member function `emplace()`, and therewith removed the dependency on ``. +* Fixed [@https://svn.boost.org/trac/boost/ticket/11241 Trac #11241]. + +[heading Boost Release 1.58] + +* `boost::none_t` is no longer convertible from literal `0`. This avoids a bug where `optional> oi = 0;` would initialize an optional object with no contained value. +* Improved the trick that prevents streaming out `optional` without header `optional_io.hpp` by using safe-bool idiom. This addresses [@https://svn.boost.org/trac/boost/ticket/10825 Trac #10825]. +* IOStream operators are now mentioned in documentation. +* Added a way to manually disable move semantics: just define macro `BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES`. This can be used to work around [@https://svn.boost.org/trac/boost/ticket/10399 Trac #10399]. +* It is no longer possible to assign `optional` to `optional` when `U` is not assignable or convertible to `T` ([@https://svn.boost.org/trac/boost/ticket/11087 Trac #11087]). +* Value accessors now work correctly on rvalues of `optional` ([@https://svn.boost.org/trac/boost/ticket/10839 Trac #10839]). + + +[heading Boost Release 1.57] + +* [@https://github.com/boostorg/optional/pull/9 Git pull #9]: ['"Supply `` to fix C++03 compile error on `logic_error("...")`"]. + + +[heading Boost Release 1.56] + +* Added support for rvalue references. Now `optional` works with moveable but non-copyable `T`'s, +* Improved `swap` (now uses move operations), +* Added function `emplace()`. This is the last of the requests from [@https://svn.boost.org/trac/boost/ticket/1841 Trac #1841], +* `optional` is moveable, including conditional `noexcept` specifications, which make it `move_if_noexcept`-friendly, +* Using explicit operator bool() on platforms that support it ([@https://svn.boost.org/trac/boost/ticket/4227 Trac #4227]) (breaking change), +* Forward declaration of `operator<<(ostream&, optional const&)` to prevent inadvertent incorrect serialization of optional objects, +* Removed deprecated function `reset()` from examples ([@https://svn.boost.org/trac/boost/ticket/9005 Trac #9005]), +* Equality comparison with `boost::none` does not require that `T` be EqualityComparable, +* Optional rvalue references are explicitly disallowed, +* Binding temporaries to optional references is explicitly disallowed (breaking change), +* More ways to access the contained value, functions `value()`, `value_or()`, `value_or_eval()`, +* Updated and reorganized documentation, added tutorial and quick guide sections. + + + +[endsect][/ relnotes] diff --git a/libs/optional/doc/92_acknowledgments.qbk b/libs/optional/doc/92_acknowledgments.qbk new file mode 100644 index 00000000..f337ce27 --- /dev/null +++ b/libs/optional/doc/92_acknowledgments.qbk @@ -0,0 +1,62 @@ +[/ + Boost.Optional + + Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal + + 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) +] + + +[section:acknowledgements Acknowledgements] + +[heading Pre-formal review] + +* Peter Dimov suggested the name 'optional', and was the first to point out +the need for aligned storage. +* Douglas Gregor developed 'type_with_alignment', and later Eric Friedman +coded 'aligned_storage', which are the core of the optional class +implementation. +* Andrei Alexandrescu and Brian Parker also worked with aligned storage +techniques and their work influenced the current implementation. +* Gennadiy Rozental made extensive and important comments which shaped the +design. +* Vesa Karvonen and Douglas Gregor made quite useful comparisons between +optional, variant and any; and made other relevant comments. +* Douglas Gregor and Peter Dimov commented on comparisons and evaluation +in boolean contexts. +* Eric Friedman helped understand the issues involved with aligned storage, +move/copy operations and exception safety. +* Many others have participated with useful comments: Aleksey Gurotov, +Kevlin Henney, David Abrahams, and others I can't recall. + +[heading Post-formal review] + +* William Kempf carefully considered the originally proposed interface +and suggested the new interface which is currently used. He also started and +fueled the discussion about the analogy optional<>/smart pointer and about +relational operators. +* Peter Dimov, Joel de Guzman, David Abrahams, Tanton Gibbs and Ian Hanson +focused on the relational semantics of optional (originally undefined); +concluding with the fact that the pointer-like interface doesn't make it a +pointer so it shall have deep relational operators. +* Augustus Saunders also explored the different relational semantics between +optional<> and a pointer and developed the OptionalPointee concept as an aid +against potential conflicts on generic code. +* Joel de Guzman noticed that optional<> can be seen as an API on top of +variant. +* Dave Gomboc explained the meaning and usage of the Haskell analog to +optional<>: the Maybe type constructor (analogy originally pointed out by +David Sankel). +* Other comments were posted by Vincent Finn, Anthony Williams, Ed Brey, +Rob Stewart, and others. +* Joel de Guzman made the case for the support of references and helped +with the proper semantics. +* Mat Marcus shown the virtues of a value-oriented interface, influencing +the current design, and contributed the idea of "none". +* Vladimir Batov's design of Boost.Convert library motivated the development +of value accessors for `optional`: functions `value`, `value_or`, `value_or_eval`. + +[endsect] + diff --git a/libs/optional/doc/Jamfile.v2 b/libs/optional/doc/Jamfile.v2 new file mode 100644 index 00000000..2fc6463e --- /dev/null +++ b/libs/optional/doc/Jamfile.v2 @@ -0,0 +1,53 @@ +# Boost.Optional +# +# Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal +# +# 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) + + +# Quickbook +# ----------------------------------------------------------------------------- + +using boostbook ; +import quickbook ; + +path-constant images : html ; + +xml optional + : + 00_optional.qbk + ; + +install images + : + images/opt_align1.png + images/opt_align2.png + images/opt_align3.png + images/opt_align4.png + : + html/images + ; + +boostbook standalone + : + optional + : + html:boost.root=../../../.. + html:boost.libraries=../../../../libs/libraries.htm + chapter.autolabel=0 + chunk.section.depth=8 + toc.section.depth=2 + toc.max.depth=2 + generate.section.toc.level=1 + pdf:img.src.path=$(images)/ + pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/libs/optional/doc/html + docbook:on + ; + +############################################################################### +alias boostdoc ; +explicit boostdoc ; +alias boostrelease : standalone ; +explicit boostrelease ; diff --git a/libs/optional/doc/html/boost_optional/a_note_about_optional_bool_.html b/libs/optional/doc/html/boost_optional/a_note_about_optional_bool_.html new file mode 100644 index 00000000..64f37f68 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/a_note_about_optional_bool_.html @@ -0,0 +1,108 @@ + + + +A note about optional<bool> + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+


+
+PrevUpHomeNext +
+
+ +

+ optional<bool> should + be used with special caution and consideration. +

+

+ First, it is functionally similar to a tristate boolean (false, maybe, true) + —such as boost::tribool— + except that in a tristate boolean, the maybe state represents + a valid value, unlike the corresponding state of an uninitialized + optional<bool>. It + should be carefully considered if an optional<bool> + instead of a tribool is really + needed. +

+

+ Second, although optional<> + provides a contextual conversion to bool + in C++11, this falls back to an implicit conversion on older compilers. This + conversion refers to the initialization state and not to the contained value. + Using optional<bool> can + lead to subtle errors due to the implicit bool + conversion: +

+
void foo ( bool v ) ;
+void bar()
+{
+    optional<bool> v = try();
+
+    // The following intended to pass the value of 'v' to foo():
+    foo(v);
+    // But instead, the initialization state is passed
+    // due to a typo: it should have been foo(*v).
+}
+
+

+ The only implicit conversion is to bool, + and it is safe in the sense that typical integral promotions don't apply (i.e. + if foo() + takes an int instead, it won't + compile). +

+

+ Third, mixed comparisons with bool + work differently than similar mixed comparisons between pointers and bool, so the results might surprise you: +

+
optional<bool> oEmpty(none), oTrue(true), oFalse(false);
+
+if (oEmpty == none);  // renders true
+if (oEmpty == false); // renders false!
+if (oEmpty == true);  // renders false!
+
+if (oFalse == none);  // renders false
+if (oFalse == false); // renders true!
+if (oFalse == true);  // renders false
+
+if (oTrue == none);   // renders false
+if (oTrue == false);  // renders false
+if (oTrue == true);   // renders true
+
+

+ In other words, for optional<>, the following assertion does not hold: +

+
assert((opt == false) == (!opt));
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/acknowledgements.html b/libs/optional/doc/html/boost_optional/acknowledgements.html new file mode 100644 index 00000000..54195804 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/acknowledgements.html @@ -0,0 +1,130 @@ + + + +Acknowledgements + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHome +
+
+ +

+ + Pre-formal + review +

+
    +
  • + Peter Dimov suggested the name 'optional', and was the first to point out + the need for aligned storage. +
  • +
  • + Douglas Gregor developed 'type_with_alignment', and later Eric Friedman + coded 'aligned_storage', which are the core of the optional class implementation. +
  • +
  • + Andrei Alexandrescu and Brian Parker also worked with aligned storage techniques + and their work influenced the current implementation. +
  • +
  • + Gennadiy Rozental made extensive and important comments which shaped the + design. +
  • +
  • + Vesa Karvonen and Douglas Gregor made quite useful comparisons between + optional, variant and any; and made other relevant comments. +
  • +
  • + Douglas Gregor and Peter Dimov commented on comparisons and evaluation + in boolean contexts. +
  • +
  • + Eric Friedman helped understand the issues involved with aligned storage, + move/copy operations and exception safety. +
  • +
  • + Many others have participated with useful comments: Aleksey Gurotov, Kevlin + Henney, David Abrahams, and others I can't recall. +
  • +
+

+ + Post-formal + review +

+
    +
  • + William Kempf carefully considered the originally proposed interface and + suggested the new interface which is currently used. He also started and + fueled the discussion about the analogy optional<>/smart pointer + and about relational operators. +
  • +
  • + Peter Dimov, Joel de Guzman, David Abrahams, Tanton Gibbs and Ian Hanson + focused on the relational semantics of optional (originally undefined); + concluding with the fact that the pointer-like interface doesn't make it + a pointer so it shall have deep relational operators. +
  • +
  • + Augustus Saunders also explored the different relational semantics between + optional<> and a pointer and developed the OptionalPointee concept + as an aid against potential conflicts on generic code. +
  • +
  • + Joel de Guzman noticed that optional<> can be seen as an API on top + of variant<T,nil_t>. +
  • +
  • + Dave Gomboc explained the meaning and usage of the Haskell analog to optional<>: + the Maybe type constructor (analogy originally pointed out by David Sankel). +
  • +
  • + Other comments were posted by Vincent Finn, Anthony Williams, Ed Brey, + Rob Stewart, and others. +
  • +
  • + Joel de Guzman made the case for the support of references and helped with + the proper semantics. +
  • +
  • + Mat Marcus shown the virtues of a value-oriented interface, influencing + the current design, and contributed the idea of "none". +
  • +
  • + Vladimir Batov's design of Boost.Convert library motivated the development + of value accessors for optional: + functions value, value_or, value_or_eval. +
  • +
+
+ + + +
+
+
+PrevUpHome +
+ + diff --git a/libs/optional/doc/html/boost_optional/acknowledgments.html b/libs/optional/doc/html/boost_optional/acknowledgments.html new file mode 100644 index 00000000..b09cf6e1 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/acknowledgments.html @@ -0,0 +1,125 @@ + + + +Acknowledgments + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHome +
+
+ +

+ + Pre-formal + review +

+
    +
  • + Peter Dimov suggested the name 'optional', and was the first to point out + the need for aligned storage. +
  • +
  • + Douglas Gregor developed 'type_with_alignment', and later Eric Friedman + coded 'aligned_storage', which are the core of the optional class implementation. +
  • +
  • + Andrei Alexandrescu and Brian Parker also worked with aligned storage techniques + and their work influenced the current implementation. +
  • +
  • + Gennadiy Rozental made extensive and important comments which shaped the + design. +
  • +
  • + Vesa Karvonen and Douglas Gregor made quite useful comparisons between + optional, variant and any; and made other relevant comments. +
  • +
  • + Douglas Gregor and Peter Dimov commented on comparisons and evaluation + in boolean contexts. +
  • +
  • + Eric Friedman helped understand the issues involved with aligned storage, + move/copy operations and exception safety. +
  • +
  • + Many others have participated with useful comments: Aleksey Gurotov, Kevlin + Henney, David Abrahams, and others I can't recall. +
  • +
+

+ + Post-formal + review +

+
    +
  • + William Kempf carefully considered the originally proposed interface and + suggested the new interface which is currently used. He also started and + fueled the discussion about the analogy optional<>/smart pointer + and about relational operators. +
  • +
  • + Peter Dimov, Joel de Guzman, David Abrahams, Tanton Gibbs and Ian Hanson + focused on the relational semantics of optional (originally undefined); + concluding with the fact that the pointer-like interface doesn't make it + a pointer so it shall have deep relational operators. +
  • +
  • + Augustus Saunders also explored the different relational semantics between + optional<> and a pointer and developed the OptionalPointee concept + as an aid against potential conflicts on generic code. +
  • +
  • + Joel de Guzman noticed that optional<> can be seen as an API on top + of variant<T,nil_t>. +
  • +
  • + Dave Gomboc explained the meaning and usage of the Haskell analog to optional<>: + the Maybe type constructor (analogy originally pointed out by David Sankel). +
  • +
  • + Other comments were posted by Vincent Finn, Anthony Williams, Ed Brey, + Rob Stewart, and others. +
  • +
  • + Joel de Guzman made the case for the support of references and helped with + the proper semantics. +
  • +
  • + Mat Marcus shown the virtues of a value-oriented interface, influencing + the current design, and contributed the idea of "none". +
  • +
+
+ + + +
+
+
+PrevUpHome +
+ + diff --git a/libs/optional/doc/html/boost_optional/dependencies_and_portability.html b/libs/optional/doc/html/boost_optional/dependencies_and_portability.html new file mode 100644 index 00000000..2b4f7c43 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/dependencies_and_portability.html @@ -0,0 +1,91 @@ + + + +Dependencies and Portability + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ The implementation uses the following other Boost modules: +

+
    +
  1. + assert +
  2. +
  3. + config +
  4. +
  5. + core +
  6. +
  7. + detail +
  8. +
  9. + move +
  10. +
  11. + mpl +
  12. +
  13. + static_assert +
  14. +
  15. + throw_exception +
  16. +
  17. + type_traits +
  18. +
  19. + utility +
  20. +
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/dependencies_and_portability/emplace_operations_in_older_compilers.html b/libs/optional/doc/html/boost_optional/dependencies_and_portability/emplace_operations_in_older_compilers.html new file mode 100644 index 00000000..e4c08bcb --- /dev/null +++ b/libs/optional/doc/html/boost_optional/dependencies_and_portability/emplace_operations_in_older_compilers.html @@ -0,0 +1,90 @@ + + + +Emplace operations in older compilers + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Certain constructors and functions + in the interface of optional + perform a 'perfect forwarding' of arguments: +

+
template<class... Args> optional(in_place_init_t, Args&&... args);
+template<class... Args> optional(in_place_init_if_t, bool condition, Args&&... args);
+template<class... Args> void emplace(Args&&... args);
+
+

+ On compilers that do not support variadic templates, each of these functions + is substituted with two overloads, one forwarding a single argument, the + other forwarding zero arguments. This forms the following set: +

+
template<class Arg> optional(in_place_init_t, Arg&& arg);
+optional(in_place_init_t);
+
+template<class Arg> optional(in_place_init_if_t, bool condition, Arg&& arg);
+optional(in_place_init_if_t, bool condition);
+
+template<class Arg> void emplace(Arg&& arg);
+void emplace();
+
+

+ On compilers that do not support rvalue references, each of these functions + is substituted with three overloads: taking const + and non-const lvalue reference, + and third forwarding zero arguments. This forms the following set: +

+
template<class Arg> optional(in_place_init_t, const Arg& arg);
+template<class Arg> optional(in_place_init_t, Arg& arg);
+optional(in_place_init_t);
+
+template<class Arg> optional(in_place_init_if_t, bool condition, const Arg& arg);
+template<class Arg> optional(in_place_init_if_t, bool condition, Arg& arg);
+optional(in_place_init_if_t, bool condition);
+
+template<class Arg> void emplace(const Arg& arg);
+template<class Arg> void emplace(Arg& arg);
+void emplace();
+
+

+ This workaround addresses about 40% of all use cases. If this is insufficient, + you need to resort to using In-Place + Factories. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html b/libs/optional/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html new file mode 100644 index 00000000..9bd61868 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/dependencies_and_portability/optional_reference_binding.html @@ -0,0 +1,107 @@ + + + +Optional Reference Binding + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ A number of compilers incorrectly + treat const lvalues of integral type as rvalues, and create an illegal temporary + when binding to an lvalue reference to const in some expressions. This could + result in creating an optional lvalue reference that is in fact bound to + an unexpected temporary rather than to the intended object. In order to prevent + hard to find run-time bugs, this library performs compile-time checks to + prevent expressions that would otherwise bind an optional reference to an + unexpected temporary. As a consequence, on certain compilers certain pieces + of functionality in optional references are missing. In order to maintain + a portability of your code across different compilers, it is recommended that + you only stick to the minimum portable interface of optional references: + prefer direct-initialization and copy assignment of optional references to + copy-initialization and assignment from T&: +

+
const int i = 0;
+optional<const int&> or1;
+optional<const int&> or2 = i;  // caution: not portable
+or1 = i;                       // caution: not portable
+
+optional<const int&> or3(i);   // portable
+or1 = optional<const int&>(i); // portable
+
+

+ Compilers known to have these deficiencies include GCC versions 4.2, 4.3, + 4.4, 4.5, 5.1, 5.2; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, 11.0, 12.0. + In order to check if your compiler correctly implements reference binding + use this test program. +

+
#include <cassert>
+
+const int global_i = 0;
+
+struct TestingReferenceBinding
+{
+  TestingReferenceBinding(const int& ii)
+  {
+    assert(&ii == &global_i);
+  }
+
+  void operator=(const int& ii)
+  {
+    assert(&ii == &global_i);
+  }
+
+  void operator=(int&&) // remove this if your compiler doesn't have rvalue refs
+  {
+    assert(false);
+  }
+};
+
+int main()
+{
+  const int& iref = global_i;
+  assert(&iref == &global_i);
+
+  TestingReferenceBinding ttt = global_i;
+  ttt = global_i;
+
+  TestingReferenceBinding ttt2 = iref;
+  ttt2 = iref;
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/detailed_semantics.html b/libs/optional/doc/html/boost_optional/detailed_semantics.html new file mode 100644 index 00000000..28aa8150 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/detailed_semantics.html @@ -0,0 +1,1975 @@ + + + +Detailed Semantics + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Because T might be of reference + type, in the sequel, those entries whose semantic depends on T being of reference type or not will be + distinguished using the following convention: +

+
    +
  • + If the entry reads: optional<T(not + a ref)>, the + description corresponds only to the case where T + is not of reference type. +
  • +
  • + If the entry reads: optional<T&>, the description corresponds only + to the case where T is + of reference type. +
  • +
  • + If the entry reads: optional<T>, the description is the same for both + cases. +
  • +
+
+ + + + + +
[Note]Note

+ The following section contains various assert() which are used only to show the postconditions + as sample code. It is not implied that the type T + must support each particular expression but that if the expression is supported, + the implied condition holds. +

+

+ space +

+

+ + optional + class member functions +

+

+ space +

+

+ optional<T>::optional() noexcept; +

+
    +
  • + Effect: Default-Constructs an optional. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
  • + Notes: T's default constructor is not called. +
  • +
  • + Example: +
    optional<T> def ;
    +assert ( !def ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( none_t ) noexcept; +

+
    +
  • + Effect: Constructs an optional + uninitialized. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
  • + Notes: T's + default constructor is not called. + The expression boost::none denotes an instance of boost::none_t that can be used as the parameter. +
  • +
  • + Example: +
    #include <boost/none.hpp>
    +optional<T> n(none) ;
    +assert ( !n ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)>::optional( T const& v ) +

+
    +
  • + Requires: is_copy_constructible<T>::value + is true. +
  • +
  • + Effect: Directly-Constructs an optional. +
  • +
  • + Postconditions: *this is initialized + and its value is a copy of v. +
  • +
  • + Throws: Whatever T::T( + T const& ) + throws. +
  • +
  • + Notes: T::T( + T const& ) + is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T + const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +assert ( *opt == v ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( T& ref ) +

+
    +
  • + Effect: Directly-Constructs an optional. +
  • +
  • + Postconditions: *this is initialized + and its value is an instance of an internal type wrapping the reference + ref. +
  • +
  • + Throws: Nothing. +
  • +
  • + Example: +
    T v;
    +T& vref = v ;
    +optional<T&> opt(vref);
    +assert ( *opt == v ) ;
    +++ v ; // mutate referee
    +assert (*opt == v);
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)>::optional( T&& + v ) +

+
    +
  • + Requires: is_move_constructible<T>::value + is true. +
  • +
  • + Effect: Directly-Move-Constructs an optional. +
  • +
  • + Postconditions: *this is initialized + and its value is move-constructed from v. +
  • +
  • + Throws: Whatever T::T( + T&& + ) throws. +
  • +
  • + Notes: T::T( + T&& + ) is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T&& ); + in that case, the state of v + is determined by exception safety guarantees for T::T(T&&). +
  • +
  • + Example: +
    T v1, v2;
    +optional<T> opt(std::move(v1));
    +assert ( *opt == v2 ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( T&& ref ) = delete +

+
  • + Notes: This constructor is deleted +
+

+ space +

+

+ optional<T (not a ref)>::optional( bool condition, T const& v ) ; +

+

+ optional<T&> ::optional( bool condition, T& + v ) ; +

+
  • + If condition is true, same as: +
+

+ optional<T (not a ref)>::optional( T const& v ) +

+

+ optional<T&> ::optional( T& + v ) +

+
  • + otherwise, same as: +
+

+ optional<T (not a ref)>::optional() +

+

+ optional<T&> ::optional() +

+

+ space +

+

+ optional<T (not a ref)>::optional( optional const& rhs ); +

+
    +
  • + Requires: is_copy_constructible<T>::value + is true. +
  • +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs is initialized, + *this + is initialized and its value is a copy of the value + of rhs; else *this is + uninitialized. +
  • +
  • + Throws: Whatever T::T( + T const& ) + throws. +
  • +
  • + Notes: If rhs is initialized, T::T(T const& ) + is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T + const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    optional<T> uninit ;
    +assert (!uninit);
    +
    +optional<T> uinit2 ( uninit ) ;
    +assert ( uninit2 == uninit );
    +
    +optional<T> init( T(2) );
    +assert ( *init == T(2) ) ;
    +
    +optional<T> init2 ( init ) ;
    +assert ( init2 == init ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( optional const& rhs ); +

+
    +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is another reference to the same object referenced + by *rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: If rhs + is initialized, both *this + and *rhs + will reefer to the same object (they alias). +
  • +
  • + Example: +
    optional<T&> uninit ;
    +assert (!uninit);
    +
    +optional<T&> uinit2 ( uninit ) ;
    +assert ( uninit2 == uninit );
    +
    +T v = 2 ; T& ref = v ;
    +optional<T> init(ref);
    +assert ( *init == v ) ;
    +
    +optional<T> init2 ( init ) ;
    +assert ( *init2 == v ) ;
    +
    +v = 3 ;
    +
    +assert ( *init  == 3 ) ;
    +assert ( *init2 == 3 ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)>::optional( optional&& rhs + ) noexcept(see below); +

+
    +
  • + Requires: is_move_constructible<T>::value + is true. +
  • +
  • + Effect: Move-constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move constructed from rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( + T&& + ) throws. +
  • +
  • + Notes: If rhs + is initialized, T::T( T + && ) + is called. The expression inside noexcept + is equivalent to is_nothrow_move_constructible<T>::value. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T&& ); + in that case, rhs remains + initialized and the value of *rhs is determined by exception safety + of T::T(T&&). +
  • +
  • + Example: +
    optional<std::unique_ptr<T>> uninit ;
    +assert (!uninit);
    +
    +optional<std::unique_ptr<T>> uinit2 ( std::move(uninit) ) ;
    +assert ( uninit2 == uninit );
    +
    +optional<std::unique_ptr<T>> init( std::unique_ptr<T>(new T(2)) );
    +assert ( **init == T(2) ) ;
    +
    +optional<std::unique_ptr<T>> init2 ( std::move(init) ) ;
    +assert ( init );
    +assert ( *init == nullptr );
    +assert ( init2 );
    +assert ( **init2 == T(2) ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( optional && + rhs ); +

+
    +
  • + Effect: Move-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is another reference to the same object referenced + by *rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: If rhs + is initialized, both *this + and *rhs + will reefer to the same object (they alias). +
  • +
  • + Example: +
    optional<std::unique_ptr<T>&> uninit ;
    +assert (!uninit);
    +
    +optional<std::unique_ptr<T>&> uinit2 ( std::move(uninit) ) ;
    +assert ( uninit2 == uninit );
    +
    +std::unique_ptr<T> v(new T(2)) ;
    +optional<std::unique_ptr<T>&> init(v);
    +assert ( *init == v ) ;
    +
    +optional<std::unique_ptr<T>&> init2 ( std::move(init) ) ;
    +assert ( *init2 == v ) ;
    +
    +*v = 3 ;
    +
    +assert ( **init  == 3 ) ;
    +assert ( **init2 == 3 ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> explicit optional<T + (not a ref)>::optional( optional<U> const& rhs ); +

+
    +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is a copy of the value + of rhs converted to type T; + else *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( + U const& ) + throws. +
  • +
  • + Notes: T::T( + U const& ) + is called if rhs is initialized, + which requires a valid conversion from U + to T. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( U + const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    optional<double> x(123.4);
    +assert ( *x == 123.4 ) ;
    +
    +optional<int> y(x) ;
    +assert( *y == 123 ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> explicit optional<T + (not a ref)>::optional( optional<U>&& + rhs ); +

+
    +
  • + Effect: Move-constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move constructed from *rhs; else *this is uninitialized. +
  • +
  • + Throws: Whatever T::T( + U&& + ) throws. +
  • +
  • + Notes: T::T( + U&& + ) is called if rhs + is initialized, which requires a valid conversion from U + to T. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( U&& ); + in that case, rhs remains + initialized and the value of *rhs is determined by exception safety + guarantee of T::T( U&& ). +
  • +
  • + Example: +
    optional<double> x(123.4);
    +assert ( *x == 123.4 ) ;
    +
    +optional<int> y(std::move(x)) ;
    +assert( *y == 123 ) ;
    +
    +
  • +
+

+ space +

+

+ template<InPlaceFactory> + explicit optional<T + (not a ref)>::optional( InPlaceFactory const& f ); +

+

+ template<TypedInPlaceFactory> + explicit optional<T + (not a ref)>::optional( TypedInPlaceFactory const& f ); +

+
    +
  • + Effect: Constructs an optional + with a value of T obtained + from the factory. +
  • +
  • + Postconditions: *this is initialized + and its value is directly given from the factory + f (i.e., the value is not copied). +
  • +
  • + Throws: Whatever the T + constructor called by the factory throws. +
  • +
  • + Notes: See In-Place + Factories +
  • +
  • + Exception Safety: Exceptions can only + be thrown during the call to the T + constructor used by the factory; in that case, this constructor has no + effect. +
  • +
  • + Example: +
    class C { C ( char, double, std::string ) ; } ;
    +
    +C v('A',123.4,"hello");
    +
    +optional<C> x( in_place   ('A', 123.4, "hello") ); // InPlaceFactory used
    +optional<C> y( in_place<C>('A', 123.4, "hello") ); // TypedInPlaceFactory used
    +
    +assert ( *x == v ) ;
    +assert ( *y == v ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( none_t ) noexcept; +

+
    +
  • + Effect: If *this is initialized destroys its contained + value. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( T + const& + rhs ) + ; +

+
    +
  • + Effect: Assigns the value rhs to an optional. +
  • +
  • + Postconditions: *this is initialized and its value is a + copy of rhs. +
  • +
  • + Throws: Whatever T::operator=( T const& ) or T::T(T const&) throws. +
  • +
  • + Notes: If *this was initialized, T's + assignment operator is used, otherwise, its copy-constructor is used. +
  • +
  • + Exception Safety: In the event of an exception, + the initialization state of *this is unchanged and its value unspecified + as far as optional is concerned + (it is up to T's operator=()). + If *this + is initially uninitialized and T's + copy constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T x;
    +optional<T> def ;
    +optional<T> opt(x) ;
    +
    +T y;
    +def = y ;
    +assert ( *def == y ) ;
    +opt = y ;
    +assert ( *opt == y ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>& + optional<T&>::operator= ( T& + rhs ) + ; +

+
    +
  • + Effect: (Re)binds the wrapped reference. +
  • +
  • + Postconditions: *this is initialized and it references the + same object referenced by rhs. +
  • +
  • + Notes: If *this was initialized, it is rebound + to the new object. See here + for details on this behavior. +
  • +
  • + Example: +
    int a = 1 ;
    +int b = 2 ;
    +T& ra = a ;
    +T& rb = b ;
    +optional<int&> def ;
    +optional<int&> opt(ra) ;
    +
    +def = rb ; // binds 'def' to 'b' through 'rb'
    +assert ( *def == b ) ;
    +*def = a ; // changes the value of 'b' to a copy of the value of 'a'
    +assert ( b == a ) ;
    +int c = 3;
    +int& rc = c ;
    +opt = rc ; // REBINDS to 'c' through 'rc'
    +c = 4 ;
    +assert ( *opt == 4 ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( T&& rhs + ) ; +

+
    +
  • + Effect: Moves the value rhs to an optional. +
  • +
  • + Postconditions: *this is initialized and its value is moved + from rhs. +
  • +
  • + Throws: Whatever T::operator=( T&& ) + or T::T(T + &&) throws. +
  • +
  • + Notes: If *this was initialized, T's + move-assignment operator is used, otherwise, its move-constructor is used. +
  • +
  • + Exception Safety: In the event of an exception, + the initialization state of *this is unchanged and its value unspecified + as far as optional is concerned + (it is up to T's operator=()). + If *this + is initially uninitialized and T's + move constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T x;
    +optional<T> def ;
    +optional<T> opt(x) ;
    +
    +T y1, y2, yR;
    +def = std::move(y1) ;
    +assert ( *def == yR ) ;
    +opt = std::move(y2) ;
    +assert ( *opt == yR ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>& + optional<T&>::operator= ( T&& + rhs ) + = delete; +

+
  • + Notes: This assignment operator is deleted. +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( optional + const& + rhs ) + ; +

+
    +
  • + Effect: Assigns another optional to an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is a copy of the value + of rhs; else *this is + uninitialized. +
  • +
  • + Throws: Whatever T::operator( T const&) + or T::T( T + const& + ) throws. +
  • +
  • + Notes: If both *this and rhs + are initially initialized, T's + assignment operator is used. If *this is initially initialized but rhs is uninitialized, T's + [destructor] is called. If *this is initially uninitialized but rhs is initialized, T's + copy constructor is called. +
  • +
  • + Exception Safety: In the event of an exception, + the initialization state of *this is unchanged and its value unspecified + as far as optional is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + copy constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +optional<T> def ;
    +
    +opt = def ;
    +assert ( !def ) ;
    +// previous value (copy of 'v') destroyed from within 'opt'.
    +
    +
  • +
+

+ space +

+

+ optional<T&> & optional<T&>::operator= ( optional<T&> + const& + rhs ) + ; +

+
    +
  • + Effect: (Re)binds thee wrapped reference. +
  • +
  • + Postconditions: If *rhs is initialized, *this is initialized and it references the + same object referenced by *rhs; otherwise, *this is uninitialized (and references no + object). +
  • +
  • + Notes: If *this was initialized and so is *rhs, + *this + is rebound to the new object. See here + for details on this behavior. +
  • +
  • + Example: +
    int a = 1 ;
    +int b = 2 ;
    +T& ra = a ;
    +T& rb = b ;
    +optional<int&> def ;
    +optional<int&> ora(ra) ;
    +optional<int&> orb(rb) ;
    +
    +def = orb ; // binds 'def' to 'b' through 'rb' wrapped within 'orb'
    +assert ( *def == b ) ;
    +*def = ora ; // changes the value of 'b' to a copy of the value of 'a'
    +assert ( b == a ) ;
    +int c = 3;
    +int& rc = c ;
    +optional<int&> orc(rc) ;
    +ora = orc ; // REBINDS ora to 'c' through 'rc'
    +c = 4 ;
    +assert ( *ora == 4 ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( optional&& rhs + ) noexcept(see below); +

+
    +
  • + Effect: Move-assigns another optional to an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is moved from *rhs, rhs + remains initialized; else *this is uninitialized. +
  • +
  • + Throws: Whatever T::operator( T&& + ) or T::T( + T && + ) throws. +
  • +
  • + Notes: If both *this and rhs + are initially initialized, T's + move assignment operator is used. If *this is + initially initialized but rhs + is uninitialized, T's [destructor] + is called. If *this + is initially uninitialized but rhs + is initialized, T's move + constructor is called. The expression inside noexcept + is equivalent to is_nothrow_move_constructible<T>::value + && is_nothrow_move_assignable<T>::value. +
  • +
  • + Exception Safety: In the event of an exception, + the initialization state of *this is unchanged and its value unspecified + as far as optional is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + move constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    optional<T> opt(T(2)) ;
    +optional<T> def ;
    +
    +opt = def ;
    +assert ( def ) ;
    +assert ( opt ) ;
    +assert ( *opt == T(2) ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&> & optional<T&>::operator= ( optional<T&>&& + rhs ) + ; +

+
  • + Effect: Same as optional<T&>::operator= ( optional<T&> const& rhs ). +
+

+ space +

+

+ template<U> optional& + optional<T (not a ref)>::operator= ( optional<U> + const& + rhs ) + ; +

+
    +
  • + Effect: Assigns another convertible optional + to an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is a copy of the value + of rhs converted + to type T; else *this is + uninitialized. +
  • +
  • + Throws: Whatever T::operator=( U const& ) or T::T( + U const& ) + throws. +
  • +
  • + Notes: If both *this and rhs are initially initialized, + T's assignment + operator (from U) + is used. If *this + is initially initialized but rhs + is uninitialized, T's + destructor is called. If *this is initially uninitialized but rhs + is initialized, T's converting + constructor (from U) + is called. +
  • +
  • + Exception Safety: In the event of an exception, + the initialization state of *this is unchanged and its value unspecified + as far as optional is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + converting constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T v;
    +optional<T> opt0(v);
    +optional<U> opt1;
    +
    +opt1 = opt0 ;
    +assert ( *opt1 == static_cast<U>(v) ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> optional& + optional<T (not a ref)>::operator= ( optional<U>&& + rhs ) + ; +

+
    +
  • + Effect: Move-assigns another convertible + optional to an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is moved from the value of rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Whatever T::operator=( U&& ) + or T::T( U&& ) + throws. +
  • +
  • + Notes: If both *this and rhs + are initially initialized, T's + assignment operator (from U&&) is used. If *this is initially initialized but rhs is uninitialized, T's + destructor is called. If *this is initially uninitialized but rhs is initialized, T's + converting constructor (from U&&) is called. +
  • +
  • + Exception Safety: In the event of an exception, + the initialization state of *this is unchanged and its value unspecified + as far as optional is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + converting constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T v;
    +optional<T> opt0(v);
    +optional<U> opt1;
    +
    +opt1 = std::move(opt0) ;
    +assert ( *opt1 == static_cast<U>(v) ) ;
    +
    +
  • +
+

+ space +

+

+ template<class... Args> void optional<T + (not a ref)>::emplace( Args...&& + args ); +

+
    +
  • + Requires: The compiler supports rvalue + references and variadic templates. +
  • +
  • + Effect: If *this is initialized calls *this = + none. Then initializes in-place + the contained value as if direct-initializing an object of type T with std::forward<Args>(args).... +
  • +
  • + Postconditions: *this is initialized. +
  • +
  • + Throws: Whatever the selected T's constructor throws. +
  • +
  • + Notes: T + need not be MoveConstructible + or MoveAssignable. +
  • +
  • + Exception Safety: If an exception is thrown + during the initialization of T, + *this + is uninitialized. +
  • +
+

+ space +

+

+ template<InPlaceFactory> + optional<T>& optional<T (not a ref)>::operator=( InPlaceFactory + const& + f ); +

+

+ template<TypedInPlaceFactory> + optional<T>& optional<T (not a ref)>::operator=( TypedInPlaceFactory + const& + f ); +

+
    +
  • + Effect: Assigns an optional + with a value of T obtained + from the factory. +
  • +
  • + Postconditions: *this is initialized + and its value is directly given from the factory + f (i.e., the value is not copied). +
  • +
  • + Throws: Whatever the T + constructor called by the factory throws. +
  • +
  • + Notes: See In-Place + Factories +
  • +
  • + Exception Safety: Exceptions can only + be thrown during the call to the T + constructor used by the factory; in that case, the optional + object will be reset to be uninitialized. +
  • +
+

+ space +

+

+ void optional<T + (not a ref)>::reset( T const& v ) ; +

+
  • + Deprecated: same as operator= ( T + const& + v) + ; +
+

+ space +

+

+ void optional<T>::reset() noexcept ; +

+
  • + Deprecated: Same as operator=( none_t ); +
+

+ space +

+

+ T const& optional<T + (not a ref)>::get() const ; +

+

+ T& + optional<T (not a ref)>::get() ; +

+

+ inline T + const& + get ( + optional<T (not a ref)> const& ) ; +

+

+ inline T& get ( optional<T + (not a ref)> + &) ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: A reference to the contained + value +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted via + BOOST_ASSERT(). +
  • +
+

+ space +

+

+ T const& optional<T&>::get() const ; +

+

+ T& + optional<T&>::get() ; +

+

+ inline T + const& + get ( + optional<T&> const& ) ; +

+

+ inline T& get ( optional<T&> + &) ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: The + reference contained. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted via + BOOST_ASSERT(). +
  • +
+

+ space +

+

+ T const& optional<T + (not a ref)>::operator*() const& ; +

+

+ T& + optional<T (not a ref)>::operator*() &; +

+

+ T&& + optional<T (not a ref)>::operator*() &&; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: A reference to the contained + value +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted via + BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions these + three overloads are replaced with the classical two: a const + and non-const member functions. +
  • +
  • + Example: +
    T v ;
    +optional<T> opt ( v );
    +T const& u = *opt;
    +assert ( u == v ) ;
    +T w ;
    +*opt = w ;
    +assert ( *opt == w ) ;
    +
    +
  • +
+

+ space +

+

+ T const& optional<T&>::operator*() const& ; +

+

+ T & + optional<T&>::operator*() & ; +

+

+ T & + optional<T&>::operator*() && ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: The + reference contained. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted via + BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions these + three overloads are replaced with the classical two: a const + and non-const member functions. +
  • +
  • + Example: +
    T v ;
    +T& vref = v ;
    +optional<T&> opt ( vref );
    +T const& vref2 = *opt;
    +assert ( vref2 == v ) ;
    +++ v ;
    +assert ( *opt == v ) ;
    +
    +
  • +
+

+ space +

+

+ T const& optional<T>::value() const& ; +

+

+ T& + optional<T>::value() & ; +

+

+ T&& + optional<T>::value() && ; +

+
    +
  • + Returns: A reference to the contained + value, if *this + is initialized. +
  • +
  • + Throws: An instance of bad_optional_access, + if *this + is not initialized. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions these three overloads are replaced with + the classical two: a const + and non-const member functions. +
  • +
  • + Example: +
    T v ;
    +optional<T> o0, o1 ( v );
    +assert ( o1.value() == v );
    +
    +try {
    +  o0.value(); // throws
    +  assert ( false );
    +}
    +catch(bad_optional_access&) {
    +  assert ( true );
    +}
    +
    + space +
  • +
+

+ template<class U> T optional<T>::value_or(U && + v) const& ; +

+

+ template<class U> T optional<T>::value_or(U && + v) && ; +

+
    +
  • + Requires: T + is CopyConstructible. +
  • +
  • + Returns: First overload: bool(*this) ? **this : static_cast<T>(forward<U>(v)). + second overload: bool(*this) ? + std::move(**this) : + static_cast<T>(forward<U>(v)). +
  • +
  • + Throws: Any exception thrown by the selected + constructor of T. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions these three overloads are replaced with + the classical two: a const + and non-const member functions. + On compilers without rvalue reference support the type of v becomes U + const&. +
  • +
+

+ space +

+

+ T const& optional<T + (not a ref)>::get_value_or( + T const& default) const ; +

+

+ T& + optional<T (not a ref)>::get_value_or( T& + default ) + ; +

+

+ inline T + const& + get_optional_value_or ( + optional<T (not a ref)> const& o, T const& default ) ; +

+

+ inline T& get_optional_value_or + ( optional<T + (not a ref)>& + o, T& default ) ; +

+
    +
  • + Deprecated: Use value_or() instead. +
  • +
  • + Returns: A reference to the contained + value, if any, or default. +
  • +
  • + Throws: Nothing. +
  • +
  • + Example: +
    T v, z ;
    +optional<T> def;
    +T const& y = def.get_value_or(z);
    +assert ( y == z ) ;
    +
    +optional<T> opt ( v );
    +T const& u = get_optional_value_or(opt,z);
    +assert ( u == v ) ;
    +assert ( u != z ) ;
    +
    +
  • +
+

+ space +

+

+ T const* optional<T + (not a ref)>::get_ptr() const ; +

+

+ T* + optional<T (not a ref)>::get_ptr() ; +

+

+ inline T + const* get_pointer ( + optional<T (not a ref)> const& ) ; +

+

+ inline T* get_pointer + ( optional<T + (not a ref)> + &) ; +

+
    +
  • + Returns: If *this is initialized, a pointer to the contained + value; else 0 (null). +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The contained value is permanently + stored within *this, + so you should not hold nor delete this pointer +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +optional<T> const copt(v);
    +T* p = opt.get_ptr() ;
    +T const* cp = copt.get_ptr();
    +assert ( p == get_pointer(opt) );
    +assert ( cp == get_pointer(copt) ) ;
    +
    +
  • +
+

+ space +

+

+ T const* optional<T + (not a ref)>::operator ->() + const ; +

+

+ T* + optional<T (not a ref)>::operator ->() ; +

+
    +
  • + Requires: *this is initialized. +
  • +
  • + Returns: A pointer to the contained value. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted via + BOOST_ASSERT(). +
  • +
  • + Example: +
    struct X { int mdata ; } ;
    +X x ;
    +optional<X> opt (x);
    +opt->mdata = 2 ;
    +
    +
  • +
+

+ space +

+

+ explicit optional<T>::operator bool() const ; +

+
    +
  • + Returns: get_ptr() != 0. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: On compilers that do not support + explicit conversion operators this falls back to safe-bool idiom. +
  • +
  • + Example: +
    optional<T> def ;
    +assert ( def == 0 );
    +optional<T> opt ( v ) ;
    +assert ( opt );
    +assert ( opt != 0 );
    +
    +
  • +
+

+ space +

+

+ bool optional<T>::operator!() noexcept ; +

+
    +
  • + Returns: If *this is uninitialized, true; + else false. +
  • +
  • + Notes: This operator is provided for those + compilers which can't use the unspecified-bool-type operator + in certain boolean contexts. +
  • +
  • + Example: +
    optional<T> opt ;
    +assert ( !opt );
    +*opt = some_T ;
    +
    +// Notice the "double-bang" idiom here.
    +assert ( !!opt ) ;
    +
    +
  • +
+

+ space +

+

+ bool optional<T>::is_initialized() + const ; +

+
  • + Deprecated: Same as explicit + operator bool + () ; +
+

+ space +

+

+ + Free + functions +

+

+ space +

+

+ optional<T (not a ref)> make_optional( T const& v ) +

+
    +
  • + Returns: optional<T>(v) for the deduced type + T of v. +
  • +
  • + Example: +
    template<class T> void foo ( optional<T> const& opt ) ;
    +
    +foo ( make_optional(1+1) ) ; // Creates an optional<int>
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)> make_optional( bool condition, T const& v ) +

+
    +
  • + Returns: optional<T>(condition,v) + for the deduced type T + of v. +
  • +
  • + Example: +
    optional<double> calculate_foo()
    +{
    +  double val = compute_foo();
    +  return make_optional(is_not_nan_and_finite(val),val);
    +}
    +
    +optional<double> v = calculate_foo();
    +if ( !v )
    +  error("foo wasn't computed");
    +
    +
  • +
+

+ space +

+

+ bool operator + == ( optional<T> const& x, optional<T> + const& + y ); +

+
    +
  • + Requires: T + shall meet requirements of EqualityComparable. +
  • +
  • + Returns: If both x + and y are initialized, + (*x + == *y). If + only x or y is initialized, false. + If both are uninitialized, true. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: Pointers have shallow relational + operators while optional + has deep relational operators. Do not use operator + == directly in generic code which + expect to be given either an optional<T> or a pointer; use equal_pointees() + instead +
  • +
  • + Example: +
    T x(12);
    +T y(12);
    +T z(21);
    +optional<T> def0 ;
    +optional<T> def1 ;
    +optional<T> optX(x);
    +optional<T> optY(y);
    +optional<T> optZ(z);
    +
    +// Identity always hold
    +assert ( def0 == def0 );
    +assert ( optX == optX );
    +
    +// Both uninitialized compare equal
    +assert ( def0 == def1 );
    +
    +// Only one initialized compare unequal.
    +assert ( def0 != optX );
    +
    +// Both initialized compare as (*lhs == *rhs)
    +assert ( optX == optY ) ;
    +assert ( optX != optZ ) ;
    +
    +
  • +
+

+ space +

+

+ bool operator + < ( optional<T> const& x, optional<T> + const& + y ); +

+
    +
  • + Requires: T + shall meet requirements of LessThanComparable. +
  • +
  • + Returns: If y + is not initialized, false. + If y is initialized and + x is not initialized, + true. If both x and y + are initialized, (*x + < *y). +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: Pointers have shallow relational + operators while optional + has deep relational operators. Do not use operator + < directly in generic code which + expect to be given either an optional<T> or a pointer; use less_pointees() + instead. +
  • +
  • + Example: +
    T x(12);
    +T y(34);
    +optional<T> def ;
    +optional<T> optX(x);
    +optional<T> optY(y);
    +
    +// Identity always hold
    +assert ( !(def < def) );
    +assert ( optX == optX );
    +
    +// Both uninitialized compare equal
    +assert ( def0 == def1 );
    +
    +// Only one initialized compare unequal.
    +assert ( def0 != optX );
    +
    +// Both initialized compare as (*lhs == *rhs)
    +assert ( optX == optY ) ;
    +assert ( optX != optZ ) ;
    +
    +
  • +
+

+ space +

+

+ bool operator + != ( optional<T> const& x, optional<T> + const& + y ); +

+
    +
  • + Returns: !( + x == + y ); +
  • +
  • + Throws: Nothing. +
  • +
+

+ space +

+

+ bool operator + > ( optional<T> const& x, optional<T> + const& + y ); +

+
    +
  • + Returns: ( + y < + x ); +
  • +
  • + Throws: Nothing. +
  • +
+

+ space +

+

+ bool operator + <= ( + optional<T> const& x, optional<T> + const& + y ); +

+
    +
  • + Returns: !( + y < + x ); +
  • +
  • + Throws: Nothing. +
  • +
+

+ space +

+

+ bool operator + >= ( + optional<T> const& x, optional<T> + const& + y ); +

+
    +
  • + Returns: !( + x<y ); +
  • +
  • + Throws: Nothing. +
  • +
+

+ bool operator + == ( optional<T> const& x, none_t + ) noexcept; +

+
    +
  • + Returns: !x. +
  • +
  • + Notes: T + need not meet requirements of EqualityComparable. +
  • +
+

+ space +

+

+ bool operator + != ( optional<T> const& x, none_t + ) noexcept; +

+
  • + Returns: !( + x == + y ); +
+

+ space +

+

+ void swap + ( optional<T>& + x, optional<T>& y ) ; +

+
    +
  • + Effect: If both x + and y are initialized, + calls swap(*x,*y) using std::swap. + If only one is initialized, say x, + calls: y.reset(*x); x.reset(); If none is initialized, does nothing. +
  • +
  • + Postconditions: The states of x and y + interchanged. +
  • +
  • + Throws: If both are initialized, whatever + swap(T&,T&) + throws. If only one is initialized, whatever T::T ( T&& + ) throws. +
  • +
  • + Notes: If both are initialized, swap(T&,T&) + is used unqualified but with std::swap + introduced in scope. If only one is initialized, T::~T() and T::T( + T&& + ) is called. +
  • +
  • + Exception Safety: If both are initialized, + this operation has the exception safety guarantees of swap(T&,T&). + If only one is initialized, it has the same basic guarantee as optional<T>::operator= ( T&& + ). +
  • +
  • + Example: +
    T x(12);
    +T y(21);
    +optional<T> def0 ;
    +optional<T> def1 ;
    +optional<T> optX(x);
    +optional<T> optY(y);
    +
    +boost::swap(def0,def1); // no-op
    +
    +boost::swap(def0,optX);
    +assert ( *def0 == x );
    +assert ( !optX );
    +
    +boost::swap(def0,optX); // Get back to original values
    +
    +boost::swap(optX,optY);
    +assert ( *optX == y );
    +assert ( *optY == x );
    +
    +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/development.html b/libs/optional/doc/html/boost_optional/development.html new file mode 100644 index 00000000..21e6db44 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/development.html @@ -0,0 +1,412 @@ + + + +Development + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ In C++, we can declare an object (a variable) of type + T, and we can give this variable + an initial value (through an initializer. + (cf. 8.5)). When a declaration includes a non-empty initializer (an initial + value is given), it is said that the object has been initialized. If the + declaration uses an empty initializer (no initial value is given), and neither + default nor value initialization applies, it is said that the object is + uninitialized. Its actual value exist but + has an indeterminate initial value (cf. 8.5/11). optional<T> intends + to formalize the notion of initialization (or lack of it) allowing a program + to test whether an object has been initialized and stating that access to + the value of an uninitialized object is undefined behavior. That is, when + a variable is declared as optional<T> + and no initial value is given, the variable is formally + uninitialized. A formally uninitialized optional object has conceptually + no value at all and this situation can be tested at runtime. It is formally + undefined behavior to try to access the value of an + uninitialized optional. An uninitialized optional can be assigned a value, + in which case its initialization state changes to initialized. Furthermore, + given the formal treatment of initialization states in optional objects, + it is even possible to reset an optional to uninitialized. +

+

+ In C++ there is no formal notion of uninitialized objects, which means that + objects always have an initial value even if indeterminate. As discussed + on the previous section, this has a drawback because you need additional + information to tell if an object has been effectively initialized. One of + the typical ways in which this has been historically dealt with is via a + special value: EOF, npos, -1, etc... This is equivalent to + adding the special value to the set of possible values of a given type. This + super set of T plus some + nil_t—where nil_t + is some stateless POD—can be modeled in modern languages as a discriminated union of T and nil_t. Discriminated + unions are often called variants. A variant has a current + type, which in our case is either T + or nil_t. Using the Boost.Variant library, this model + can be implemented in terms of boost::variant<T,nil_t>. + There is precedent for a discriminated union as a model for an optional value: + the Haskell Maybe + built-in type constructor. Thus, a discriminated union T+nil_t + serves as a conceptual foundation. +

+

+ A variant<T,nil_t> follows naturally from the traditional + idiom of extending the range of possible values adding an additional sentinel + value with the special meaning of Nothing. However, + this additional Nothing value is largely irrelevant + for our purpose since our goal is to formalize the notion of uninitialized + objects and, while a special extended value can be used to convey that meaning, + it is not strictly necessary in order to do so. +

+

+ The observation made in the last paragraph about the irrelevant nature of + the additional nil_t with + respect to purpose of optional<T> suggests + an alternative model: a container that either has a + value of T or nothing. +

+

+ As of this writing I don't know of any precedent for a variable-size fixed-capacity + (of 1) stack-based container model for optional values, yet I believe this + is the consequence of the lack of practical implementations of such a container + rather than an inherent shortcoming of the container model. +

+

+ In any event, both the discriminated-union or the single-element container + models serve as a conceptual ground for a class representing optional—i.e. + possibly uninitialized—objects. For instance, these models show the exact + semantics required for a wrapper of optional values: +

+

+ Discriminated-union: +

+
    +
  • + deep-copy semantics: copies of the variant + implies copies of the value. +
  • +
  • + deep-relational semantics: comparisons + between variants matches both current types and values +
  • +
  • + If the variant's current type is T, + it is modeling an initialized optional. +
  • +
  • + If the variant's current type is not T, + it is modeling an uninitialized optional. +
  • +
  • + Testing if the variant's current type is T + models testing if the optional is initialized +
  • +
  • + Trying to extract a T + from a variant when its current type is not T, + models the undefined behavior of trying to access the value of an uninitialized + optional +
  • +
+

+ Single-element container: +

+
    +
  • + deep-copy semantics: copies of the container + implies copies of the value. +
  • +
  • + deep-relational semantics: comparisons + between containers compare container size and if match, contained value +
  • +
  • + If the container is not empty (contains an object of type T), it is modeling an initialized + optional. +
  • +
  • + If the container is empty, it is modeling an uninitialized + optional. +
  • +
  • + Testing if the container is empty models testing if the optional is initialized +
  • +
  • + Trying to extract a T + from an empty container models the undefined behavior of trying to access + the value of an uninitialized optional +
  • +
+
+
+ +

+ Objects of type optional<T> + are intended to be used in places where objects of type T + would but which might be uninitialized. Hence, optional<T>'s + purpose is to formalize the additional possibly uninitialized state. From + the perspective of this role, optional<T> + can have the same operational semantics of T + plus the additional semantics corresponding to this special state. As such, + optional<T> could + be thought of as a supertype of T. + Of course, we can't do that in C++, so we need to compose the desired semantics + using a different mechanism. Doing it the other way around, that is, making + optional<T> a + subtype of T + is not only conceptually wrong but also impractical: it is not allowed to + derive from a non-class type, such as a built-in type. +

+

+ We can draw from the purpose of optional<T> + the required basic semantics: +

+
    +
  • + Default Construction: To introduce a + formally uninitialized wrapped object. +
  • +
  • + Direct Value Construction via copy: + To introduce a formally initialized wrapped object whose value is obtained + as a copy of some object. +
  • +
  • + Deep Copy Construction: To obtain a + new yet equivalent wrapped object. +
  • +
  • + Direct Value Assignment (upon initialized): + To assign a value to the wrapped object. +
  • +
  • + Direct Value Assignment (upon uninitialized): + To initialize the wrapped object with a value obtained as a copy of some + object. +
  • +
  • + Assignment (upon initialized): To assign + to the wrapped object the value of another wrapped object. +
  • +
  • + Assignment (upon uninitialized): To + initialize the wrapped object with value of another wrapped object. +
  • +
  • + Deep Relational Operations (when supported by the + type T): To compare wrapped object values taking into account + the presence of uninitialized states. +
  • +
  • + Value access: To unwrap the wrapped + object. +
  • +
  • + Initialization state query: To determine + if the object is formally initialized or not. +
  • +
  • + Swap: To exchange wrapped objects. (with + whatever exception safety guarantees are provided by T's + swap). +
  • +
  • + De-initialization: To release the wrapped + object (if any) and leave the wrapper in the uninitialized state. +
  • +
+

+ Additional operations are useful, such as converting constructors and converting + assignments, in-place construction and assignment, and safe value access + via a pointer to the wrapped object or null. +

+
+
+ +

+ Since the purpose of optional is to allow us to use objects with a formal + uninitialized additional state, the interface could try to follow the interface + of the underlying T type + as much as possible. In order to choose the proper degree of adoption of + the native T interface, the + following must be noted: Even if all the operations supported by an instance + of type T are defined for + the entire range of values for such a type, an optional<T> + extends such a set of values with a new value for which most (otherwise valid) + operations are not defined in terms of T. +

+

+ Furthermore, since optional<T> + itself is merely a T wrapper + (modeling a T supertype), + any attempt to define such operations upon uninitialized optionals will be + totally artificial w.r.t. T. +

+

+ This library chooses an interface which follows from T's + interface only for those operations which are well defined (w.r.t the type + T) even if any of the operands + are uninitialized. These operations include: construction, copy-construction, + assignment, swap and relational operations. +

+

+ For the value access operations, which are undefined (w.r.t the type T) when the operand is uninitialized, a + different interface is chosen (which will be explained next). +

+

+ Also, the presence of the possibly uninitialized state requires additional + operations not provided by T + itself which are supported by a special interface. +

+
+ + Lexically-hinted + Value Access in the presence of possibly uninitialized optional objects: The + operators * and -> +
+

+ A relevant feature of a pointer is that it can have a null + pointer value. This is a special value which + is used to indicate that the pointer is not referring to any object at all. + In other words, null pointer values convey the notion of nonexistent objects. +

+

+ This meaning of the null pointer value allowed pointers to became a de + facto standard for handling optional objects because all you have + to do to refer to a value which you don't really have is to use a null pointer + value of the appropriate type. Pointers have been used for decades—from + the days of C APIs to modern C++ libraries—to refer + to optional (that is, possibly nonexistent) objects; particularly as optional + arguments to a function, but also quite often as optional data members. +

+

+ The possible presence of a null pointer value makes the operations that access + the pointee's value possibly undefined, therefore, expressions which use + dereference and access operators, such as: ( + *p = 2 ) + and ( p->foo() ), implicitly + convey the notion of optionality, and this information is tied to the syntax + of the expressions. That is, the presence of operators * + and -> tell by themselves + —without any additional context— that the expression will be undefined + unless the implied pointee actually exist. +

+

+ Such a de facto idiom for referring to optional objects + can be formalized in the form of a concept: the OptionalPointee + concept. This concept captures the syntactic usage of operators *, -> + and contextual conversion to bool + to convey the notion of optionality. +

+

+ However, pointers are good to refer + to optional objects, but not particularly good to handle the optional objects + in all other respects, such as initializing or moving/copying them. The problem + resides in the shallow-copy of pointer semantics: if you need to effectively + move or copy the object, pointers alone are not enough. The problem is that + copies of pointers do not imply copies of pointees. For example, as was discussed + in the motivation, pointers alone cannot be used to return optional objects + from a function because the object must move outside from the function and + into the caller's context. +

+

+ A solution to the shallow-copy problem that is often used is to resort to + dynamic allocation and use a smart pointer to automatically handle the details + of this. For example, if a function is to optionally return an object X, it can use shared_ptr<X> + as the return value. However, this requires dynamic allocation of X. If X + is a built-in or small POD, this technique is very poor in terms of required + resources. Optional objects are essentially values so it is very convenient + to be able to use automatic storage and deep-copy semantics to manipulate + optional values just as we do with ordinary values. Pointers do not have + this semantics, so are inappropriate for the initialization and transport + of optional values, yet are quite convenient for handling the access to the + possible undefined value because of the idiomatic aid present in the OptionalPointee concept + incarnated by pointers. +

+
+ + Optional<T> + as a model of OptionalPointee +
+

+ For value access operations optional<> uses operators * + and -> to lexically warn + about the possibly uninitialized state appealing to the familiar pointer + semantics w.r.t. to null pointers. +

+
+ + + + + +
[Warning]Warning

+ However, it is particularly important to note that optional<> objects are not pointers. optional<> is not, and does not model, a pointer. +

+

+ For instance, optional<> + does not have shallow-copy so does not alias: two different optionals never + refer to the same value unless T + itself is a reference (but may have equivalent values). + The difference between an optional<T> + and a pointer must be kept in mind, particularly because the semantics of + relational operators are different: since optional<T> + is a value-wrapper, relational operators are deep: they compare optional + values; but relational operators for pointers are shallow: they do not compare + pointee values. As a result, you might be able to replace optional<T> + by T* + on some situations but not always. Specifically, on generic code written + for both, you cannot use relational operators directly, and must use the + template functions equal_pointees() + and less_pointees() + instead. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/discussion.html b/libs/optional/doc/html/boost_optional/discussion.html new file mode 100644 index 00000000..d17a70e8 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/discussion.html @@ -0,0 +1,128 @@ + + + +Discussion + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Consider these functions which should return a value but which might not have + a value to return: +

+
    +
  • + (A) double sqrt(double n ); +
  • +
  • + (B) char get_async_input(); +
  • +
  • + (C) point polygon::get_any_point_effectively_inside(); +
  • +
+

+ There are different approaches to the issue of not having a value to return. +

+

+ A typical approach is to consider the existence of a valid return value as + a postcondition, so that if the function cannot compute the value to return, + it has either undefined behavior (and can use assert in a debug build) or uses + a runtime check and throws an exception if the postcondition is violated. This + is a reasonable choice for example, for function (A), because the lack of a + proper return value is directly related to an invalid parameter (out of domain + argument), so it is appropriate to require the callee to supply only parameters + in a valid domain for execution to continue normally. +

+

+ However, function (B), because of its asynchronous nature, does not fail just + because it can't find a value to return; so it is incorrect to consider such + a situation an error and assert or throw an exception. This function must return, + and somehow, must tell the callee that it is not returning a meaningful value. +

+

+ A similar situation occurs with function (C): it is conceptually an error to + ask a null-area polygon to return a point inside itself, + but in many applications, it is just impractical for performance reasons to + treat this as an error (because detecting that the polygon has no area might + be too expensive to be required to be tested previously), and either an arbitrary + point (typically at infinity) is returned, or some efficient way to tell the + callee that there is no such point is used. +

+

+ There are various mechanisms to let functions communicate that the returned + value is not valid. One such mechanism, which is quite common since it has + zero or negligible overhead, is to use a special value which is reserved to + communicate this. Classical examples of such special values are EOF, string::npos, points + at infinity, etc... +

+

+ When those values exist, i.e. the return type can hold all meaningful values + plus the signal value, this mechanism + is quite appropriate and well known. Unfortunately, there are cases when such + values do not exist. In these cases, the usual alternative is either to use + a wider type, such as int in place + of char; or a compound type, such + as std::pair<point,bool>. +

+

+ Returning a std::pair<T,bool>, thus attaching a boolean flag to the result + which indicates if the result is meaningful, has the advantage that can be + turned into a consistent idiom since the first element of the pair can be whatever + the function would conceptually return. For example, the last two functions + could have the following interface: +

+
std::pair<char,bool> get_async_input();
+std::pair<point,bool> polygon::get_any_point_effectively_inside();
+
+

+ These functions use a consistent interface for dealing with possibly nonexistent + results: +

+
std::pair<point,bool> p = poly.get_any_point_effectively_inside();
+if ( p.second )
+    flood_fill(p.first);
+
+

+ However, not only is this quite a burden syntactically, it is also error prone + since the user can easily use the function result (first element of the pair) + without ever checking if it has a valid value. +

+

+ Clearly, we need a better idiom. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/examples.html b/libs/optional/doc/html/boost_optional/examples.html new file mode 100644 index 00000000..64a95a97 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/examples.html @@ -0,0 +1,147 @@ + + + +Examples + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +
optional<char> get_async_input()
+{
+    if ( !queue.empty() )
+        return optional<char>(queue.top());
+    else return optional<char>(); // uninitialized
+}
+
+void receive_async_message()
+{
+    optional<char> rcv ;
+    // The safe boolean conversion from 'rcv' is used here.
+    while ( (rcv = get_async_input()) && !timeout() )
+        output(*rcv);
+}
+
+
+
+ +
optional<string> name ;
+if ( database.open() )
+{
+    name = database.lookup(employer_name) ;
+}
+else
+{
+    if ( can_ask_user )
+        name = user.ask(employer_name) ;
+}
+
+if ( name )
+    print(*name);
+else print("employer's name not found!");
+
+
+
+ +
class figure
+{
+    public:
+
+    figure()
+    {
+        // data member 'm_clipping_rect' is uninitialized at this point.
+    }
+
+    void clip_in_rect ( rect const& rect )
+    {
+        ....
+        m_clipping_rect = rect ; // initialized here.
+    }
+
+    void draw ( canvas& cvs )
+    {
+        if ( m_clipping_rect )
+            do_clipping(*m_clipping_rect);
+
+        cvs.drawXXX(..);
+    }
+
+    // this can return NULL.
+    rect const* get_clipping_rect() { return get_pointer(m_clipping_rect); }
+
+    private :
+
+    optional<rect> m_clipping_rect ;
+
+};
+
+
+
+ +
class ExpensiveCtor { ... } ;
+class Fred
+{
+    Fred() : mLargeVector(10000) {}
+
+    std::vector< optional<ExpensiveCtor> > mLargeVector ;
+} ;
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/exception_safety_guarantees.html b/libs/optional/doc/html/boost_optional/exception_safety_guarantees.html new file mode 100644 index 00000000..3cb8b153 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/exception_safety_guarantees.html @@ -0,0 +1,170 @@ + + + +Exception Safety Guarantees + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This library assumes that T's + destructor does not throw exceptions. If it does, the behaviour of many operations + on optional<T> is + undefined. +

+

+ The following mutating operations never throw exceptions: +

+
    +
  • + optional<T>::operator= ( none_t ) noexcept +
  • +
  • + optional<T>::reset() noexcept +
  • +
+

+ In addition, the following constructors and the destructor never throw exceptions: +

+
    +
  • + optional<T>::optional() + noexcept +
  • +
  • + optional<T>::optional( none_t ) noexcept +
  • +
+

+ Regarding the following assignment functions: +

+
    +
  • + optional<T>::operator= ( optional<T> const& ) +
  • +
  • + optional<T>::operator= ( T const& ) +
  • +
  • + template<class U> optional<T>::operator= ( optional<U> const& ) +
  • +
  • + template<class InPlaceFactory> optional<T>::operator= ( InPlaceFactory + const& + ) +
  • +
  • + template<class TypedInPlaceFactory> optional<T>::operator= ( TypedInPlaceFactory + const& + ) +
  • +
  • + optional<T>::reset( T const& ) +
  • +
+

+ They forward calls to the corresponding T's + constructors or assignments (depending on whether the optional object is initialized + or not); so if both T's constructor + and the assignment provide strong exception safety guarantee, optional<T>'s assignment + also provides strong exception safety guarantee; otherwise we only get the + basic guarantee. Additionally, if both involved T's + constructor and the assignment never throw, optional<T>'s + assignment also never throws. +

+

+ Unless T's constructor or assignment + throws, assignments to optional<T> + do not throw anything else on its own. A throw during assignment never changes + the initialization state of any optional object involved: +

+
optional<T> opt1(val1);
+optional<T> opt2(val2);
+assert(opt1);
+assert(opt2);
+
+try
+{
+  opt1 = opt2; // throws
+}
+catch(...)
+{
+  assert(opt1);
+  assert(opt2);
+}
+
+

+ This also applies to move assignments/constructors. However, move operations + are made no-throw more often. +

+

+ Operation emplace provides + basic exception safety guarantee. If it throws, the optional object becomes + uninitialized regardless of its initial state, and its previous contained value + (if any) is destroyed. It doesn't call any assignment or move/copy constructor + on T. +

+

+ + Swap +

+

+ Unless swap on optional is + customized, its primary implementation forwards calls to T's + swap or move constructor (depending + on the initialization state of the optional objects). Thus, if both T's swap + and move constructor never throw, swap + on optional<T> never + throws. similarly, if both T's + swap and move constructor offer + strong guarantee, swap on + optional<T> also + offers a strong guarantee. +

+

+ In case swap on optional is + customized, the call to T's + move constructor are replaced with the calls to T's + default constructor followed by swap. + (This is more useful on older compilers that do not support move semantics, + when one wants to achieve stronger exception safety guarantees.) In this case + the exception safety guarantees for swap + are reliant on the guarantees of T's + swap and default constructor +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/implementation_notes.html b/libs/optional/doc/html/boost_optional/implementation_notes.html new file mode 100644 index 00000000..48d476cd --- /dev/null +++ b/libs/optional/doc/html/boost_optional/implementation_notes.html @@ -0,0 +1,55 @@ + + + +Implementation Notes + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ optional<T> is + currently implemented using a custom aligned storage facility built from alignment_of and type_with_alignment + (both from Type Traits). It uses a separate boolean flag to indicate the initialization + state. Placement new with T's + copy/move constructor and T's + destructor are explicitly used to initialize, copy, move and destroy optional + values. As a result, T's default + constructor is effectively by-passed, but the exception guarantees are basic. + It is planned to replace the current implementation with another with stronger + exception safety, such as a future boost::variant. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/in_place_factories.html b/libs/optional/doc/html/boost_optional/in_place_factories.html new file mode 100644 index 00000000..1cc1e05f --- /dev/null +++ b/libs/optional/doc/html/boost_optional/in_place_factories.html @@ -0,0 +1,196 @@ + + + +In-Place Factories + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ One of the typical problems with wrappers and containers is that their interfaces + usually provide an operation to initialize or assign the contained object as + a copy of some other object. This not only requires the underlying type to + be Copy Constructible, + but also requires the existence of a fully constructed object, often temporary, + just to follow the copy from: +

+
struct X
+{
+    X ( int, std::string ) ;
+} ;
+
+class W
+{
+    X wrapped_ ;
+
+    public:
+
+    W ( X const& x ) : wrapped_(x) {}
+} ;
+
+void foo()
+{
+    // Temporary object created.
+    W ( X(123,"hello") ) ;
+}
+
+

+ A solution to this problem is to support direct construction of the contained + object right in the container's storage. In this scheme, the user only needs + to supply the arguments to the constructor to use in the wrapped object construction. +

+
class W
+{
+    X wrapped_ ;
+
+    public:
+
+    W ( X const& x ) : wrapped_(x) {}
+    W ( int a0, std::string a1) : wrapped_(a0,a1) {}
+} ;
+
+void foo()
+{
+    // Wrapped object constructed in-place
+    // No temporary created.
+    W (123,"hello") ;
+}
+
+

+ A limitation of this method is that it doesn't scale well to wrapped objects + with multiple constructors nor to generic code were the constructor overloads + are unknown. +

+

+ The solution presented in this library is the family of InPlaceFactories + and TypedInPlaceFactories. These factories + are a family of classes which encapsulate an increasing number of arbitrary + constructor parameters and supply a method to construct an object of a given + type using those parameters at an address specified by the user via placement + new. +

+

+ For example, one member of this family looks like: +

+
template<class T,class A0, class A1>
+class TypedInPlaceFactory2
+{
+    A0 m_a0 ; A1 m_a1 ;
+
+    public:
+
+    TypedInPlaceFactory2( A0 const& a0, A1 const& a1 ) : m_a0(a0), m_a1(a1) {}
+
+    void construct ( void* p ) { new (p) T(m_a0,m_a1) ; }
+ } ;
+
+

+ A wrapper class aware of this can use it as: +

+
class W
+{
+    X wrapped_ ;
+
+    public:
+
+    W ( X const& x ) : wrapped_(x) {}
+    W ( TypedInPlaceFactory2 const& fac ) { fac.construct(&wrapped_) ; }
+} ;
+
+void foo()
+{
+    // Wrapped object constructed in-place via a TypedInPlaceFactory.
+    // No temporary created.
+    W ( TypedInPlaceFactory2<X,int,std::string>(123,"hello")) ;
+}
+
+

+ The factories are divided in two groups: +

+
    +
  • + TypedInPlaceFactories: those which + take the target type as a primary template parameter. +
  • +
  • + InPlaceFactories: those with a template + construct(void*) member + function taking the target type. +
  • +
+

+ Within each group, all the family members differ only in the number of parameters + allowed. +

+

+ This library provides an overloaded set of helper template functions to construct + these factories without requiring unnecessary template parameters: +

+
template<class A0,...,class AN>
+InPlaceFactoryN <A0,...,AN> in_place ( A0 const& a0, ..., AN const& aN) ;
+
+template<class T,class A0,...,class AN>
+TypedInPlaceFactoryN <T,A0,...,AN> in_place ( T const& a0, A0 const& a0, ..., AN const& aN) ;
+
+

+ In-place factories can be used generically by the wrapper and user as follows: +

+
class W
+{
+    X wrapped_ ;
+
+    public:
+
+    W ( X const& x ) : wrapped_(x) {}
+
+    template< class InPlaceFactory >
+    W ( InPlaceFactory const& fac ) { fac.template <X>construct(&wrapped_) ; }
+
+} ;
+
+void foo()
+{
+    // Wrapped object constructed in-place via a InPlaceFactory.
+    // No temporary created.
+    W ( in_place(123,"hello") ) ;
+}
+
+

+ The factories are implemented in the headers: in_place_factory.hpp + and typed_in_place_factory.hpp +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/motivation.html b/libs/optional/doc/html/boost_optional/motivation.html new file mode 100644 index 00000000..ee00899c --- /dev/null +++ b/libs/optional/doc/html/boost_optional/motivation.html @@ -0,0 +1,128 @@ + + + +Motivation + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Consider these functions which should return a value but which might not have + a value to return: +

+
    +
  • + (A) double sqrt(double n ); +
  • +
  • + (B) char get_async_input(); +
  • +
  • + (C) point polygon::get_any_point_effectively_inside(); +
  • +
+

+ There are different approaches to the issue of not having a value to return. +

+

+ A typical approach is to consider the existence of a valid return value as + a postcondition, so that if the function cannot compute the value to return, + it has either undefined behavior (and can use assert in a debug build) or uses + a runtime check and throws an exception if the postcondition is violated. This + is a reasonable choice for example, for function (A), because the lack of a + proper return value is directly related to an invalid parameter (out of domain + argument), so it is appropriate to require the callee to supply only parameters + in a valid domain for execution to continue normally. +

+

+ However, function (B), because of its asynchronous nature, does not fail just + because it can't find a value to return; so it is incorrect to consider such + a situation an error and assert or throw an exception. This function must return, + and somehow, must tell the callee that it is not returning a meaningful value. +

+

+ A similar situation occurs with function (C): it is conceptually an error to + ask a null-area polygon to return a point inside itself, + but in many applications, it is just impractical for performance reasons to + treat this as an error (because detecting that the polygon has no area might + be too expensive to be required to be tested previously), and either an arbitrary + point (typically at infinity) is returned, or some efficient way to tell the + callee that there is no such point is used. +

+

+ There are various mechanisms to let functions communicate that the returned + value is not valid. One such mechanism, which is quite common since it has + zero or negligible overhead, is to use a special value which is reserved to + communicate this. Classical examples of such special values are EOF, string::npos, points + at infinity, etc... +

+

+ When those values exist, i.e. the return type can hold all meaningful values + plus the signal value, this mechanism + is quite appropriate and well known. Unfortunately, there are cases when such + values do not exist. In these cases, the usual alternative is either to use + a wider type, such as int in place + of char; or a compound type, such + as std::pair<point,bool>. +

+

+ Returning a std::pair<T,bool>, thus attaching a boolean flag to the result + which indicates if the result is meaningful, has the advantage that can be + turned into a consistent idiom since the first element of the pair can be whatever + the function would conceptually return. For example, the last two functions + could have the following interface: +

+
std::pair<char,bool> get_async_input();
+std::pair<point,bool> polygon::get_any_point_effectively_inside();
+
+

+ These functions use a consistent interface for dealing with possibly nonexistent + results: +

+
std::pair<point,bool> p = poly.get_any_point_effectively_inside();
+if ( p.second )
+    flood_fill(p.first);
+
+

+ However, not only is this quite a burden syntactically, it is also error prone + since the user can easily use the function result (first element of the pair) + without ever checking if it has a valid value. +

+

+ Clearly, we need a better idiom. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/optional_references.html b/libs/optional/doc/html/boost_optional/optional_references.html new file mode 100644 index 00000000..5ff61bf8 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/optional_references.html @@ -0,0 +1,114 @@ + + + +Optional references + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This library allows the template parameter T + to be of reference type: T&, and to some extent, T + const&. +

+

+ However, since references are not real objects some restrictions apply and + some operations are not available in this case: +

+
    +
  • + Converting constructors +
  • +
  • + Converting assignment +
  • +
  • + InPlace construction +
  • +
  • + InPlace assignment +
  • +
  • + Value-access via pointer +
  • +
+

+ Also, even though optional<T&> + treats it wrapped pseudo-object much as a real value, a true real reference + is stored so aliasing will occur: +

+
    +
  • + Copies of optional<T&> + will copy the references but all these references will nonetheless refer + to the same object. +
  • +
  • + Value-access will actually provide access to the referenced object rather + than the reference itself. +
  • +
+
+ + + + + +
[Warning]Warning

+ On compilers that do not conform to Standard C++ rules of reference binding, + operations on optional references might give adverse results: rather than + binding a reference to a designated object they may create an unexpected + temporary and bind to it. For more details see Dependencies + and Portability section. +

+

+ + Rvalue + references +

+

+ Rvalue references and lvalue references to const have the ability in C++ to + extend the life time of a temporary they bind to. Optional references do not + have this capability, therefore to avoid surprising effects it is not possible + to initialize an optional references from a temporary. Optional rvalue references + are disabled altogether. Also, the initialization and assignment of an optional + reference to const from rvalue reference is disabled. +

+
const int& i = 1;            // legal
+optional<const int&> oi = 1; // illegal
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/quick_start.html b/libs/optional/doc/html/boost_optional/quick_start.html new file mode 100644 index 00000000..0388d430 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/quick_start.html @@ -0,0 +1,169 @@ + + + +Quick Start + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Let's write and use a converter function that converts a std::string + to an int. It is possible that + for a given string (e.g. "cat") + there exists no value of type int + capable of representing the conversion result. We do not consider such situation + an error. We expect that the converter can be used only to check if the conversion + is possible. A natural signature for this function can be: +

+
#include <boost/optional.hpp>
+boost::optional<int> convert(const std::string& text);
+
+

+ All necessary functionality can be included with one header <boost/optional.hpp>. + The above function signature means that the function can either return a + value of type int or a flag + indicating that no value of int + is available. This does not indicate an error. It is like one additional + value of int. This is how we + can use our function: +

+
const std::string& text = /*... */;
+boost::optional<int> oi = convert(text); // move-construct
+if (oi)                                  // contextual conversion to bool
+  int i = *oi;                           // operator*
+
+

+ In order to test if optional + contains a value, we use the contextual conversion to type bool. Because of this we can combine the initialization + of the optional object and the test into one instruction: +

+
if (boost::optional<int> oi = convert(text))
+  int i = *oi;
+
+

+ We extract the contained value with operator* (and with operator-> where it makes sense). An attempt to + extract the contained value of an uninitialized optional object is an undefined + behaviour (UB). This implementation guards the call with BOOST_ASSERT. Therefore you should be sure + that the contained value is there before extracting. For instance, the following + code is reasonably UB-safe: +

+
int i = *convert("100");
+
+

+ This is because we know that string value "100" + converts to a valid value of int. + If you do not like this potential UB, you can use an alternative way of extracting + the contained value: +

+
try {
+  int j = convert(text).value();
+}
+catch (const boost::bad_optional_access&) {
+  // deal with it
+}
+
+

+ This version throws an exception upon an attempt to access a nonexistent + contained value. If your way of dealing with the missing value is to use + some default, like 0, there exists + a yet another alternative: +

+
int k = convert(text).value_or(0);
+
+

+ This uses the atoi-like approach + to conversions: if text does + not represent an integral number just return 0. + Finally, you can provide a callback to be called when trying to access the + contained value fails: +

+
int fallback_to_default()
+{
+  cerr << "could not convert; using -1 instead" << endl;
+  return -1;
+}
+
+int l = convert(text).value_or_eval(fallback_to_default);
+
+

+ This will call the provided callback and return whatever the callback returns. + The callback can have side effects: they will only be observed when the optional + object does not contain a value. +

+

+ Now, let's consider how function convert + can be implemented. +

+
boost::optional<int> convert(const std::string& text)
+{
+  std::stringstream s(text);
+  int i;
+  if ((s >> i) && s.get() == std::char_traits<char>::eof())
+    return i;
+  else
+    return boost::none;
+}
+
+

+ Observe the two return statements. return + i uses the converting constructor + that can create optional<T> + from T. Thus constructed + optional object is initialized and its value is a copy of i. + The other return statement uses another converting constructor from a special + tag boost::none. It is used to indicate that we want + to create an uninitialized optional object. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/quick_start/bypassing_unnecessary_default_construction.html b/libs/optional/doc/html/boost_optional/quick_start/bypassing_unnecessary_default_construction.html new file mode 100644 index 00000000..b49c8abe --- /dev/null +++ b/libs/optional/doc/html/boost_optional/quick_start/bypassing_unnecessary_default_construction.html @@ -0,0 +1,75 @@ + + + +Bypassing unnecessary default construction + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Suppose we have class Date, + which does not have a default constructor: there is no good candidate for + a default date. We have a function that returns two dates in form of a boost::tuple: +

+
boost::tuple<Date, Date> getPeriod();
+
+

+ In other place we want to use the result of getPeriod, + but want the two dates to be named: begin + and end. We want to implement + something like 'multiple return values': +

+
Date begin, end; // Error: no default ctor!
+boost::tie(begin, end) = getPeriod();
+
+

+ The second line works already, this is the capability of Boost.Tuple + library, but the first line won't work. We could set some invented initial + dates, but it is confusing and may be an unacceptable cost, given that these + values will be overwritten in the next line anyway. This is where optional can help: +

+
boost::optional<Date> begin, end;
+boost::tie(begin, end) = getPeriod();
+
+

+ It works because inside boost::tie a + move-assignment from T is + invoked on optional<T>, + which internally calls a move-constructor of T. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/quick_start/optional_automatic_variables.html b/libs/optional/doc/html/boost_optional/quick_start/optional_automatic_variables.html new file mode 100644 index 00000000..e4bf47a1 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/quick_start/optional_automatic_variables.html @@ -0,0 +1,75 @@ + + + +Optional automatic variables + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ We could write function convert + in a slightly different manner, so that it has a single return-statement: +

+
boost::optional<int> convert(const std::string& text)
+{
+  boost::optional<int> ans;
+  std::stringstream s(text);
+  int i;
+  if ((s >> i) && s.get() == std::char_traits<char>::eof())
+    ans = i;
+
+  return ans;
+}
+
+

+ The default constructor of optional + creates an uninitialized optional object. Unlike with ints + you cannot have an optional<int> + in an indeterminate state. Its state is always well defined. Instruction + ans = + i initializes the optional object. + It uses the 'mixed' assignment from int. + In general, for optional<T>, + when an assignment from T + is invoked, it can do two things. If the optional object is not initialized + (our case here), it initializes the contained value using T's + copy constructor. If the optional object is already initialized, it assigns + the new value to it using T's + copy assignment. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/quick_start/optional_data_members.html b/libs/optional/doc/html/boost_optional/quick_start/optional_data_members.html new file mode 100644 index 00000000..32684053 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/quick_start/optional_data_members.html @@ -0,0 +1,94 @@ + + + +Optional data members + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Suppose we want to implement a lazy load optimization. + This is because we do not want to perform an expensive initialization of + our Resource until (if at + all) it is really used. We can do it this way: +

+
class Widget
+{
+  mutable boost::optional<const Resource> resource_;
+
+public:
+  Widget() {}
+
+  const Resource& getResource() const // not thread-safe
+  {
+    if (resource_ == boost::none)
+        resource_.emplace("resource", "arguments");
+
+    return *resource_;
+  }
+};
+
+

+ optional's default constructor + creates an uninitialized optional. No call to Resource's + default constructor is attempted. Resource + doesn't have to be DefaultConstructible. In function + getResource we first check + if resource_ is initialized. + This time we do not use the contextual conversion to bool, + but a comparison with boost::none. + These two ways are equivalent. Function emplace + initializes the optional in-place by perfect-forwarding the arguments to + the constructor of Resource. + No copy- or move-construction is involved here. Resource + doesn't even have to be MoveConstructible. +

+
+ + + + + +
[Note]Note

+ Function emplace is only + available on compilers that support rvalue references and variadic templates. + If your compiler does not support these features and you still need to + avoid any move-constructions, use In-Place + Factories. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/quick_start/optional_return_values.html b/libs/optional/doc/html/boost_optional/quick_start/optional_return_values.html new file mode 100644 index 00000000..b9953e7e --- /dev/null +++ b/libs/optional/doc/html/boost_optional/quick_start/optional_return_values.html @@ -0,0 +1,135 @@ + + + +Optional return values + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Let's write and use a converter function that converts an a std::string + to an int. It is possible that + for a given string (e.g. "cat") + there exist no value of type int + capable of representing the conversion result. We do not consider such situation + an error. We expect that the converter can be used only to check if the conversion + is possible. A natural signature for this function can be: +

+
#include <boost/optional.hpp>
+boost::optional<int> convert(const std::string& text);
+
+

+ All necessary functionality can be included with one header <boost/optional.hpp>. + The above function signature means that the function can either return a + value of type int or a flag + indicating that no value of int + is available. This does not indicate an error. It is like one additional + value of int. This is how we + can use our function: +

+
const std::string& text = /*... */;
+boost::optional<int> oi = convert(text); // move-construct
+if (oi)                                 // contextual conversion to bool
+  int i = *oi;                          // operator*
+
+

+ In order to test if optional + contains a value, we use the contextual conversion to type bool. Because of this we can combine the initialization + of the optional object and the test into one instruction: +

+
if (boost::optional<int> oi = convert(text))
+  int i = *oi;
+
+

+ We extract the contained value with operator* (and with operator-> where it makes sense). An attempt to + extract the contained value of an uninitialized optional object is an undefined + behaviour (UB). This implementation guards the call with BOOST_ASSERT. Therefore you should be sure + that the contained value is there before extracting. For instance, the following + code is reasonably UB-safe: +

+
int i = *convert("100");
+
+

+ This is because we know that string value "100" + converts to a valid value of int. + If you do not like this potential UB, you can use an alternative way of extracting + the contained value: +

+
try {
+  int j = convert(text).value();
+}
+catch (const boost::bad_optional_access&) {
+  // deal with it
+}
+
+

+ This version throws an exception upon an attempt to access a nonexistent + contained value. If your way of dealing with the missing value is to use + some default, like 0, there exists + a yet another alternative: +

+
int k = convert(text).value_or(0);
+
+

+ This uses the atoi-like approach + to conversions: if text does + not represent an integral number just return 0. + Now, let's consider how function convert + can be implemented. +

+
boost::optional<int> convert(const std::string& text)
+{
+  std::stringstream s(text);
+  int i;
+  if ((s >> i) && s.get() == std::char_traits<char>::eof())
+    return i;
+  else
+    return boost::none;
+}
+
+

+ Observe the two return statements. return + i uses the converting constructor + that can create optional<T> + from T. Thus constructed + optional object is initialized and its value is a copy of i. + The other return statement uses another converting constructor from a special + tag boost::none. It is used to indicate that we want + to create an uninitialized optional object. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/quick_start/storage_in_containers.html b/libs/optional/doc/html/boost_optional/quick_start/storage_in_containers.html new file mode 100644 index 00000000..95809140 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/quick_start/storage_in_containers.html @@ -0,0 +1,64 @@ + + + +Storage in containers + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Suppose you want to ask users to choose some number (an int). + One of the valid responses is to choose nothing, which is represented by + an uninitialized optional<int>. + You want to make a histogram showing how many times each choice was made. + You can use an std::map: +

+
std::map<boost::optional<int>, int> choices;
+
+for (int i = 0; i < LIMIT; ++i) {
+  boost::optional<int> choice = readChoice();
+  ++choices[choice];
+}
+
+

+ This works because optional<T> + is LessThanComparable whenever T is LessThanComparable. In this case + the state of being uninitialized is treated as a yet another value of T, which is compared less than any value + of T. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/rebinding_semantics_for_assignment_of_optional_references.html b/libs/optional/doc/html/boost_optional/rebinding_semantics_for_assignment_of_optional_references.html new file mode 100644 index 00000000..bfcba148 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/rebinding_semantics_for_assignment_of_optional_references.html @@ -0,0 +1,148 @@ + + + +Rebinding semantics for assignment of optional references + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ If you assign to an uninitialized optional<T&> + the effect is to bind (for the first time) to the object. Clearly, there is + no other choice. +

+
int x = 1 ;
+int& rx = x ;
+optional<int&> ora ;
+optional<int&> orb(x) ;
+ora = orb ; // now 'ora' is bound to 'x' through 'rx'
+*ora = 2 ; // Changes value of 'x' through 'ora'
+assert(x==2);
+
+

+ If you assign to a bare C++ reference, the assignment is forwarded to the referenced + object; its value changes but the reference is never rebound. +

+
int a = 1 ;
+int& ra = a ;
+int b = 2 ;
+int& rb = b ;
+ra = rb ; // Changes the value of 'a' to 'b'
+assert(a==b);
+b = 3 ;
+assert(ra!=b); // 'ra' is not rebound to 'b'
+
+

+ Now, if you assign to an initialized optional<T&>, + the effect is to rebind to the new object + instead of assigning the referee. This is unlike bare C++ references. +

+
int a = 1 ;
+int b = 2 ;
+int& ra = a ;
+int& rb = b ;
+optional<int&> ora(ra) ;
+optional<int&> orb(rb) ;
+ora = orb ; // 'ora' is rebound to 'b'
+*ora = 3 ; // Changes value of 'b' (not 'a')
+assert(a==1);
+assert(b==3);
+
+

+ + Rationale +

+

+ Rebinding semantics for the assignment of initialized + optional references has been + chosen to provide consistency among initialization states + even at the expense of lack of consistency with the semantics of bare C++ references. + It is true that optional<U> strives + to behave as much as possible as U + does whenever it is initialized; but in the case when U + is T&, + doing so would result in inconsistent behavior w.r.t to the lvalue initialization + state. +

+

+ Imagine optional<T&> + forwarding assignment to the referenced object (thus changing the referenced + object value but not rebinding), and consider the following code: +

+
optional<int&> a = get();
+int x = 1 ;
+int& rx = x ;
+optional<int&> b(rx);
+a = b ;
+
+

+ What does the assignment do? +

+

+ If a is uninitialized, + the answer is clear: it binds to x + (we now have another reference to x). + But what if a is already initialized? + it would change the value of the referenced object (whatever that is); which + is inconsistent with the other possible case. +

+

+ If optional<T&> + would assign just like T& + does, you would never be able to use Optional's assignment without explicitly + handling the previous initialization state unless your code is capable of functioning + whether after the assignment, a + aliases the same object as b + or not. +

+

+ That is, you would have to discriminate in order to be consistent. +

+

+ If in your code rebinding to another object is not an option, then it is very + likely that binding for the first time isn't either. In such case, assignment + to an uninitialized optional<T&> + shall be prohibited. It is quite possible that in such a scenario it is a precondition + that the lvalue must be already initialized. If it isn't, then binding for + the first time is OK while rebinding is not which is IMO very unlikely. In + such a scenario, you can assign the value itself directly, as in: +

+
assert(!!opt);
+*opt=value;
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/acknowledgements.html b/libs/optional/doc/html/boost_optional/reference/acknowledgements.html new file mode 100644 index 00000000..f5a719de --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/acknowledgements.html @@ -0,0 +1,131 @@ + + + +Acknowledgements + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHome +
+
+ +
+ + Pre-formal + review +
+
    +
  • + Peter Dimov suggested the name 'optional', and was the first to point + out the need for aligned storage. +
  • +
  • + Douglas Gregor developed 'type_with_alignment', and later Eric Friedman + coded 'aligned_storage', which are the core of the optional class implementation. +
  • +
  • + Andrei Alexandrescu and Brian Parker also worked with aligned storage + techniques and their work influenced the current implementation. +
  • +
  • + Gennadiy Rozental made extensive and important comments which shaped + the design. +
  • +
  • + Vesa Karvonen and Douglas Gregor made quite useful comparisons between + optional, variant and any; and made other relevant comments. +
  • +
  • + Douglas Gregor and Peter Dimov commented on comparisons and evaluation + in boolean contexts. +
  • +
  • + Eric Friedman helped understand the issues involved with aligned storage, + move/copy operations and exception safety. +
  • +
  • + Many others have participated with useful comments: Aleksey Gurotov, + Kevlin Henney, David Abrahams, and others I can't recall. +
  • +
+
+ + Post-formal + review +
+
    +
  • + William Kempf carefully considered the originally proposed interface + and suggested the new interface which is currently used. He also started + and fueled the discussion about the analogy optional<>/smart pointer + and about relational operators. +
  • +
  • + Peter Dimov, Joel de Guzman, David Abrahams, Tanton Gibbs and Ian Hanson + focused on the relational semantics of optional (originally undefined); + concluding with the fact that the pointer-like interface doesn't make + it a pointer so it shall have deep relational operators. +
  • +
  • + Augustus Saunders also explored the different relational semantics between + optional<> and a pointer and developed the OptionalPointee concept + as an aid against potential conflicts on generic code. +
  • +
  • + Joel de Guzman noticed that optional<> can be seen as an API on + top of variant<T,nil_t>. +
  • +
  • + Dave Gomboc explained the meaning and usage of the Haskell analog to + optional<>: the Maybe type constructor (analogy originally pointed + out by David Sankel). +
  • +
  • + Other comments were posted by Vincent Finn, Anthony Williams, Ed Brey, + Rob Stewart, and others. +
  • +
  • + Joel de Guzman made the case for the support of references and helped + with the proper semantics. +
  • +
  • + Mat Marcus shown the virtues of a value-oriented interface, influencing + the current design, and contributed the idea of "none". +
  • +
  • + Vladimir Batov's design of Boost.Convert library motivated the development + of value accessors for optional: + functions value, value_or, value_or_eval. +
  • +
+
+ + + +
+
+
+PrevUpHome +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/dependencies_and_portability.html b/libs/optional/doc/html/boost_optional/reference/dependencies_and_portability.html new file mode 100644 index 00000000..5128861e --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/dependencies_and_portability.html @@ -0,0 +1,84 @@ + + + +Dependencies and Portability + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ +

+ The implementation uses the following other Boost modules: +

+
    +
  1. + assert +
  2. +
  3. + config +
  4. +
  5. + core +
  6. +
  7. + detail +
  8. +
  9. + move +
  10. +
  11. + mpl +
  12. +
  13. + static_assert +
  14. +
  15. + throw_exception +
  16. +
  17. + type_traits +
  18. +
  19. + utility +
  20. +
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/dependencies_and_portability/optional_reference_binding.html b/libs/optional/doc/html/boost_optional/reference/dependencies_and_portability/optional_reference_binding.html new file mode 100644 index 00000000..16c16378 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/dependencies_and_portability/optional_reference_binding.html @@ -0,0 +1,100 @@ + + + +Optional Reference Binding + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ On compilers that do not conform to Standard C++ rules of reference binding, + operations on optional references might give adverse results: rather than + binding a reference to a designated object they may create an unexpected + temporary and bind to it. Compilers known to have these deficiencies include + GCC versions 4.2, 4.3, 4.4, 4.5; QCC 4.4.2; MSVC versions 8.0, 9.0, 10.0, + 11.0, 12.0. On these compilers prefer using direct-initialization and copy + assignment of optional references to copy-initialization and assignment + from T&: +

+
const int i = 0;
+optional<const int&> or1;
+optional<const int&> or2 = i;  // not portable
+or1 = i;                       // not portable
+
+optional<const int&> or3(i);   // portable
+or1 = optional<const int&>(i); // portable
+
+

+ In order to check if your compiler correctly implements reference binding + use this test program. +

+
#include <cassert>
+
+const int global_i = 0;
+
+struct TestingReferenceBinding
+{
+  TestingReferenceBinding(const int& ii)
+  {
+    assert(&ii == &global_i);
+  }
+
+  void operator=(const int& ii)
+  {
+    assert(&ii == &global_i);
+  }
+
+  void operator=(int&&) // remove this if your compiler doesn't have rvalue refs
+  {
+    assert(false);
+  }
+};
+
+int main()
+{
+  const int& iref = global_i;
+  assert(&iref == &global_i);
+
+  TestingReferenceBinding ttt = global_i;
+  ttt = global_i;
+
+  TestingReferenceBinding ttt2 = iref;
+  ttt2 = iref;
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_bad_optional_access_hpp_.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_bad_optional_access_hpp_.html new file mode 100644 index 00000000..f5b40337 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_bad_optional_access_hpp_.html @@ -0,0 +1,63 @@ + + + +Header <boost/optional/bad_optional_access.hpp> + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ +

+

+
namespace boost {
+
+class bad_optional_access : public std::logic_error
+{
+public:
+    bad_optional_access(); R
+};
+
+} // namespace boost
+
+

+

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_bad_optional_access_hpp_/detailed_semantics.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_bad_optional_access_hpp_/detailed_semantics.html new file mode 100644 index 00000000..eea25e98 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_bad_optional_access_hpp_/detailed_semantics.html @@ -0,0 +1,60 @@ + + + +Detailed semantics + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ space +

+

+ bad_optional_access(); +

+
    +
  • + Effect: Constructs an object of class + bad_optional_access. +
  • +
  • + Postconditions: what() returns an implementation-defined + NTBS. +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_hpp_.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_hpp_.html new file mode 100644 index 00000000..8390a062 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_hpp_.html @@ -0,0 +1,47 @@ + + + +Header <boost/optional.hpp> + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This is an alias for header <boost/optional/optional.hpp>. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_fwd_hpp_.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_fwd_hpp_.html new file mode 100644 index 00000000..45d55b27 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_fwd_hpp_.html @@ -0,0 +1,66 @@ + + + +Header <boost/optional/optional_fwd.hpp> + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ +

+

+
namespace boost {
+
+template <class T> class optional ;
+
+template <class T> void swap ( optional<T>& , optional<T>& );
+
+template <class T> struct optional_swap_should_use_default_constructor ;
+
+} // namespace boost
+
+

+

+

+ This header only contains declarations. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics.html new file mode 100644 index 00000000..2b6f9eb4 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics.html @@ -0,0 +1,2423 @@ + + + +Detailed Semantics + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Because T might be of reference + type, in the sequel, those entries whose semantic depends on T being of reference type or not will + be distinguished using the following convention: +

+
    +
  • + If the entry reads: optional<T(not + a ref)>, + the description corresponds only to the case where T + is not of reference type. +
  • +
  • + If the entry reads: optional<T&>, the description corresponds + only to the case where T + is of reference type. +
  • +
  • + If the entry reads: optional<T>, the description is the same for + both cases. +
  • +
+
+ + + + + +
[Note]Note

+ The following section contains various assert() which are used only to show the postconditions + as sample code. It is not implied that the type T + must support each particular expression but that if the expression is + supported, the implied condition holds. +

+

+ space +

+
+ + optional + class member functions +
+

+ space +

+

+ optional<T>::optional() + noexcept; +

+
    +
  • + Effect: Default-Constructs an optional. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
  • + Notes: T's default constructor is not called. +
  • +
  • + Example: +
    optional<T> def ;
    +assert ( !def ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( + none_t ) + noexcept; +

+
    +
  • + Effect: Constructs an optional uninitialized. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
  • + Notes: T's + default constructor is not called. + The expression boost::none + denotes an instance of boost::none_t + that can be used as the parameter. +
  • +
  • + Example: +
    #include <boost/none.hpp>
    +optional<T> n(none) ;
    +assert ( !n ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)>::optional( T const& v ) +

+
    +
  • + Requires: is_copy_constructible<T>::value + is true. +
  • +
  • + Effect: Directly-Constructs an optional. +
  • +
  • + Postconditions: *this is initialized + and its value is a copy of v. +
  • +
  • + Throws: Whatever T::T( T const& + ) throws. +
  • +
  • + Notes: T::T( T const& + ) is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +assert ( *opt == v ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( + T& + ref ) +

+
    +
  • + Effect: Directly-Constructs an optional. +
  • +
  • + Postconditions: *this is initialized + and its value is an instance of an internal type wrapping the reference + ref. +
  • +
  • + Throws: Nothing. +
  • +
  • + Example: +
    T v;
    +T& vref = v ;
    +optional<T&> opt(vref);
    +assert ( *opt == v ) ;
    +++ v ; // mutate referee
    +assert (*opt == v);
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)>::optional( T&& v + ) +

+
    +
  • + Requires: is_move_constructible<T>::value + is true. +
  • +
  • + Effect: Directly-Move-Constructs an + optional. +
  • +
  • + Postconditions: *this is initialized + and its value is move-constructed from v. +
  • +
  • + Throws: Whatever T::T( T&& ) + throws. +
  • +
  • + Notes: T::T( T&& ) + is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T&& ); + in that case, the state of v + is determined by exception safety guarantees for T::T(T&&). +
  • +
  • + Example: +
    T v1, v2;
    +optional<T> opt(std::move(v1));
    +assert ( *opt == v2 ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( + T&& + ref ) + = delete +

+
  • + Notes: This constructor is deleted +
+

+ space +

+

+ optional<T (not a ref)>::optional( bool condition, + T const& v ) ; +

+

+ optional<T&> + ::optional( bool condition, + T& + v ) + ; +

+
  • + If condition is true, same as: +
+

+ optional<T (not a ref)>::optional( T const& v ) +

+

+ optional<T&> + ::optional( T& v ) +

+
  • + otherwise, same as: +
+

+ optional<T (not a ref)>::optional() +

+

+ optional<T&> + ::optional() +

+

+ space +

+

+ optional<T (not a ref)>::optional( optional + const& + rhs ); +

+
    +
  • + Requires: is_copy_constructible<T>::value + is true. +
  • +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs is initialized, + *this + is initialized and its value is a copy of the + value of rhs; else + *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( T const& + ) throws. +
  • +
  • + Notes: If rhs is initialized, T::T(T const& ) + is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    optional<T> uninit ;
    +assert (!uninit);
    +
    +optional<T> uinit2 ( uninit ) ;
    +assert ( uninit2 == uninit );
    +
    +optional<T> init( T(2) );
    +assert ( *init == T(2) ) ;
    +
    +optional<T> init2 ( init ) ;
    +assert ( init2 == init ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( + optional const& rhs + ); +

+
    +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is another reference to the same object + referenced by *rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: If rhs + is initialized, both *this and *rhs will refer to the same object + (they alias). +
  • +
  • + Example: +
    optional<T&> uninit ;
    +assert (!uninit);
    +
    +optional<T&> uinit2 ( uninit ) ;
    +assert ( uninit2 == uninit );
    +
    +T v = 2 ; T& ref = v ;
    +optional<T> init(ref);
    +assert ( *init == v ) ;
    +
    +optional<T> init2 ( init ) ;
    +assert ( *init2 == v ) ;
    +
    +v = 3 ;
    +
    +assert ( *init  == 3 ) ;
    +assert ( *init2 == 3 ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)>::optional( optional&& rhs + ) noexcept(see below); +

+
    +
  • + Requires: is_move_constructible<T>::value + is true. +
  • +
  • + Effect: Move-constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move constructed from rhs; else *this is uninitialized. +
  • +
  • + Throws: Whatever T::T( T&& ) + throws. +
  • +
  • + Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible<T>::value. +
  • +
  • + Notes: If rhs + is initialized, T::T( T && + ) is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T&& ); + in that case, rhs remains + initialized and the value of *rhs is determined by exception safety + of T::T(T&&). +
  • +
  • + Example: +
    optional<std::unique_ptr<T>> uninit ;
    +assert (!uninit);
    +
    +optional<std::unique_ptr<T>> uinit2 ( std::move(uninit) ) ;
    +assert ( uninit2 == uninit );
    +
    +optional<std::unique_ptr<T>> init( std::unique_ptr<T>(new T(2)) );
    +assert ( **init == T(2) ) ;
    +
    +optional<std::unique_ptr<T>> init2 ( std::move(init) ) ;
    +assert ( init );
    +assert ( *init == nullptr );
    +assert ( init2 );
    +assert ( **init2 == T(2) ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( + optional && + rhs ); +

+
    +
  • + Effect: Move-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is another reference to the same object + referenced by *rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: If rhs + is initialized, both *this and *rhs will refer to the same object + (they alias). +
  • +
  • + Example: +
    optional<std::unique_ptr<T>&> uninit ;
    +assert (!uninit);
    +
    +optional<std::unique_ptr<T>&> uinit2 ( std::move(uninit) ) ;
    +assert ( uninit2 == uninit );
    +
    +std::unique_ptr<T> v(new T(2)) ;
    +optional<std::unique_ptr<T>&> init(v);
    +assert ( *init == v ) ;
    +
    +optional<std::unique_ptr<T>&> init2 ( std::move(init) ) ;
    +assert ( *init2 == v ) ;
    +
    +*v = 3 ;
    +
    +assert ( **init  == 3 ) ;
    +assert ( **init2 == 3 ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> explicit optional<T + (not a ref)>::optional( + optional<U> const& rhs ); +

+
    +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is a copy of the + value of rhs converted to type T; + else *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( U const& + ) throws. +
  • +
  • + Notes: T::T( U const& + ) is called if rhs is initialized, which requires + a valid conversion from U + to T. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( U const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    optional<double> x(123.4);
    +assert ( *x == 123.4 ) ;
    +
    +optional<int> y(x) ;
    +assert( *y == 123 ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> explicit optional<T + (not a ref)>::optional( + optional<U>&& + rhs ); +

+
    +
  • + Effect: Move-constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move-constructed from *rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( U&& ) + throws. +
  • +
  • + Notes: T::T( U&& ) + is called if rhs is + initialized, which requires a valid conversion from U + to T. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( U&& ); + in that case, rhs remains + initialized and the value of *rhs is determined by exception safety + guarantee of T::T( U&& + ). +
  • +
  • + Example: +
    optional<double> x(123.4);
    +assert ( *x == 123.4 ) ;
    +
    +optional<int> y(std::move(x)) ;
    +assert( *y == 123 ) ;
    +
    +
  • +
+

+ space +

+

+ template<InPlaceFactory> + explicit optional<T + (not a ref)>::optional( + InPlaceFactory const& f ); +

+

+ template<TypedInPlaceFactory> + explicit optional<T + (not a ref)>::optional( + TypedInPlaceFactory const& f ); +

+
    +
  • + Effect: Constructs an optional with a value of T obtained from the factory. +
  • +
  • + Postconditions: *this is initialized + and its value is directly given from the factory + f (i.e., the value + is not copied). +
  • +
  • + Throws: Whatever the T constructor called by the factory + throws. +
  • +
  • + Notes: See In-Place + Factories +
  • +
  • + Exception Safety: Exceptions can only + be thrown during the call to the T + constructor used by the factory; in that case, this constructor has + no effect. +
  • +
  • + Example: +
    class C { C ( char, double, std::string ) ; } ;
    +
    +C v('A',123.4,"hello");
    +
    +optional<C> x( in_place   ('A', 123.4, "hello") ); // InPlaceFactory used
    +optional<C> y( in_place<C>('A', 123.4, "hello") ); // TypedInPlaceFactory used
    +
    +assert ( *x == v ) ;
    +assert ( *y == v ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( none_t + ) noexcept; +

+
    +
  • + Effect: If *this is initialized destroys its contained + value. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( T + const& + rhs ) + ; +

+
    +
  • + Effect: Assigns the value rhs to an optional. +
  • +
  • + Postconditions: *this is initialized and its value is + a copy of rhs. +
  • +
  • + Throws: Whatever T::operator=( T const& + ) or T::T(T const&) + throws. +
  • +
  • + Notes: If *this was initialized, T's assignment operator is used, + otherwise, its copy-constructor is used. +
  • +
  • + Exception Safety: In the event of + an exception, the initialization state of *this is unchanged and its value unspecified + as far as optional + is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + copy constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T x;
    +optional<T> def ;
    +optional<T> opt(x) ;
    +
    +T y;
    +def = y ;
    +assert ( *def == y ) ;
    +opt = y ;
    +assert ( *opt == y ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>& + optional<T&>::operator= ( T& rhs + ) ; +

+
    +
  • + Effect: (Re)binds the wrapped reference. +
  • +
  • + Postconditions: *this is initialized and it references + the same object referenced by rhs. +
  • +
  • + Notes: If *this was initialized, it is rebound + to the new object. See here + for details on this behavior. +
  • +
  • + Example: +
    int a = 1 ;
    +int b = 2 ;
    +T& ra = a ;
    +T& rb = b ;
    +optional<int&> def ;
    +optional<int&> opt(ra) ;
    +
    +def = rb ; // binds 'def' to 'b' through 'rb'
    +assert ( *def == b ) ;
    +*def = a ; // changes the value of 'b' to a copy of the value of 'a'
    +assert ( b == a ) ;
    +int c = 3;
    +int& rc = c ;
    +opt = rc ; // REBINDS to 'c' through 'rc'
    +c = 4 ;
    +assert ( *opt == 4 ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( T&& rhs + ) ; +

+
    +
  • + Effect: Moves the value rhs to an optional. +
  • +
  • + Postconditions: *this is initialized and its value is + moved from rhs. +
  • +
  • + Throws: Whatever T::operator=( T&& ) + or T::T(T &&) + throws. +
  • +
  • + Notes: If *this was initialized, T's move-assignment operator is used, + otherwise, its move-constructor is used. +
  • +
  • + Exception Safety: In the event of + an exception, the initialization state of *this is unchanged and its value unspecified + as far as optional + is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + move constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T x;
    +optional<T> def ;
    +optional<T> opt(x) ;
    +
    +T y1, y2, yR;
    +def = std::move(y1) ;
    +assert ( *def == yR ) ;
    +opt = std::move(y2) ;
    +assert ( *opt == yR ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>& + optional<T&>::operator= ( T&& rhs + ) = + delete; +

+
  • + Notes: This assignment operator is + deleted. +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( optional + const& + rhs ) + ; +

+
    +
  • + Requires: T + is CopyConstructible and CopyAssignable. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns *rhs + to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with *rhs +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this; +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the initialization state of *this and rhs + remains unchanged. If an exception is thrown during the call to T's copy constructor, no effect. + If an exception is thrown during the call to T's + copy assignment, the state of its contained value is as defined by + the exception safety guarantee of T's + copy assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +optional<T> def ;
    +
    +opt = def ;
    +assert ( !def ) ;
    +// previous value (copy of 'v') destroyed from within 'opt'.
    +
    +
  • +
+

+ space +

+

+ optional<T&> + & optional<T&>::operator= ( optional<T&> const& rhs + ) ; +

+
    +
  • + Effect: (Re)binds thee wrapped reference. +
  • +
  • + Postconditions: If *rhs is initialized, *this + is initialized and it references the same object referenced by *rhs; + otherwise, *this + is uninitialized (and references no object). +
  • +
  • + Notes: If *this was initialized and so is *rhs, + *this + is rebound to the new object. See here + for details on this behavior. +
  • +
  • + Example: +
    int a = 1 ;
    +int b = 2 ;
    +T& ra = a ;
    +T& rb = b ;
    +optional<int&> def ;
    +optional<int&> ora(ra) ;
    +optional<int&> orb(rb) ;
    +
    +def = orb ; // binds 'def' to 'b' through 'rb' wrapped within 'orb'
    +assert ( *def == b ) ;
    +*def = ora ; // changes the value of 'b' to a copy of the value of 'a'
    +assert ( b == a ) ;
    +int c = 3;
    +int& rc = c ;
    +optional<int&> orc(rc) ;
    +ora = orc ; // REBINDS ora to 'c' through 'rc'
    +c = 4 ;
    +assert ( *ora == 4 ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( optional&& rhs + ) noexcept(see below); +

+
    +
  • + Requires: T + is MoveConstructible + and MoveAssignable. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns std::move(*rhs) to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with std::move(*rhs) +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this; +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible<T>::value && + is_nothrow_move_assignable<T>::value. +
  • +
  • + Exception Safety: If any exception + is thrown, the initialization state of *this and rhs + remains unchanged. If an exception is thrown during the call to T's move constructor, the state of + *rhs + is determined by the exception safety guarantee of T's + move constructor. If an exception is thrown during the call to T's + move-assignment, the state of **this and *rhs is determined by the exception + safety guarantee of T's move assignment. +
  • +
  • + Example: +
    optional<T> opt(T(2)) ;
    +optional<T> def ;
    +
    +opt = def ;
    +assert ( def ) ;
    +assert ( opt ) ;
    +assert ( *opt == T(2) ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&> + & optional<T&>::operator= ( optional<T&>&& rhs + ) ; +

+
  • + Effect: Same as optional<T&>::operator= ( optional<T&> + const& + rhs ). +
+

+ space +

+

+ template<U> optional& + optional<T (not a ref)>::operator= ( optional<U> const& rhs + ) ; +

+
    +
  • +

    + Effect: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns *rhs + to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with *rhs +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this. +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the result of the expression bool(*this) remains unchanged. If an exception + is thrown during the call to T's + constructor, no effect. If an exception is thrown during the call to + T's assignment, the + state of its contained value is as defined by the exception safety + guarantee of T's copy + assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt0(v);
    +optional<U> opt1;
    +
    +opt1 = opt0 ;
    +assert ( *opt1 == static_cast<U>(v) ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> optional& + optional<T (not a ref)>::operator= ( optional<U>&& rhs + ) ; +

+
    +
  • +

    + Effect: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns std::move(*rhs) to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with std::move(*rhs) +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this. +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the result of the expression bool(*this) remains unchanged. If an exception + is thrown during the call to T's + constructor, no effect. If an exception is thrown during the call to + T's assignment, the + state of its contained value is as defined by the exception safety + guarantee of T's copy + assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt0(v);
    +optional<U> opt1;
    +
    +opt1 = std::move(opt0) ;
    +assert ( opt0 );
    +assert ( opt1 )
    +assert ( *opt1 == static_cast<U>(v) ) ;
    +
    +
  • +
+

+ space +

+

+ template<class... Args> + void optional<T + (not a ref)>::emplace( + Args...&& + args ); +

+
    +
  • + Requires: The compiler supports rvalue + references and variadic templates. +
  • +
  • + Effect: If *this is initialized calls *this = none. + Then initializes in-place the contained value as if direct-initializing + an object of type T + with std::forward<Args>(args).... +
  • +
  • + Postconditions: *this is initialized. +
  • +
  • + Throws: Whatever the selected T's constructor throws. +
  • +
  • + Exception Safety: If an exception + is thrown during the initialization of T, + *this + is uninitialized. +
  • +
  • + Notes: T + need not be MoveConstructible + or MoveAssignable. + On compilers that do not support variadic templates, the signature + falls back to two overloads:template<class + Arg> + void emplace(Arg&& arg) and void + emplace(). + On compilers that do not support rvalue references, the signature falls + back to three overloads: taking const + and non-const lvalue reference, + and third with empty function argument list. +
  • +
  • + Example: +
    T v;
    +optional<const T> opt;
    +opt.emplace(0);  // create in-place using ctor T(int)
    +opt.emplace();   // destroy previous and default-construct another T
    +opt.emplace(v);  // destroy and copy-construct in-place (no assignment called)
    +
    +
  • +
+

+ space +

+

+ template<InPlaceFactory> + optional<T>& + optional<T (not a ref)>::operator=( InPlaceFactory + const& + f ); +

+

+ template<TypedInPlaceFactory> + optional<T>& + optional<T (not a ref)>::operator=( TypedInPlaceFactory + const& + f ); +

+
    +
  • + Effect: Assigns an optional + with a value of T obtained + from the factory. +
  • +
  • + Postconditions: *this is initialized + and its value is directly given from the factory + f (i.e., the value + is not copied). +
  • +
  • + Throws: Whatever the T constructor called by the factory + throws. +
  • +
  • + Notes: See In-Place + Factories +
  • +
  • + Exception Safety: Exceptions can only + be thrown during the call to the T + constructor used by the factory; in that case, the optional + object will be reset to be uninitialized. +
  • +
+

+ space +

+

+ void optional<T + (not a ref)>::reset( T const& v ) ; +

+
  • + Deprecated: same as operator= + ( T + const& + v) + ; +
+

+ space +

+

+ void optional<T>::reset() noexcept + ; +

+
  • + Deprecated: Same as operator=( + none_t ); +
+

+ space +

+

+ T const& optional<T + (not a ref)>::get() const ; +

+

+ T& + optional<T (not a ref)>::get() ; +

+

+ inline T + const& + get ( + optional<T (not a ref)> const& ) ; +

+

+ inline T& get + ( optional<T + (not a ref)> + &) ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: A reference to the contained + value +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). +
  • +
+

+ space +

+

+ T const& optional<T&>::get() const ; +

+

+ T& + optional<T&>::get() ; +

+

+ inline T + const& + get ( + optional<T&> + const& + ) ; +

+

+ inline T& get + ( optional<T&> &) + ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: The + reference contained. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). +
  • +
+

+ space +

+

+ T const& optional<T + (not a ref)>::operator*() + const& + ; +

+

+ T& + optional<T (not a ref)>::operator*() &; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: A reference to the contained + value +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions + these two overloads are replaced with the classical two: a const and non-const + member functions. +
  • +
  • + Example: +
    T v ;
    +optional<T> opt ( v );
    +T const& u = *opt;
    +assert ( u == v ) ;
    +T w ;
    +*opt = w ;
    +assert ( *opt == w ) ;
    +
    +
  • +
+

+ space +

+

+ T&& + optional<T (not a ref)>::operator*() &&; +

+
    +
  • + Requires: *this contains a value. +
  • +
  • + Effects: Equivalent to return std::move(*val);. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions + this overload is not present. +
  • +
+

+ space +

+

+ T & + optional<T&>::operator*() + const& + ; +

+

+ T & + optional<T&>::operator*() + & ; +

+

+ T & + optional<T&>::operator*() + && ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: The + reference contained. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions + these three overloads are replaced with the classical two: a const and non-const + member functions. +
  • +
  • + Example: +
    T v ;
    +T& vref = v ;
    +optional<T&> opt ( vref );
    +T const& vref2 = *opt;
    +assert ( vref2 == v ) ;
    +++ v ;
    +assert ( *opt == v ) ;
    +
    +
  • +
+

+ space +

+

+ T const& optional<T>::value() const& ; +

+

+ T& + optional<T>::value() & ; +

+
    +
  • + Effects: Equivalent to return bool(*this) ? *val : throw bad_optional_access();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions these two overloads are replaced + with the classical two: a const + and non-const member functions. +
  • +
  • + Example: +
    T v ;
    +optional<T> o0, o1 ( v );
    +assert ( o1.value() == v );
    +
    +try {
    +  o0.value(); // throws
    +  assert ( false );
    +}
    +catch(bad_optional_access&) {
    +  assert ( true );
    +}
    +
    +
  • +
+

+ space +

+

+ T&& + optional<T>::value() && ; +

+
    +
  • + Effects: Equivalent to return bool(*this) ? std::move(*val) : throw bad_optional_access();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ template<class U> T optional<T>::value_or(U && + v) + const& + ; +

+
    +
  • + Effects: Equivalent to if (*this) return **this; else return + std::forward<U>(v);. +
  • +
  • + Remarks: If T + is not CopyConstructible or U && + is not convertible to T, + the program is ill-formed. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is replaced with the + const-qualified member + function. On compilers without rvalue reference support the type of + v becomes U const&. +
  • +
+

+ space +

+

+ template<class U> T optional<T>::value_or(U && + v) + && ; +

+
    +
  • + Effects: Equivalent to if (*this) return std::move(**this); else return std::forward<U>(v);. +
  • +
  • + Remarks: If T + is not MoveConstructible + or U && + is not convertible to T, + the program is ill-formed. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ template<class F> T optional<T>::value_or_eval(F f) const& ; +

+
    +
  • + Requires: T + is CopyConstructible and F models a Generator whose result type + is convertible to T. +
  • +
  • + Effects: if + (*this) return **this; else return f();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is replaced with the + const-qualified member + function. +
  • +
  • + Example: +
    int complain_and_0()
    +{
    +  clog << "no value returned, using default" << endl;
    +  return 0;
    +}
    +
    +optional<int> o1 = 1;
    +optional<int> oN = none;
    +
    +int i = o1.value_or_eval(complain_and_0); // fun not called
    +assert (i == 1);
    +
    +int j = oN.value_or_eval(complain_and_0); // fun called
    +assert (i == 0);
    +
    +
  • +
+

+ space +

+

+ template<class F> T optional<T>::value_or_eval(F f) && + ; +

+
    +
  • + Requires: T + is MoveConstructible + and F models a Generator + whose result type is convertible to T. +
  • +
  • + Effects: if + (*this) return std::move(**this); else return + f();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ T const& optional<T + (not a ref)>::get_value_or( + T const& default) const ; +

+

+ T& + optional<T (not a ref)>::get_value_or( T& default + ) ; +

+

+ inline T + const& + get_optional_value_or ( + optional<T (not a ref)> const& o, T const& default ) ; +

+

+ inline T& get_optional_value_or + ( optional<T + (not a ref)>& + o, + T& + default ) + ; +

+
    +
  • + Deprecated: Use value_or() instead. +
  • +
  • + Returns: A reference to the contained + value, if any, or default. +
  • +
  • + Throws: Nothing. +
  • +
  • + Example: +
    T v, z ;
    +optional<T> def;
    +T const& y = def.get_value_or(z);
    +assert ( y == z ) ;
    +
    +optional<T> opt ( v );
    +T const& u = get_optional_value_or(opt,z);
    +assert ( u == v ) ;
    +assert ( u != z ) ;
    +
    +
  • +
+

+ space +

+

+ T const* optional<T + (not a ref)>::get_ptr() + const ; +

+

+ T* + optional<T (not a ref)>::get_ptr() ; +

+

+ inline T + const* + get_pointer ( + optional<T (not a ref)> const& ) ; +

+

+ inline T* get_pointer + ( optional<T + (not a ref)> + &) ; +

+
    +
  • + Returns: If *this is initialized, a pointer to the + contained value; else 0 + (null). +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The contained value is permanently + stored within *this, + so you should not hold nor delete this pointer +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +optional<T> const copt(v);
    +T* p = opt.get_ptr() ;
    +T const* cp = copt.get_ptr();
    +assert ( p == get_pointer(opt) );
    +assert ( cp == get_pointer(copt) ) ;
    +
    +
  • +
+

+ space +

+

+ T const* optional<T + (not a ref)>::operator ->() + const ; +

+

+ T* + optional<T (not a ref)>::operator + ->() ; +

+
    +
  • + Requires: *this is initialized. +
  • +
  • + Returns: A pointer to the contained + value. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). +
  • +
  • + Example: +
    struct X { int mdata ; } ;
    +X x ;
    +optional<X> opt (x);
    +opt->mdata = 2 ;
    +
    +
  • +
+

+ space +

+

+ explicit optional<T>::operator + bool() + const noexcept + ; +

+
    +
  • + Returns: get_ptr() != 0. +
  • +
  • + Notes: On compilers that do not support + explicit conversion operators this falls back to safe-bool idiom. +
  • +
  • + Example: +
    optional<T> def ;
    +assert ( def == 0 );
    +optional<T> opt ( v ) ;
    +assert ( opt );
    +assert ( opt != 0 );
    +
    +
  • +
+

+ space +

+

+ bool optional<T>::operator!() noexcept + ; +

+
    +
  • + Returns: If *this is uninitialized, true; else false. +
  • +
  • + Notes: This operator is provided for + those compilers which can't use the unspecified-bool-type + operator in certain boolean contexts. +
  • +
  • + Example: +
    optional<T> opt ;
    +assert ( !opt );
    +*opt = some_T ;
    +
    +// Notice the "double-bang" idiom here.
    +assert ( !!opt ) ;
    +
    +
  • +
+

+ space +

+

+ bool optional<T>::is_initialized() const ; +

+
  • + Deprecated: Same as explicit operator + bool () + ; +
+

+ space +

+
+ + Free + functions +
+

+ space +

+

+ optional<T (not a ref)> make_optional( T const& v ) +

+
    +
  • + Returns: optional<T>(v) for the deduced + type T of v. +
  • +
  • + Example: +
    template<class T> void foo ( optional<T> const& opt ) ;
    +
    +foo ( make_optional(1+1) ) ; // Creates an optional<int>
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)> make_optional( bool condition, + T const& v ) +

+
    +
  • + Returns: optional<T>(condition,v) for the deduced + type T of v. +
  • +
  • + Example: +
    optional<double> calculate_foo()
    +{
    +  double val = compute_foo();
    +  return make_optional(is_not_nan_and_finite(val),val);
    +}
    +
    +optional<double> v = calculate_foo();
    +if ( !v )
    +  error("foo wasn't computed");
    +
    +
  • +
+

+ space +

+

+ bool operator + == ( + optional<T> const& x, optional<T> const& y ); +

+
    +
  • + Requires: T + shall meet requirements of EqualityComparable. +
  • +
  • + Returns: If both x + and y are initialized, + (*x + == *y). + If only x or y is initialized, false. + If both are uninitialized, true. +
  • +
  • + Notes: This definition guarantees + that optional<T> + not containing a value is compared unequal to any optional<T> containing any value, and equal + to any other optional<T> not containing a value. Pointers + have shallow relational operators while optional + has deep relational operators. Do not use operator== directly in generic code which expect + to be given either an optional<T> or a pointer; use equal_pointees() + instead +
  • +
  • + Example: +
    optional<T> oN, oN_;
    +optional<T> o1(T(1)), o1_(T(1));
    +optional<T> o2(T(2));
    +
    +assert ( oN == oN );  // Identity implies equality
    +assert ( o1 == o1 );  //
    +
    +assert ( oN == oN_ ); // Both uninitialized compare equal
    +
    +assert ( oN != o1 );  // Initialized unequal to initialized.
    +
    +assert ( o1 == o1_ ); // Both initialized compare as (*lhs == *rhs)
    +assert ( o1 != o2 );  //
    +
    +
  • +
+

+ space +

+

+ bool operator + < ( + optional<T> const& x, optional<T> const& y ); +

+
    +
  • + Requires: Expression *x < *y shall be well-formed and its result + shall be convertible to bool. +
  • +
  • + Returns: (!y) ? false : (!x) ? true : *x < + *y. +
  • +
  • + Notes: This definition guarantees + that optional<T> + not containing a value is ordered as less than any optional<T> containing any value, and equivalent + to any other optional<T> not containing a value. Pointers + have shallow relational operators while optional + has deep relational operators. Do not use operator< directly in generic code which + expect to be given either an optional<T> or a pointer; use less_pointees() + instead. T need not + be LessThanComparable. Only + single operator< + is required. Other relational operations are defined in terms of this + one. If T's operator< + satisfies the axioms of LessThanComparable (transitivity, + antisymmetry and irreflexivity), optional<T> is LessThanComparable. +
  • +
  • + Example: +
    optional<T> oN, oN_;
    +optional<T> o0(T(0));
    +optional<T> o1(T(1));
    +
    +assert ( !(oN < oN) );  // Identity implies equivalence
    +assert ( !(o1 < o1) );
    +
    +assert ( !(oN < oN_) ); // Two uninitialized are equivalent
    +assert ( !(oN_ < oN) );
    +
    +assert ( oN < o0 );     // Uninitialized is less than initialized
    +assert ( !(o0 < oN) );
    +
    +assert ( o1 < o2 ) ;    // Two initialized compare as (*lhs < *rhs)
    +assert ( !(o2 < o1) ) ;
    +assert ( !(o2 < o2) ) ;
    +
    +
  • +
+

+ space +

+

+ bool operator + != ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: !( + x == + y ); +
+

+ space +

+

+ bool operator + > ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: ( + y < + x ); +
+

+ space +

+

+ bool operator + <= ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: !( + y < + x ); +
+

+ space +

+

+ bool operator + >= ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: !( + x < + y ); +
+

+ space +

+

+ bool operator + == ( + optional<T> const& x, none_t ) + noexcept; +

+

+ bool operator + == ( + none_t, + optional<T> const& x ) noexcept; +

+
+

+ space +

+

+ bool operator + != ( + optional<T> const& x, none_t ) + noexcept; +

+

+ bool operator + != ( + none_t, + optional<T> const& x ) noexcept; +

+
  • + Returns: !( + x == + y ); +
+

+ space +

+

+ void swap + ( optional<T>& x, optional<T>& y + ) ; +

+
    +
  • + Requires: Lvalues of type T shall be swappable and T shall be MoveConstructible. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + calls swap(*(*this), *rhs) +

    +
    +

    + initializes the contained value of *this as if direct-initializing + an object of type T + with the expression std::move(*rhs), followed by rhs.val->T::~T(), + *this + contains a value and rhs + does not contain a value +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + initializes the contained value of rhs + as if direct-initializing an object of type T with the expression + std::move(*(*this)), + followed by val->T::~T(), *this does not contain a value + and rhs contains + a value +

    +
    +

    + no effect +

    +
    +
  • +
  • + Postconditions: The states of x and y + interchanged. +
  • +
  • + Throws: If both are initialized, whatever + swap(T&,T&) + throws. If only one is initialized, whatever T::T ( T&& ) + throws. +
  • +
  • + Example: +
    T x(12);
    +T y(21);
    +optional<T> def0 ;
    +optional<T> def1 ;
    +optional<T> optX(x);
    +optional<T> optY(y);
    +
    +boost::swap(def0,def1); // no-op
    +
    +boost::swap(def0,optX);
    +assert ( *def0 == x );
    +assert ( !optX );
    +
    +boost::swap(def0,optX); // Get back to original values
    +
    +boost::swap(optX,optY);
    +assert ( *optX == y );
    +assert ( *optY == x );
    +
    +
  • +
+

+ space +

+

+ void swap + ( optional<T&>& x, optional<T&>& y + ) noexcept + ; +

+
    +
  • + Postconditions: x + refers to what y referred + to before the swap (if anything). y + refers to whatever x + referred to before the swap. +
  • +
  • + Example: +
    T x(12);
    +T y(21);
    +
    +optional<T&> opt0;
    +optional<T&> optX (x);
    +optional<T&> optY (y);
    +
    +boost::swap(optX, optY);
    +assert (addressof(*optX) == addressof(y));
    +assert (addressof(*optY) == addressof(x));
    +
    +boost::swap(opt0, optX);
    +assert ( opt0 );
    +assert ( !optX );
    +assert (addressof(*opt0) == addressof(y));
    +
    + [endsect] +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____free_functions.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____free_functions.html new file mode 100644 index 00000000..b3c6401d --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____free_functions.html @@ -0,0 +1,447 @@ + + + +Detailed Semantics -- Free Functions + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ space +

+

+ optional<T> make_optional( + T const& v ) +

+
    +
  • + Returns: optional<T>(v) for the deduced + type T of v. +
  • +
  • + Example: +
    template<class T> void foo ( optional<T> const& opt ) ;
    +
    +foo ( make_optional(1+1) ) ; // Creates an optional<int>
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)> make_optional( bool condition, + T const& v ) +

+
    +
  • + Returns: optional<T>(condition,v) for the deduced + type T of v. +
  • +
  • + Example: +
    optional<double> calculate_foo()
    +{
    +  double val = compute_foo();
    +  return make_optional(is_not_nan_and_finite(val),val);
    +}
    +
    +optional<double> v = calculate_foo();
    +if ( !v )
    +  error("foo wasn't computed");
    +
    +
  • +
+

+ space +

+

+ bool operator + == ( + optional<T> const& x, optional<T> const& y ); +

+
    +
  • + Requires: T + shall meet requirements of EqualityComparable. +
  • +
  • + Returns: If both x + and y are initialized, + (*x + == *y). + If only x or y is initialized, false. + If both are uninitialized, true. +
  • +
  • + Notes: This definition guarantees + that optional<T> + not containing a value is compared unequal to any optional<T> containing any value, and equal + to any other optional<T> not containing a value. Pointers + have shallow relational operators while optional + has deep relational operators. Do not use operator== directly in generic code which expect + to be given either an optional<T> or a pointer; use equal_pointees() + instead +
  • +
  • + Example: +
    optional<T> oN, oN_;
    +optional<T> o1(T(1)), o1_(T(1));
    +optional<T> o2(T(2));
    +
    +assert ( oN == oN );  // Identity implies equality
    +assert ( o1 == o1 );  //
    +
    +assert ( oN == oN_ ); // Both uninitialized compare equal
    +
    +assert ( oN != o1 );  // Initialized unequal to initialized.
    +
    +assert ( o1 == o1_ ); // Both initialized compare as (*lhs == *rhs)
    +assert ( o1 != o2 );  //
    +
    +
  • +
+

+ space +

+

+ bool operator + < ( + optional<T> const& x, optional<T> const& y ); +

+
    +
  • + Requires: Expression *x < *y shall be well-formed and its result + shall be convertible to bool. +
  • +
  • + Returns: (!y) ? false : (!x) ? true : *x < + *y. +
  • +
  • + Notes: This definition guarantees + that optional<T> + not containing a value is ordered as less than any optional<T> containing any value, and equivalent + to any other optional<T> not containing a value. Pointers + have shallow relational operators while optional + has deep relational operators. Do not use operator< directly in generic code which + expect to be given either an optional<T> or a pointer; use less_pointees() + instead. T need not + be LessThanComparable. Only + single operator< + is required. Other relational operations are defined in terms of this + one. If T's operator< + satisfies the axioms of LessThanComparable (transitivity, + antisymmetry and irreflexivity), optional<T> is LessThanComparable. +
  • +
  • + Example: +
    optional<T> oN, oN_;
    +optional<T> o0(T(0));
    +optional<T> o1(T(1));
    +
    +assert ( !(oN < oN) );  // Identity implies equivalence
    +assert ( !(o1 < o1) );
    +
    +assert ( !(oN < oN_) ); // Two uninitialized are equivalent
    +assert ( !(oN_ < oN) );
    +
    +assert ( oN < o0 );     // Uninitialized is less than initialized
    +assert ( !(o0 < oN) );
    +
    +assert ( o1 < o2 ) ;    // Two initialized compare as (*lhs < *rhs)
    +assert ( !(o2 < o1) ) ;
    +assert ( !(o2 < o2) ) ;
    +
    +
  • +
+

+ space +

+

+ bool operator + != ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: !( + x == + y ); +
+

+ space +

+

+ bool operator + > ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: ( + y < + x ); +
+

+ space +

+

+ bool operator + <= ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: !( + y < + x ); +
+

+ space +

+

+ bool operator + >= ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: !( + x < + y ); +
+

+ space +

+

+ bool operator + == ( + optional<T> const& x, none_t ) + noexcept; +

+

+ bool operator + == ( + none_t, + optional<T> const& x ) noexcept; +

+
+

+ space +

+

+ bool operator + != ( + optional<T> const& x, none_t ) + noexcept; +

+

+ bool operator + != ( + none_t, + optional<T> const& x ) noexcept; +

+
  • + Returns: !( + x == + y ); +
+

+ space +

+

+ void swap + ( optional<T>& x, optional<T>& y + ) ; +

+
    +
  • + Requires: Lvalues of type T shall be swappable and T shall be MoveConstructible. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + calls swap(*(*this), *rhs) +

    +
    +

    + initializes the contained value of *this as if direct-initializing + an object of type T + with the expression std::move(*rhs), followed by rhs.val->T::~T(), + *this + contains a value and rhs + does not contain a value +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + initializes the contained value of rhs + as if direct-initializing an object of type T with the expression + std::move(*(*this)), + followed by val->T::~T(), *this does not contain a value + and rhs contains + a value +

    +
    +

    + no effect +

    +
    +
  • +
  • + Postconditions: The states of x and y + interchanged. +
  • +
  • + Throws: If both are initialized, whatever + swap(T&,T&) + throws. If only one is initialized, whatever T::T ( T&& ) + throws. +
  • +
  • + Example: +
    T x(12);
    +T y(21);
    +optional<T> def0 ;
    +optional<T> def1 ;
    +optional<T> optX(x);
    +optional<T> optY(y);
    +
    +boost::swap(def0,def1); // no-op
    +
    +boost::swap(def0,optX);
    +assert ( *def0 == x );
    +assert ( !optX );
    +
    +boost::swap(def0,optX); // Get back to original values
    +
    +boost::swap(optX,optY);
    +assert ( *optX == y );
    +assert ( *optY == x );
    +
    +
  • +
+

+ space +

+

+ void swap + ( optional<T&>& x, optional<T&>& y + ) noexcept + ; +

+
    +
  • + Postconditions: x + refers to what y referred + to before the swap (if anything). y + refers to whatever x + referred to before the swap. +
  • +
  • + Example: +
    T x(12);
    +T y(21);
    +
    +optional<T&> opt0;
    +optional<T&> optX (x);
    +optional<T&> optY (y);
    +
    +boost::swap(optX, optY);
    +assert (addressof(*optX) == addressof(y));
    +assert (addressof(*optY) == addressof(x));
    +
    +boost::swap(opt0, optX);
    +assert ( opt0 );
    +assert ( !optX );
    +assert (addressof(*opt0) == addressof(y));
    +
    + [endsect] +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____optional_references.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____optional_references.html new file mode 100644 index 00000000..7eedfaba --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____optional_references.html @@ -0,0 +1,57 @@ + + + +Detailed Semantics -- Optional References + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ space +

+

+ optional<&>::optional() + noexcept; +

+

+ optional<&>::optional(none_t) noexcept; +

+
  • + Postconditions: *this refers to nothing. +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____optional_values.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____optional_values.html new file mode 100644 index 00000000..17eeb386 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics____optional_values.html @@ -0,0 +1,1983 @@ + + + +Detailed Semantics -- Optional Values + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ + + + + +
[Note]Note

+ The following section contains various assert() which are used only to show the postconditions + as sample code. It is not implied that the type T + must support each particular expression but that if the expression is + supported, the implied condition holds. +

+

+ space +

+

+ optional<T>::optional() + noexcept; +

+
    +
  • + Effect: Default-Constructs an optional. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
  • + Notes: T's default constructor is not called. +
  • +
  • + Example: +
    optional<T> def ;
    +assert ( !def ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( + none_t ) + noexcept; +

+
    +
  • + Effect: Constructs an optional uninitialized. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
  • + Notes: T's + default constructor is not called. + The expression boost::none + denotes an instance of boost::none_t + that can be used as the parameter. +
  • +
  • + Example: +
    #include <boost/none.hpp>
    +optional<T> n(none) ;
    +assert ( !n ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)>::optional( T const& v ) +

+
    +
  • + Requires: is_copy_constructible<T>::value + is true. +
  • +
  • + Effect: Directly-Constructs an optional. +
  • +
  • + Postconditions: *this is initialized + and its value is a copy of v. +
  • +
  • + Throws: Whatever T::T( T const& + ) throws. +
  • +
  • + Notes: T::T( T const& + ) is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +assert ( *opt == v ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( + T& + ref ) +

+
    +
  • + Effect: Directly-Constructs an optional. +
  • +
  • + Postconditions: *this is initialized + and its value is an instance of an internal type wrapping the reference + ref. +
  • +
  • + Throws: Nothing. +
  • +
  • + Example: +
    T v;
    +T& vref = v ;
    +optional<T&> opt(vref);
    +assert ( *opt == v ) ;
    +++ v ; // mutate referee
    +assert (*opt == v);
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)>::optional( T&& v + ) +

+
    +
  • + Requires: is_move_constructible<T>::value + is true. +
  • +
  • + Effect: Directly-Move-Constructs an + optional. +
  • +
  • + Postconditions: *this is initialized + and its value is move-constructed from v. +
  • +
  • + Throws: Whatever T::T( T&& ) + throws. +
  • +
  • + Notes: T::T( T&& ) + is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T&& ); + in that case, the state of v + is determined by exception safety guarantees for T::T(T&&). +
  • +
  • + Example: +
    T v1, v2;
    +optional<T> opt(std::move(v1));
    +assert ( *opt == v2 ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( + T&& + ref ) + = delete +

+
  • + Notes: This constructor is deleted +
+

+ space +

+

+ optional<T (not a ref)>::optional( bool condition, + T const& v ) ; +

+

+ optional<T&> + ::optional( bool condition, + T& + v ) + ; +

+
  • + If condition is true, same as: +
+

+ optional<T (not a ref)>::optional( T const& v ) +

+

+ optional<T&> + ::optional( T& v ) +

+
  • + otherwise, same as: +
+

+ optional<T (not a ref)>::optional() +

+

+ optional<T&> + ::optional() +

+

+ space +

+

+ optional<T (not a ref)>::optional( optional + const& + rhs ); +

+
    +
  • + Requires: is_copy_constructible<T>::value + is true. +
  • +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs is initialized, + *this + is initialized and its value is a copy of the + value of rhs; else + *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( T const& + ) throws. +
  • +
  • + Notes: If rhs is initialized, T::T(T const& ) + is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    optional<T> uninit ;
    +assert (!uninit);
    +
    +optional<T> uinit2 ( uninit ) ;
    +assert ( uninit2 == uninit );
    +
    +optional<T> init( T(2) );
    +assert ( *init == T(2) ) ;
    +
    +optional<T> init2 ( init ) ;
    +assert ( init2 == init ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( + optional const& rhs + ); +

+
    +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is another reference to the same object + referenced by *rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: If rhs + is initialized, both *this and *rhs will refer to the same object + (they alias). +
  • +
  • + Example: +
    optional<T&> uninit ;
    +assert (!uninit);
    +
    +optional<T&> uinit2 ( uninit ) ;
    +assert ( uninit2 == uninit );
    +
    +T v = 2 ; T& ref = v ;
    +optional<T> init(ref);
    +assert ( *init == v ) ;
    +
    +optional<T> init2 ( init ) ;
    +assert ( *init2 == v ) ;
    +
    +v = 3 ;
    +
    +assert ( *init  == 3 ) ;
    +assert ( *init2 == 3 ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T (not a ref)>::optional( optional&& rhs + ) noexcept(see below); +

+
    +
  • + Requires: is_move_constructible<T>::value + is true. +
  • +
  • + Effect: Move-constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move constructed from rhs; else *this is uninitialized. +
  • +
  • + Throws: Whatever T::T( T&& ) + throws. +
  • +
  • + Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible<T>::value. +
  • +
  • + Notes: If rhs + is initialized, T::T( T && + ) is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T&& ); + in that case, rhs remains + initialized and the value of *rhs is determined by exception safety + of T::T(T&&). +
  • +
  • + Example: +
    optional<std::unique_ptr<T>> uninit ;
    +assert (!uninit);
    +
    +optional<std::unique_ptr<T>> uinit2 ( std::move(uninit) ) ;
    +assert ( uninit2 == uninit );
    +
    +optional<std::unique_ptr<T>> init( std::unique_ptr<T>(new T(2)) );
    +assert ( **init == T(2) ) ;
    +
    +optional<std::unique_ptr<T>> init2 ( std::move(init) ) ;
    +assert ( init );
    +assert ( *init == nullptr );
    +assert ( init2 );
    +assert ( **init2 == T(2) ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>::optional( + optional && + rhs ); +

+
    +
  • + Effect: Move-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is another reference to the same object + referenced by *rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: If rhs + is initialized, both *this and *rhs will refer to the same object + (they alias). +
  • +
  • + Example: +
    optional<std::unique_ptr<T>&> uninit ;
    +assert (!uninit);
    +
    +optional<std::unique_ptr<T>&> uinit2 ( std::move(uninit) ) ;
    +assert ( uninit2 == uninit );
    +
    +std::unique_ptr<T> v(new T(2)) ;
    +optional<std::unique_ptr<T>&> init(v);
    +assert ( *init == v ) ;
    +
    +optional<std::unique_ptr<T>&> init2 ( std::move(init) ) ;
    +assert ( *init2 == v ) ;
    +
    +*v = 3 ;
    +
    +assert ( **init  == 3 ) ;
    +assert ( **init2 == 3 ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> explicit optional<T + (not a ref)>::optional( + optional<U> const& rhs ); +

+
    +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is a copy of the + value of rhs converted to type T; + else *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( U const& + ) throws. +
  • +
  • + Notes: T::T( U const& + ) is called if rhs is initialized, which requires + a valid conversion from U + to T. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( U const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    optional<double> x(123.4);
    +assert ( *x == 123.4 ) ;
    +
    +optional<int> y(x) ;
    +assert( *y == 123 ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> explicit optional<T + (not a ref)>::optional( + optional<U>&& + rhs ); +

+
    +
  • + Effect: Move-constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move-constructed from *rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( U&& ) + throws. +
  • +
  • + Notes: T::T( U&& ) + is called if rhs is + initialized, which requires a valid conversion from U + to T. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( U&& ); + in that case, rhs remains + initialized and the value of *rhs is determined by exception safety + guarantee of T::T( U&& + ). +
  • +
  • + Example: +
    optional<double> x(123.4);
    +assert ( *x == 123.4 ) ;
    +
    +optional<int> y(std::move(x)) ;
    +assert( *y == 123 ) ;
    +
    +
  • +
+

+ space +

+

+ template<InPlaceFactory> + explicit optional<T + (not a ref)>::optional( + InPlaceFactory const& f ); +

+

+ template<TypedInPlaceFactory> + explicit optional<T + (not a ref)>::optional( + TypedInPlaceFactory const& f ); +

+
    +
  • + Effect: Constructs an optional with a value of T obtained from the factory. +
  • +
  • + Postconditions: *this is initialized + and its value is directly given from the factory + f (i.e., the value + is not copied). +
  • +
  • + Throws: Whatever the T constructor called by the factory + throws. +
  • +
  • + Notes: See In-Place + Factories +
  • +
  • + Exception Safety: Exceptions can only + be thrown during the call to the T + constructor used by the factory; in that case, this constructor has + no effect. +
  • +
  • + Example: +
    class C { C ( char, double, std::string ) ; } ;
    +
    +C v('A',123.4,"hello");
    +
    +optional<C> x( in_place   ('A', 123.4, "hello") ); // InPlaceFactory used
    +optional<C> y( in_place<C>('A', 123.4, "hello") ); // TypedInPlaceFactory used
    +
    +assert ( *x == v ) ;
    +assert ( *y == v ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( none_t + ) noexcept; +

+
    +
  • + Effect: If *this is initialized destroys its contained + value. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( T + const& + rhs ) + ; +

+
    +
  • + Effect: Assigns the value rhs to an optional. +
  • +
  • + Postconditions: *this is initialized and its value is + a copy of rhs. +
  • +
  • + Throws: Whatever T::operator=( T const& + ) or T::T(T const&) + throws. +
  • +
  • + Notes: If *this was initialized, T's assignment operator is used, + otherwise, its copy-constructor is used. +
  • +
  • + Exception Safety: In the event of + an exception, the initialization state of *this is unchanged and its value unspecified + as far as optional + is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + copy constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T x;
    +optional<T> def ;
    +optional<T> opt(x) ;
    +
    +T y;
    +def = y ;
    +assert ( *def == y ) ;
    +opt = y ;
    +assert ( *opt == y ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>& + optional<T&>::operator= ( T& rhs + ) ; +

+
    +
  • + Effect: (Re)binds the wrapped reference. +
  • +
  • + Postconditions: *this is initialized and it references + the same object referenced by rhs. +
  • +
  • + Notes: If *this was initialized, it is rebound + to the new object. See here + for details on this behavior. +
  • +
  • + Example: +
    int a = 1 ;
    +int b = 2 ;
    +T& ra = a ;
    +T& rb = b ;
    +optional<int&> def ;
    +optional<int&> opt(ra) ;
    +
    +def = rb ; // binds 'def' to 'b' through 'rb'
    +assert ( *def == b ) ;
    +*def = a ; // changes the value of 'b' to a copy of the value of 'a'
    +assert ( b == a ) ;
    +int c = 3;
    +int& rc = c ;
    +opt = rc ; // REBINDS to 'c' through 'rc'
    +c = 4 ;
    +assert ( *opt == 4 ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( T&& rhs + ) ; +

+
    +
  • + Effect: Moves the value rhs to an optional. +
  • +
  • + Postconditions: *this is initialized and its value is + moved from rhs. +
  • +
  • + Throws: Whatever T::operator=( T&& ) + or T::T(T &&) + throws. +
  • +
  • + Notes: If *this was initialized, T's move-assignment operator is used, + otherwise, its move-constructor is used. +
  • +
  • + Exception Safety: In the event of + an exception, the initialization state of *this is unchanged and its value unspecified + as far as optional + is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + move constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T x;
    +optional<T> def ;
    +optional<T> opt(x) ;
    +
    +T y1, y2, yR;
    +def = std::move(y1) ;
    +assert ( *def == yR ) ;
    +opt = std::move(y2) ;
    +assert ( *opt == yR ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&>& + optional<T&>::operator= ( T&& rhs + ) = + delete; +

+
  • + Notes: This assignment operator is + deleted. +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( optional + const& + rhs ) + ; +

+
    +
  • + Requires: T + is CopyConstructible and CopyAssignable. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns *rhs + to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with *rhs +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this; +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the initialization state of *this and rhs + remains unchanged. If an exception is thrown during the call to T's copy constructor, no effect. + If an exception is thrown during the call to T's + copy assignment, the state of its contained value is as defined by + the exception safety guarantee of T's + copy assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +optional<T> def ;
    +
    +opt = def ;
    +assert ( !def ) ;
    +// previous value (copy of 'v') destroyed from within 'opt'.
    +
    +
  • +
+

+ space +

+

+ optional<T&> + & optional<T&>::operator= ( optional<T&> const& rhs + ) ; +

+
    +
  • + Effect: (Re)binds thee wrapped reference. +
  • +
  • + Postconditions: If *rhs is initialized, *this + is initialized and it references the same object referenced by *rhs; + otherwise, *this + is uninitialized (and references no object). +
  • +
  • + Notes: If *this was initialized and so is *rhs, + *this + is rebound to the new object. See here + for details on this behavior. +
  • +
  • + Example: +
    int a = 1 ;
    +int b = 2 ;
    +T& ra = a ;
    +T& rb = b ;
    +optional<int&> def ;
    +optional<int&> ora(ra) ;
    +optional<int&> orb(rb) ;
    +
    +def = orb ; // binds 'def' to 'b' through 'rb' wrapped within 'orb'
    +assert ( *def == b ) ;
    +*def = ora ; // changes the value of 'b' to a copy of the value of 'a'
    +assert ( b == a ) ;
    +int c = 3;
    +int& rc = c ;
    +optional<int&> orc(rc) ;
    +ora = orc ; // REBINDS ora to 'c' through 'rc'
    +c = 4 ;
    +assert ( *ora == 4 ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T (not a ref)>::operator= ( optional&& rhs + ) noexcept(see below); +

+
    +
  • + Requires: T + is MoveConstructible + and MoveAssignable. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns std::move(*rhs) to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with std::move(*rhs) +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this; +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible<T>::value && + is_nothrow_move_assignable<T>::value. +
  • +
  • + Exception Safety: If any exception + is thrown, the initialization state of *this and rhs + remains unchanged. If an exception is thrown during the call to T's move constructor, the state of + *rhs + is determined by the exception safety guarantee of T's + move constructor. If an exception is thrown during the call to T's + move-assignment, the state of **this and *rhs is determined by the exception + safety guarantee of T's move assignment. +
  • +
  • + Example: +
    optional<T> opt(T(2)) ;
    +optional<T> def ;
    +
    +opt = def ;
    +assert ( def ) ;
    +assert ( opt ) ;
    +assert ( *opt == T(2) ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T&> + & optional<T&>::operator= ( optional<T&>&& rhs + ) ; +

+
  • + Effect: Same as optional<T&>::operator= ( optional<T&> + const& + rhs ). +
+

+ space +

+

+ template<U> optional& + optional<T (not a ref)>::operator= ( optional<U> const& rhs + ) ; +

+
    +
  • +

    + Effect: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns *rhs + to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with *rhs +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this. +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the result of the expression bool(*this) remains unchanged. If an exception + is thrown during the call to T's + constructor, no effect. If an exception is thrown during the call to + T's assignment, the + state of its contained value is as defined by the exception safety + guarantee of T's copy + assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt0(v);
    +optional<U> opt1;
    +
    +opt1 = opt0 ;
    +assert ( *opt1 == static_cast<U>(v) ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> optional& + optional<T (not a ref)>::operator= ( optional<U>&& rhs + ) ; +

+
    +
  • +

    + Effect: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns std::move(*rhs) to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with std::move(*rhs) +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this. +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the result of the expression bool(*this) remains unchanged. If an exception + is thrown during the call to T's + constructor, no effect. If an exception is thrown during the call to + T's assignment, the + state of its contained value is as defined by the exception safety + guarantee of T's copy + assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt0(v);
    +optional<U> opt1;
    +
    +opt1 = std::move(opt0) ;
    +assert ( opt0 );
    +assert ( opt1 )
    +assert ( *opt1 == static_cast<U>(v) ) ;
    +
    +
  • +
+

+ space +

+

+ template<class... Args> + void optional<T + (not a ref)>::emplace( + Args...&& + args ); +

+
    +
  • + Requires: The compiler supports rvalue + references and variadic templates. +
  • +
  • + Effect: If *this is initialized calls *this = none. + Then initializes in-place the contained value as if direct-initializing + an object of type T + with std::forward<Args>(args).... +
  • +
  • + Postconditions: *this is initialized. +
  • +
  • + Throws: Whatever the selected T's constructor throws. +
  • +
  • + Exception Safety: If an exception + is thrown during the initialization of T, + *this + is uninitialized. +
  • +
  • + Notes: T + need not be MoveConstructible + or MoveAssignable. + On compilers that do not support variadic templates, the signature + falls back to two overloads:template<class + Arg> + void emplace(Arg&& arg) and void + emplace(). + On compilers that do not support rvalue references, the signature falls + back to three overloads: taking const + and non-const lvalue reference, + and third with empty function argument list. +
  • +
  • + Example: +
    T v;
    +optional<const T> opt;
    +opt.emplace(0);  // create in-place using ctor T(int)
    +opt.emplace();   // destroy previous and default-construct another T
    +opt.emplace(v);  // destroy and copy-construct in-place (no assignment called)
    +
    +
  • +
+

+ space +

+

+ template<InPlaceFactory> + optional<T>& + optional<T (not a ref)>::operator=( InPlaceFactory + const& + f ); +

+

+ template<TypedInPlaceFactory> + optional<T>& + optional<T (not a ref)>::operator=( TypedInPlaceFactory + const& + f ); +

+
    +
  • + Effect: Assigns an optional + with a value of T obtained + from the factory. +
  • +
  • + Postconditions: *this is initialized + and its value is directly given from the factory + f (i.e., the value + is not copied). +
  • +
  • + Throws: Whatever the T constructor called by the factory + throws. +
  • +
  • + Notes: See In-Place + Factories +
  • +
  • + Exception Safety: Exceptions can only + be thrown during the call to the T + constructor used by the factory; in that case, the optional + object will be reset to be uninitialized. +
  • +
+

+ space +

+

+ void optional<T + (not a ref)>::reset( T const& v ) ; +

+
  • + Deprecated: same as operator= + ( T + const& + v) + ; +
+

+ space +

+

+ void optional<T>::reset() noexcept + ; +

+
  • + Deprecated: Same as operator=( + none_t ); +
+

+ space +

+

+ T const& optional<T + (not a ref)>::get() const ; +

+

+ T& + optional<T (not a ref)>::get() ; +

+

+ inline T + const& + get ( + optional<T (not a ref)> const& ) ; +

+

+ inline T& get + ( optional<T + (not a ref)> + &) ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: A reference to the contained + value +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). +
  • +
+

+ space +

+

+ T const& optional<T&>::get() const ; +

+

+ T& + optional<T&>::get() ; +

+

+ inline T + const& + get ( + optional<T&> + const& + ) ; +

+

+ inline T& get + ( optional<T&> &) + ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: The + reference contained. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). +
  • +
+

+ space +

+

+ T const& optional<T + (not a ref)>::operator*() + const& + ; +

+

+ T& + optional<T (not a ref)>::operator*() &; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: A reference to the contained + value +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions + these two overloads are replaced with the classical two: a const and non-const + member functions. +
  • +
  • + Example: +
    T v ;
    +optional<T> opt ( v );
    +T const& u = *opt;
    +assert ( u == v ) ;
    +T w ;
    +*opt = w ;
    +assert ( *opt == w ) ;
    +
    +
  • +
+

+ space +

+

+ T&& + optional<T (not a ref)>::operator*() &&; +

+
    +
  • + Requires: *this contains a value. +
  • +
  • + Effects: Equivalent to return std::move(*val);. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions + this overload is not present. +
  • +
+

+ space +

+

+ T & + optional<T&>::operator*() + const& + ; +

+

+ T & + optional<T&>::operator*() + & ; +

+

+ T & + optional<T&>::operator*() + && ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: The + reference contained. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions + these three overloads are replaced with the classical two: a const and non-const + member functions. +
  • +
  • + Example: +
    T v ;
    +T& vref = v ;
    +optional<T&> opt ( vref );
    +T const& vref2 = *opt;
    +assert ( vref2 == v ) ;
    +++ v ;
    +assert ( *opt == v ) ;
    +
    +
  • +
+

+ space +

+

+ T const& optional<T>::value() const& ; +

+

+ T& + optional<T>::value() & ; +

+
    +
  • + Effects: Equivalent to return bool(*this) ? *val : throw bad_optional_access();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions these two overloads are replaced + with the classical two: a const + and non-const member functions. +
  • +
  • + Example: +
    T v ;
    +optional<T> o0, o1 ( v );
    +assert ( o1.value() == v );
    +
    +try {
    +  o0.value(); // throws
    +  assert ( false );
    +}
    +catch(bad_optional_access&) {
    +  assert ( true );
    +}
    +
    +
  • +
+

+ space +

+

+ T&& + optional<T>::value() && ; +

+
    +
  • + Effects: Equivalent to return bool(*this) ? std::move(*val) : throw bad_optional_access();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ template<class U> T optional<T>::value_or(U && + v) + const& + ; +

+
    +
  • + Effects: Equivalent to if (*this) return **this; else return + std::forward<U>(v);. +
  • +
  • + Remarks: If T + is not CopyConstructible or U && + is not convertible to T, + the program is ill-formed. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is replaced with the + const-qualified member + function. On compilers without rvalue reference support the type of + v becomes U const&. +
  • +
+

+ space +

+

+ template<class U> T optional<T>::value_or(U && + v) + && ; +

+
    +
  • + Effects: Equivalent to if (*this) return std::move(**this); else return std::forward<U>(v);. +
  • +
  • + Remarks: If T + is not MoveConstructible + or U && + is not convertible to T, + the program is ill-formed. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ template<class F> T optional<T>::value_or_eval(F f) const& ; +

+
    +
  • + Requires: T + is CopyConstructible and F models a Generator whose result type + is convertible to T. +
  • +
  • + Effects: if + (*this) return **this; else return f();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is replaced with the + const-qualified member + function. +
  • +
  • + Example: +
    int complain_and_0()
    +{
    +  clog << "no value returned, using default" << endl;
    +  return 0;
    +}
    +
    +optional<int> o1 = 1;
    +optional<int> oN = none;
    +
    +int i = o1.value_or_eval(complain_and_0); // fun not called
    +assert (i == 1);
    +
    +int j = oN.value_or_eval(complain_and_0); // fun called
    +assert (i == 0);
    +
    +
  • +
+

+ space +

+

+ template<class F> T optional<T>::value_or_eval(F f) && + ; +

+
    +
  • + Requires: T + is MoveConstructible + and F models a Generator + whose result type is convertible to T. +
  • +
  • + Effects: if + (*this) return std::move(**this); else return + f();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ T const& optional<T + (not a ref)>::get_value_or( + T const& default) const ; +

+

+ T& + optional<T (not a ref)>::get_value_or( T& default + ) ; +

+

+ inline T + const& + get_optional_value_or ( + optional<T (not a ref)> const& o, T const& default ) ; +

+

+ inline T& get_optional_value_or + ( optional<T + (not a ref)>& + o, + T& + default ) + ; +

+
    +
  • + Deprecated: Use value_or() instead. +
  • +
  • + Returns: A reference to the contained + value, if any, or default. +
  • +
  • + Throws: Nothing. +
  • +
  • + Example: +
    T v, z ;
    +optional<T> def;
    +T const& y = def.get_value_or(z);
    +assert ( y == z ) ;
    +
    +optional<T> opt ( v );
    +T const& u = get_optional_value_or(opt,z);
    +assert ( u == v ) ;
    +assert ( u != z ) ;
    +
    +
  • +
+

+ space +

+

+ T const* optional<T + (not a ref)>::get_ptr() + const ; +

+

+ T* + optional<T (not a ref)>::get_ptr() ; +

+

+ inline T + const* + get_pointer ( + optional<T (not a ref)> const& ) ; +

+

+ inline T* get_pointer + ( optional<T + (not a ref)> + &) ; +

+
    +
  • + Returns: If *this is initialized, a pointer to the + contained value; else 0 + (null). +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The contained value is permanently + stored within *this, + so you should not hold nor delete this pointer +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +optional<T> const copt(v);
    +T* p = opt.get_ptr() ;
    +T const* cp = copt.get_ptr();
    +assert ( p == get_pointer(opt) );
    +assert ( cp == get_pointer(copt) ) ;
    +
    +
  • +
+

+ space +

+

+ T const* optional<T + (not a ref)>::operator ->() + const ; +

+

+ T* + optional<T (not a ref)>::operator + ->() ; +

+
    +
  • + Requires: *this is initialized. +
  • +
  • + Returns: A pointer to the contained + value. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). +
  • +
  • + Example: +
    struct X { int mdata ; } ;
    +X x ;
    +optional<X> opt (x);
    +opt->mdata = 2 ;
    +
    +
  • +
+

+ space +

+

+ explicit optional<T>::operator + bool() + const noexcept + ; +

+
    +
  • + Returns: get_ptr() != 0. +
  • +
  • + Notes: On compilers that do not support + explicit conversion operators this falls back to safe-bool idiom. +
  • +
  • + Example: +
    optional<T> def ;
    +assert ( def == 0 );
    +optional<T> opt ( v ) ;
    +assert ( opt );
    +assert ( opt != 0 );
    +
    +
  • +
+

+ space +

+

+ bool optional<T>::operator!() noexcept + ; +

+
    +
  • + Returns: If *this is uninitialized, true; else false. +
  • +
  • + Notes: This operator is provided for + those compilers which can't use the unspecified-bool-type + operator in certain boolean contexts. +
  • +
  • + Example: +
    optional<T> opt ;
    +assert ( !opt );
    +*opt = some_T ;
    +
    +// Notice the "double-bang" idiom here.
    +assert ( !!opt ) ;
    +
    +
  • +
+

+ space +

+

+ bool optional<T>::is_initialized() const ; +

+
  • + Deprecated: Same as explicit operator + bool () + ; +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___free_functions.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___free_functions.html new file mode 100644 index 00000000..776cffbb --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___free_functions.html @@ -0,0 +1,521 @@ + + + +Detailed Semantics - Free Functions + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ space +

+

+ optional<T> make_optional( + T const& v ) +

+
    +
  • + Returns: optional<T>(v) for the deduced + type T of v. +
  • +
  • + Example: +
    template<class T> void foo ( optional<T> const& opt ) ;
    +
    +foo ( make_optional(1+1) ) ; // Creates an optional<int>
    +
    +
  • +
+

+ space +

+

+ optional<std::decay_t<T>> + make_optional( + T && + v ) +

+
  • + Returns: optional<std::decay_t<T>>(std::move(v)) for the deduced + type T of v. +
+

+ space +

+

+ optional<T> make_optional( + bool condition, T const& v ) +

+
    +
  • + Returns: optional<T>(condition, v) for the deduced + type T of v. +
  • +
  • + Example: +
    optional<double> calculate_foo()
    +{
    +  double val = compute_foo();
    +  return make_optional(is_not_nan_and_finite(val),val);
    +}
    +
    +optional<double> v = calculate_foo();
    +if ( !v )
    +  error("foo wasn't computed");
    +
    +
  • +
+

+ space +

+

+ optional<std::decay_t<T>> + make_optional( + bool condition, T && v + ) +

+
  • + Returns: optional<std::decay_t<T>>(condition, std::move(v)) for the deduced + type T of v. +
+

+ space +

+

+ bool operator + == ( + optional<T> const& x, optional<T> const& y ); +

+
    +
  • + Requires: T + shall meet requirements of EqualityComparable. +
  • +
  • + Returns: If both x + and y are initialized, + (*x + == *y). + If only x or y is initialized, false. + If both are uninitialized, true. +
  • +
  • + Notes: This definition guarantees + that optional<T> + not containing a value is compared unequal to any optional<T> containing any value, and equal + to any other optional<T> not containing a value. Pointers + have shallow relational operators while optional + has deep relational operators. Do not use operator== directly in generic code which expect + to be given either an optional<T> or a pointer; use equal_pointees() + instead +
  • +
  • + Example: +
    optional<T> oN, oN_;
    +optional<T> o1(T(1)), o1_(T(1));
    +optional<T> o2(T(2));
    +
    +assert ( oN == oN );  // Identity implies equality
    +assert ( o1 == o1 );  //
    +
    +assert ( oN == oN_ ); // Both uninitialized compare equal
    +
    +assert ( oN != o1 );  // Initialized unequal to initialized.
    +
    +assert ( o1 == o1_ ); // Both initialized compare as (*lhs == *rhs)
    +assert ( o1 != o2 );  //
    +
    +
  • +
+

+ space +

+

+ bool operator + < ( + optional<T> const& x, optional<T> const& y ); +

+
    +
  • + Requires: Expression *x < *y shall be well-formed and its result + shall be convertible to bool. +
  • +
  • + Returns: (!y) ? false : (!x) ? true : *x < + *y. +
  • +
  • + Notes: This definition guarantees + that optional<T> + not containing a value is ordered as less than any optional<T> containing any value, and equivalent + to any other optional<T> not containing a value. Pointers + have shallow relational operators while optional + has deep relational operators. Do not use operator< directly in generic code which + expect to be given either an optional<T> or a pointer; use less_pointees() + instead. T need not + be LessThanComparable. Only + single operator< + is required. Other relational operations are defined in terms of this + one. If T's operator< + satisfies the axioms of LessThanComparable (transitivity, + antisymmetry and irreflexivity), optional<T> is LessThanComparable. +
  • +
  • + Example: +
    optional<T> oN, oN_;
    +optional<T> o0(T(0));
    +optional<T> o1(T(1));
    +
    +assert ( !(oN < oN) );  // Identity implies equivalence
    +assert ( !(o1 < o1) );
    +
    +assert ( !(oN < oN_) ); // Two uninitialized are equivalent
    +assert ( !(oN_ < oN) );
    +
    +assert ( oN < o0 );     // Uninitialized is less than initialized
    +assert ( !(o0 < oN) );
    +
    +assert ( o1 < o2 ) ;    // Two initialized compare as (*lhs < *rhs)
    +assert ( !(o2 < o1) ) ;
    +assert ( !(o2 < o2) ) ;
    +
    +
  • +
+

+ space +

+

+ bool operator + != ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: !( + x == + y ); +
+

+ space +

+

+ bool operator + > ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: ( + y < + x ); +
+

+ space +

+

+ bool operator + <= ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: !( + y < + x ); +
+

+ space +

+

+ bool operator + >= ( + optional<T> const& x, optional<T> const& y ); +

+
  • + Returns: !( + x < + y ); +
+

+ space +

+

+ bool operator + == ( + optional<T> const& x, none_t ) + noexcept; +

+

+ bool operator + == ( + none_t, + optional<T> const& x ) noexcept; +

+
+

+ space +

+

+ bool operator + != ( + optional<T> const& x, none_t ) + noexcept; +

+

+ bool operator + != ( + none_t, + optional<T> const& x ) noexcept; +

+
  • + Returns: bool(x); +
+

+ space +

+

+ auto get_pointer + ( optional<T>& o + ) -> + typename optional<T>::pointer_type + ; +

+

+ auto get_pointer + ( optional<T> const& o ) -> typename optional<T>::pointer_const_type + ; +

+
    +
  • + Returns: o.get_ptr(). +
  • +
  • + Throws: Nothing. +
  • +
+

+ space +

+

+ auto get_optional_value_or + ( optional<T>& o, typename optional<T>::reference_type def + ) -> + typename optional<T>::reference_type + ; +

+

+ auto get_optional_value_or + ( optional<T> const& o, typename optional<T>::reference_const_type def + ) -> + typename optional<T>::reference_const_type + ; +

+
    +
  • + Returns: o.get_value_or(def). +
  • +
  • + Throws: Nothing. +
  • +
  • + Remarks: This function is deprecated. +
  • +
+

+ space +

+

+ void swap + ( optional<T>& x, optional<T>& y + ) ; +

+
    +
  • + Requires: Lvalues of type T shall be swappable and T shall be MoveConstructible. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + calls swap(*(*this), *rhs) +

    +
    +

    + initializes the contained value of *this as if direct-initializing + an object of type T + with the expression std::move(*rhs), followed by rhs.val->T::~T(), + *this + contains a value and rhs + does not contain a value +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + initializes the contained value of rhs + as if direct-initializing an object of type T with the expression + std::move(*(*this)), + followed by val->T::~T(), *this does not contain a value + and rhs contains + a value +

    +
    +

    + no effect +

    +
    +
  • +
  • + Postconditions: The states of x and y + interchanged. +
  • +
  • + Throws: If both are initialized, whatever + swap(T&,T&) + throws. If only one is initialized, whatever T::T ( T&& ) + throws. +
  • +
  • + Example: +
    T x(12);
    +T y(21);
    +optional<T> def0 ;
    +optional<T> def1 ;
    +optional<T> optX(x);
    +optional<T> optY(y);
    +
    +boost::swap(def0,def1); // no-op
    +
    +boost::swap(def0,optX);
    +assert ( *def0 == x );
    +assert ( !optX );
    +
    +boost::swap(def0,optX); // Get back to original values
    +
    +boost::swap(optX,optY);
    +assert ( *optX == y );
    +assert ( *optY == x );
    +
    +
  • +
+

+ space +

+

+ void swap + ( optional<T&>& x, optional<T&>& y + ) noexcept + ; +

+
    +
  • + Postconditions: x + refers to what y referred + to before the swap (if anything). y + refers to whatever x + referred to before the swap. +
  • +
  • + Example: +
    T x(12);
    +T y(21);
    +
    +optional<T&> opt0;
    +optional<T&> optX (x);
    +optional<T&> optY (y);
    +
    +boost::swap(optX, optY);
    +assert (addressof(*optX) == addressof(y));
    +assert (addressof(*optY) == addressof(x));
    +
    +boost::swap(opt0, optX);
    +assert ( opt0 );
    +assert ( !optX );
    +assert (addressof(*opt0) == addressof(y));
    +
    +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_references.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_references.html new file mode 100644 index 00000000..3a4d5fef --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_references.html @@ -0,0 +1,552 @@ + + + +Detailed Semantics - Optional References + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ space +

+

+ optional<T&>::optional() + noexcept; +

+

+ optional<T&>::optional(none_t) noexcept; +

+
  • + Postconditions: bool(*this) == false; *this refers to nothing. +
+

+ space +

+

+ template<class R> optional<T&>::optional(R&& r) noexcept; +

+
    +
  • + Postconditions: bool(*this) == true; addressof(**this) == addressof(r). +
  • +
  • + Remarks: Unless R + is an lvalue reference, the program is ill-formed. This constructor + does not participate in overload resolution if decay<R> is an instance of boost::optional. +
  • +
  • + Notes: This constructor is declared + explicit on compilers + that do not correctly support binding to const lvalues of integral types. + For more details see here. +
  • +
  • + Example: +
    T v;
    +T& vref = v ;
    +optional<T&> opt(vref);
    +assert ( *opt == v ) ;
    +++ v ; // mutate referee
    +assert (*opt == v);
    +
    +
  • +
+

+ space +

+

+ template<class R> optional<T&>::optional(bool cond, R&& + r) + noexcept; +

+
    +
  • + Effects: Initializes ref with expression cond ? + addressof(r) : nullptr. +
  • +
  • + Postconditions: bool(*this) == cond; If bool(*this), addressof(**this) == addressof(r). +
  • +
  • + Remarks: Unless R + is an lvalue reference, the program is ill-formed. This constructor + does not participate in overload resolution if decay<R> is an instance of boost::optional. +
  • +
+

+ space +

+

+ optional<T&>::optional ( + optional const& rhs + ) noexcept + ; +

+
    +
  • + Effects: Initializes ref with expression rhs.ref. +
  • +
  • + Postconditions: bool(*this) == bool(rhs). +
  • +
  • + Example: +
    optional<T&> uninit ;
    +assert (!uninit);
    +
    +optional<T&> uinit2 ( uninit ) ;
    +assert ( uninit2 == uninit );
    +
    +T v = 2 ; T& ref = v ;
    +optional<T> init(ref);
    +assert ( *init == v ) ;
    +
    +optional<T> init2 ( init ) ;
    +assert ( *init2 == v ) ;
    +
    +v = 3 ;
    +
    +assert ( *init  == 3 ) ;
    +assert ( *init2 == 3 ) ;
    +
    +
  • +
+

+ space +

+

+ template<class U> explicit + optional<T&>::optional ( + optional<U&> + const& + rhs ) + noexcept ; +

+
    +
  • + Requires: is_convertible<U&, T&>::value + is true. +
  • +
  • + Effects: Initializes ref with expression rhs.ref. +
  • +
  • + Postconditions: bool(*this) == bool(rhs). +
  • +
+

+ space +

+

+ optional<T&>::operator= ( none_t + ) noexcept + ; +

+
    +
  • + Effects: Assigns ref + with expression nullptr. +
  • +
  • + returns: *this. +
  • +
  • + Postconditions: bool(*this) == false. +
  • +
+

+ optional& + optional<T&>::operator= ( optional + const& + rhs ) + noexcept ; +

+
    +
  • + Effects: Assigns ref + with expression rhs.ref. +
  • +
  • + returns: *this. +
  • +
  • + Postconditions: bool(*this) == bool(rhs). +
  • +
  • + Notes: This behaviour is called rebinding + semantics. See here + for details. +
  • +
  • + Example: +
    int a = 1 ;
    +int b = 2 ;
    +T& ra = a ;
    +T& rb = b ;
    +optional<int&> def ;
    +optional<int&> ora(ra) ;
    +optional<int&> orb(rb) ;
    +
    +def = orb ; // binds 'def' to 'b' through 'rb' wrapped within 'orb'
    +assert ( *def == b ) ;
    +*def = ora ; // changes the value of 'b' to a copy of the value of 'a'
    +assert ( b == a ) ;
    +int c = 3;
    +int& rc = c ;
    +optional<int&> orc(rc) ;
    +ora = orc ; // REBINDS ora to 'c' through 'rc'
    +c = 4 ;
    +assert ( *ora == 4 ) ;
    +
    +
  • +
+

+ template<class U> optional& optional<T&>::operator= ( optional<U&> const& rhs + ) noexcept + ; +

+
    +
  • + Requires: is_convertible<U&, T&>::value + is true. +
  • +
  • + Effects: Assigns ref + with expression rhs.ref. +
  • +
  • + returns: *this. +
  • +
  • + Postconditions: bool(*this) == bool(rhs). +
  • +
+

+ space +

+

+ template<class R> optional& optional<T&>::operator= ( R&& r + ) noexcept + ; +

+
    +
  • + Effects: Assigns ref + with expression r. +
  • +
  • + returns: *this. +
  • +
  • + Postconditions: bool(*this) == true. +
  • +
  • + Remarks: Unless R + is an lvalue reference, the program is ill-formed. This function does + not participate in overload resolution if decay<R> is an instance of boost::optional. +
  • +
  • + Example: +
    int a = 1 ;
    +int b = 2 ;
    +T& ra = a ;
    +T& rb = b ;
    +optional<int&> def ;
    +optional<int&> opt(ra) ;
    +
    +def = rb ; // binds 'def' to 'b' through 'rb'
    +assert ( *def == b ) ;
    +*def = a ; // changes the value of 'b' to a copy of the value of 'a'
    +assert ( b == a ) ;
    +int c = 3;
    +int& rc = c ;
    +opt = rc ; // REBINDS to 'c' through 'rc'
    +c = 4 ;
    +assert ( *opt == 4 ) ;
    +
    +
  • +
+

+ space +

+

+ void optional<T&>::emplace( R&& r + ) noexcept + ; +

+
    +
  • + Effects: Assigns ref + with expression r. +
  • +
  • + Postconditions: bool(*this) == true. +
  • +
  • + Remarks: Unless R + is an lvalue reference, the program is ill-formed. This function does + not participate in overload resolution if decay<R> is an instance of boost::optional. +
  • +
+

+ space +

+

+ T& + optional<T&>::get() const ; +

+

+ T& + optional<T&>::operator *() + const ; +

+
    +
  • + Requires: bool(*this) == true. +
  • +
  • + Effects: Returns *ref. +
  • +
  • + Throws: Nothing. +
  • +
  • + Example: +
    T v ;
    +T& vref = v ;
    +optional<T&> opt ( vref );
    +T const& vref2 = *opt;
    +assert ( vref2 == v ) ;
    +++ v ;
    +assert ( *opt == v ) ;
    +
    +
  • +
+

+ space +

+

+ T* + optional<T&>::operator -> + () const + ; +

+
    +
  • + Requires: bool(*this) == true. +
  • +
  • + Effects: Returns ref. +
  • +
  • + Throws: Nothing. +
  • +
+

+ space +

+

+ T& + optional<T&>::value() const ; +

+
  • + Effects: Equivalent to return bool(*this) ? *val : throw bad_optional_access();. +
+

+ space +

+

+ template<class R> T& optional<T&>::value_or( R&& r + ) const + noexcept; +

+
    +
  • + Effects: Equivalent to if (*this) return **this; else return + r;. +
  • +
  • + Remarks: Unless R + is an lvalue reference, the program is ill-formed. +
  • +
+

+ space +

+

+ template<class F> T& optional<T&>::value_or( F f ) const ; +

+
    +
  • + Effects: Equivalent to if (*this) return **this; else return + f();. +
  • +
  • + Remarks: Unless decltype(f()) is an lvalue reference, the program + is ill-formed. +
  • +
+

+ space +

+

+ template<class F> auto optional<T&>::map( F f ) const -> see below; +

+
    +
  • + Effects: Equivalent to if (*this) return f(**this); else return none;. +
  • +
  • + Remarks: The return type of this function + is optional<decltype(f(**this))>. +
  • +
+

+ space +

+

+ template<class F> auto optional<T&>::flat_map( + F f + ) const + -> see below; +

+
    +
  • + Requires: The return type of expression + f(**this) + is optional<U> + for some object or reference type U. +
  • +
  • + Effects: Equivalent to if (*this) return f(**this); else return none;. +
  • +
  • + Remarks: The return type of this function + is optional<U>. +
  • +
+

+ space +

+

+ T* + optional<T&>::get_ptr () + const noexcept; +

+
  • + Returns: ref. +
+

+ space +

+

+ bool has_value() const noexcept; +

+

+ optional<T&>::operator bool + () const + noexcept; +

+
  • + Returns: bool(ref). +
+

+ space +

+

+ optional<T&>::operator ! () const noexcept; +

+
  • + Returns: !bool(ref). +
+

+ space +

+

+ void optional<T&>::reset() noexcept; +

+
  • + Effects: Same as *this = none. +
+

+ space +

+

+ template<class R> void optional<T&>::reset ( R&& + r) + noexcept; +

+
    +
  • + Effects: Equivalent to *this = std::forward<R>(r). +
  • +
  • + Remarks: This function is deprecated. +
  • +
+

+ space +

+

+ bool optional<T&>::is_initialized() const noexcept; +

+
    +
  • + Effects: Equivalent to return bool(*this). +
  • +
  • + Remarks: This function is deprecated. +
  • +
+

+ space +

+

+ template<class R> T& optional<T&>::get_value_or( R&& r + ) const + noexcept; +

+
    +
  • + Effects: Equivalent to return value_or(std::forward<R>(r);. +
  • +
  • + Remarks: This function is deprecated. +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html new file mode 100644 index 00000000..ce614066 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/detailed_semantics___optional_values.html @@ -0,0 +1,1788 @@ + + + +Detailed Semantics - Optional Values + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ + + + + +
[Note]Note

+ The following section contains various assert() which are used only to show the postconditions + as sample code. It is not implied that the type T + must support each particular expression but that if the expression is + supported, the implied condition holds. +

+

+ space +

+

+ optional<T>::optional() + noexcept; +

+
    +
  • + Effect: Default-Constructs an optional. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
  • + Notes: T's default constructor is not called. +
  • +
  • + Example: +
    optional<T> def ;
    +assert ( !def ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( + none_t ) + noexcept; +

+
    +
  • + Effect: Constructs an optional uninitialized. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
  • + Notes: T's + default constructor is not called. + The expression boost::none + denotes an instance of boost::none_t + that can be used as the parameter. +
  • +
  • + Example: +
    #include <boost/none.hpp>
    +optional<T> n(none) ;
    +assert ( !n ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( + T const& v ) +

+
    +
  • + Requires: is_copy_constructible<T>::value + is true. +
  • +
  • + Effect: Directly-Constructs an optional. +
  • +
  • + Postconditions: *this is initialized + and its value is a copy of v. +
  • +
  • + Throws: Whatever T::T( T const& + ) throws. +
  • +
  • + Notes: T::T( T const& + ) is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +assert ( *opt == v ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( + T&& + v ) +

+
    +
  • + Requires: is_move_constructible<T>::value + is true. +
  • +
  • + Effect: Directly-Move-Constructs an + optional. +
  • +
  • + Postconditions: *this is initialized + and its value is move-constructed from v. +
  • +
  • + Throws: Whatever T::T( T&& ) + throws. +
  • +
  • + Notes: T::T( T&& ) + is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T&& ); + in that case, the state of v + is determined by exception safety guarantees for T::T(T&&). +
  • +
  • + Example: +
    T v1, v2;
    +optional<T> opt(std::move(v1));
    +assert ( *opt == v2 ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( + bool condition, T const& v ) ; +

+
  • + If condition is true, same as: +
+

+ optional<T>::optional( + T const& v ) +

+
  • + otherwise, same as: +
+

+ optional<T>::optional() +

+

+ space +

+

+ optional<T>::optional( + optional const& rhs + ); +

+
    +
  • + Requires: is_copy_constructible<T>::value + is true. +
  • +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs is initialized, + *this + is initialized and its value is a copy of the + value of rhs; else + *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( T const& + ) throws. +
  • +
  • + Notes: If rhs is initialized, T::T(T const& ) + is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    optional<T> uninit ;
    +assert (!uninit);
    +
    +optional<T> uinit2 ( uninit ) ;
    +assert ( uninit2 == uninit );
    +
    +optional<T> init( T(2) );
    +assert ( *init == T(2) ) ;
    +
    +optional<T> init2 ( init ) ;
    +assert ( init2 == init ) ;
    +
    +
  • +
+

+ space +

+

+ optional<T>::optional( + optional&& + rhs ) + noexcept(see + below); +

+
    +
  • + Requires: is_move_constructible<T>::value + is true. +
  • +
  • + Effect: Move-constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move constructed from rhs; else *this is uninitialized. +
  • +
  • + Throws: Whatever T::T( T&& ) + throws. +
  • +
  • + Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible<T>::value. +
  • +
  • + Notes: If rhs + is initialized, T::T( T && + ) is called. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( T&& ); + in that case, rhs remains + initialized and the value of *rhs is determined by exception safety + of T::T(T&&). +
  • +
  • + Example: +
    optional<std::unique_ptr<T>> uninit ;
    +assert (!uninit);
    +
    +optional<std::unique_ptr<T>> uinit2 ( std::move(uninit) ) ;
    +assert ( uninit2 == uninit );
    +
    +optional<std::unique_ptr<T>> init( std::unique_ptr<T>(new T(2)) );
    +assert ( **init == T(2) ) ;
    +
    +optional<std::unique_ptr<T>> init2 ( std::move(init) ) ;
    +assert ( init );
    +assert ( *init == nullptr );
    +assert ( init2 );
    +assert ( **init2 == T(2) ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> explicit optional<T>::optional( optional<U> const& rhs + ); +

+
    +
  • + Effect: Copy-Constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is a copy of the + value of rhs converted to type T; + else *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( U const& + ) throws. +
  • +
  • + Notes: T::T( U const& + ) is called if rhs is initialized, which requires + a valid conversion from U + to T. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( U const& + ); in that case, this constructor + has no effect. +
  • +
  • + Example: +
    optional<double> x(123.4);
    +assert ( *x == 123.4 ) ;
    +
    +optional<int> y(x) ;
    +assert( *y == 123 ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> explicit optional<T>::optional( optional<U>&& rhs + ); +

+
    +
  • + Effect: Move-constructs an optional. +
  • +
  • + Postconditions: If rhs + is initialized, *this + is initialized and its value is move-constructed from *rhs; + else *this + is uninitialized. +
  • +
  • + Throws: Whatever T::T( U&& ) + throws. +
  • +
  • + Notes: T::T( U&& ) + is called if rhs is + initialized, which requires a valid conversion from U + to T. +
  • +
  • + Exception Safety: Exceptions can only + be thrown during T::T( U&& ); + in that case, rhs remains + initialized and the value of *rhs is determined by exception safety + guarantee of T::T( U&& + ). +
  • +
  • + Example: +
    optional<double> x(123.4);
    +assert ( *x == 123.4 ) ;
    +
    +optional<int> y(std::move(x)) ;
    +assert( *y == 123 ) ;
    +
    +
  • +
+

+ space +

+

+ template<class... Args> + explicit optional<T>::optional( in_place_init_t, Args&&... ars + ); +

+
    +
  • + Requires: is_constructible_v<T, Args&&...> is true. +
  • +
  • + Effect: Initializes the contained + value as if direct-non-list-initializing an object of type T with the arguments std::forward<Args>(args).... +
  • +
  • + Postconditions: *this is initialized. +
  • +
  • + Throws: Any exception thrown by the + selected constructor of T. +
  • +
  • + Notes: T + need not be MoveConstructible. + On compilers that do not support variadic templates or rvalue references, + this constuctor is available in limited functionality. For details + see here. +
  • +
  • + Example: +
    // creates an std::mutex using its default constructor
    +optional<std::mutex> om {in_place_init};
    +assert (om);
    +
    +// creates a unique_lock by calling unique_lock(*om, std::defer_lock)
    +optional<std::unique_lock<std::mutex>> ol {in_place_init, *om, std::defer_lock};
    +assert (ol);
    +assert (!ol->owns_lock());
    +
    +
  • +
+

+ space +

+

+ template<class... Args> + explicit optional<T>::optional( in_place_init_if_t, bool condition, + Args&&... + ars ); +

+
    +
  • + Requires: is_constructible_v<T, Args&&...> is true. +
  • +
  • + Effect: If condition + is true, initializes the + contained value as if direct-non-list-initializing an object of type + T with the arguments + std::forward<Args>(args).... +
  • +
  • + Postconditions: bool(*this) == condition. +
  • +
  • + Throws: Any exception thrown by the + selected constructor of T. +
  • +
  • + Notes: T + need not be MoveConstructible. + On compilers that do not support variadic templates or rvalue references, + this constuctor is available in limited functionality. For details + see here. +
  • +
  • + Example: +
    optional<std::vector<std::string>> ov1 {in_place_init_if, false, 3, "A"};
    +assert (!ov1);
    +
    +optional<std::vector<std::string>> ov2 {in_place_init_if, true, 3, "A"};
    +assert (ov2);
    +assert (ov2->size() == 3);
    +
    +
  • +
+

+ space +

+

+ template<InPlaceFactory> + explicit optional<T>::optional( InPlaceFactory + const& + f ); +

+

+ template<TypedInPlaceFactory> + explicit optional<T>::optional( TypedInPlaceFactory + const& + f ); +

+
    +
  • + Effect: Constructs an optional with a value of T obtained from the factory. +
  • +
  • + Postconditions: *this is initialized + and its value is directly given from the factory + f (i.e., the value + is not copied). +
  • +
  • + Throws: Whatever the T constructor called by the factory + throws. +
  • +
  • + Notes: See In-Place + Factories +
  • +
  • + Exception Safety: Exceptions can only + be thrown during the call to the T + constructor used by the factory; in that case, this constructor has + no effect. +
  • +
  • + Example: +
    class C { C ( char, double, std::string ) ; } ;
    +
    +C v('A',123.4,"hello");
    +
    +optional<C> x( in_place   ('A', 123.4, "hello") ); // InPlaceFactory used
    +optional<C> y( in_place<C>('A', 123.4, "hello") ); // TypedInPlaceFactory used
    +
    +assert ( *x == v ) ;
    +assert ( *y == v ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( none_t + ) noexcept; +

+
    +
  • + Effect: If *this is initialized destroys its contained + value. +
  • +
  • + Postconditions: *this is uninitialized. +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( T const& rhs ) ; +

+
    +
  • + Effect: Assigns the value rhs to an optional. +
  • +
  • + Postconditions: *this is initialized and its value is + a copy of rhs. +
  • +
  • + Throws: Whatever T::operator=( T const& + ) or T::T(T const&) + throws. +
  • +
  • + Notes: If *this was initialized, T's assignment operator is used, + otherwise, its copy-constructor is used. +
  • +
  • + Exception Safety: In the event of + an exception, the initialization state of *this is unchanged and its value unspecified + as far as optional + is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + copy constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T x;
    +optional<T> def ;
    +optional<T> opt(x) ;
    +
    +T y;
    +def = y ;
    +assert ( *def == y ) ;
    +opt = y ;
    +assert ( *opt == y ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( T&& rhs + ) ; +

+
    +
  • + Effect: Moves the value rhs to an optional. +
  • +
  • + Postconditions: *this is initialized and its value is + moved from rhs. +
  • +
  • + Throws: Whatever T::operator=( T&& ) + or T::T(T &&) + throws. +
  • +
  • + Notes: If *this was initialized, T's move-assignment operator is used, + otherwise, its move-constructor is used. +
  • +
  • + Exception Safety: In the event of + an exception, the initialization state of *this is unchanged and its value unspecified + as far as optional + is concerned (it is up to T's + operator=()). + If *this + is initially uninitialized and T's + move constructor fails, *this is left properly uninitialized. +
  • +
  • + Example: +
    T x;
    +optional<T> def ;
    +optional<T> opt(x) ;
    +
    +T y1, y2, yR;
    +def = std::move(y1) ;
    +assert ( *def == yR ) ;
    +opt = std::move(y2) ;
    +assert ( *opt == yR ) ;
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( optional + const& + rhs ) + ; +

+
    +
  • + Requires: T + is CopyConstructible and CopyAssignable. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns *rhs + to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with *rhs +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this; +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the initialization state of *this and rhs + remains unchanged. If an exception is thrown during the call to T's copy constructor, no effect. + If an exception is thrown during the call to T's + copy assignment, the state of its contained value is as defined by + the exception safety guarantee of T's + copy assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +optional<T> def ;
    +
    +opt = def ;
    +assert ( !def ) ;
    +// previous value (copy of 'v') destroyed from within 'opt'.
    +
    +
  • +
+

+ space +

+

+ optional& + optional<T>::operator= ( optional&& rhs + ) noexcept(see below); +

+
    +
  • + Requires: T + is MoveConstructible + and MoveAssignable. +
  • +
  • +

    + Effects: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns std::move(*rhs) to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with std::move(*rhs) +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this; +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible<T>::value && + is_nothrow_move_assignable<T>::value. +
  • +
  • + Exception Safety: If any exception + is thrown, the initialization state of *this and rhs + remains unchanged. If an exception is thrown during the call to T's move constructor, the state of + *rhs + is determined by the exception safety guarantee of T's + move constructor. If an exception is thrown during the call to T's + move-assignment, the state of **this and *rhs is determined by the exception + safety guarantee of T's move assignment. +
  • +
  • + Example: +
    optional<T> opt(T(2)) ;
    +optional<T> def ;
    +
    +opt = def ;
    +assert ( def ) ;
    +assert ( opt ) ;
    +assert ( *opt == T(2) ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> optional& + optional<T>::operator= ( optional<U> const& rhs + ) ; +

+
    +
  • +

    + Effect: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns *rhs + to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with *rhs +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this. +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the result of the expression bool(*this) remains unchanged. If an exception + is thrown during the call to T's + constructor, no effect. If an exception is thrown during the call to + T's assignment, the + state of its contained value is as defined by the exception safety + guarantee of T's copy + assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt0(v);
    +optional<U> opt1;
    +
    +opt1 = opt0 ;
    +assert ( *opt1 == static_cast<U>(v) ) ;
    +
    +
  • +
+

+ space +

+

+ template<U> optional& + optional<T>::operator= ( optional<U>&& rhs + ) ; +

+
    +
  • +

    + Effect: +

    +
    +++++ + + + + + + + + + + + + + + + + + + +
    + +

    + *this contains a value +

    +
    +

    + *this does not contain a value +

    +
    +

    + rhs + contains a value +

    +
    +

    + assigns std::move(*rhs) to the contained value +

    +
    +

    + initializes the contained value as if direct-initializing + an object of type T + with std::move(*rhs) +

    +
    +

    + rhs + does not contain a value +

    +
    +

    + destroys the contained value by calling val->T::~T() +

    +
    +

    + no effect +

    +
    +
  • +
  • + Returns: *this. +
  • +
  • + Postconditions: bool(rhs) == bool(*this). +
  • +
  • + Exception Safety: If any exception + is thrown, the result of the expression bool(*this) remains unchanged. If an exception + is thrown during the call to T's + constructor, no effect. If an exception is thrown during the call to + T's assignment, the + state of its contained value is as defined by the exception safety + guarantee of T's copy + assignment. +
  • +
  • + Example: +
    T v;
    +optional<T> opt0(v);
    +optional<U> opt1;
    +
    +opt1 = std::move(opt0) ;
    +assert ( opt0 );
    +assert ( opt1 )
    +assert ( *opt1 == static_cast<U>(v) ) ;
    +
    +
  • +
+

+ space +

+

+ template<class... Args> + void optional<T>::emplace( Args&&... args + ); +

+
    +
  • + Requires: The compiler supports rvalue + references and variadic templates. +
  • +
  • + Effect: If *this is initialized calls *this = none. + Then initializes in-place the contained value as if direct-initializing + an object of type T + with std::forward<Args>(args).... +
  • +
  • + Postconditions: *this is initialized. +
  • +
  • + Throws: Whatever the selected T's constructor throws. +
  • +
  • + Exception Safety: If an exception + is thrown during the initialization of T, + *this + is uninitialized. +
  • +
  • + Notes: T + need not be MoveConstructible + or MoveAssignable. + On compilers that do not support variadic templates or rvalue references, + this function is available in limited functionality. For details see here. +
  • +
  • + Example: +
    T v;
    +optional<const T> opt;
    +opt.emplace(0);  // create in-place using ctor T(int)
    +opt.emplace();   // destroy previous and default-construct another T
    +opt.emplace(v);  // destroy and copy-construct in-place (no assignment called)
    +
    +
  • +
+

+ space +

+

+ template<InPlaceFactory> + optional<T>& + optional<T>::operator=( InPlaceFactory const& f ); +

+

+ template<TypedInPlaceFactory> + optional<T>& + optional<T>::operator=( TypedInPlaceFactory const& f ); +

+
    +
  • + Effect: Assigns an optional + with a value of T obtained + from the factory. +
  • +
  • + Postconditions: *this is initialized + and its value is directly given from the factory + f (i.e., the value + is not copied). +
  • +
  • + Throws: Whatever the T constructor called by the factory + throws. +
  • +
  • + Notes: See In-Place + Factories +
  • +
  • + Exception Safety: Exceptions can only + be thrown during the call to the T + constructor used by the factory; in that case, the optional + object will be reset to be uninitialized. +
  • +
+

+ space +

+

+ void optional<T>::reset( T const& v ) ; +

+
  • + Deprecated: same as operator= + ( T + const& + v) + ; +
+

+ space +

+

+ void optional<T>::reset() noexcept + ; +

+
  • + Effects: Same as operator=( none_t + ); +
+

+ space +

+

+ T const& optional<T>::get() const ; +

+

+ T& + optional<T>::get() ; +

+

+ inline T + const& + get ( + optional<T> const& ) ; +

+

+ inline T& get + ( optional<T> &) + ; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: A reference to the contained + value +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). +
  • +
+

+ space +

+

+ T const& optional<T>::operator*() const& ; +

+

+ T& + optional<T>::operator*() + &; +

+
    +
  • + Requires: *this is initialized +
  • +
  • + Returns: A reference to the contained + value +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions + these two overloads are replaced with the classical two: a const and non-const + member functions. +
  • +
  • + Example: +
    T v ;
    +optional<T> opt ( v );
    +T const& u = *opt;
    +assert ( u == v ) ;
    +T w ;
    +*opt = w ;
    +assert ( *opt == w ) ;
    +
    +
  • +
+

+ space +

+

+ T&& + optional<T>::operator*() + &&; +

+
    +
  • + Requires: *this contains a value. +
  • +
  • + Effects: Equivalent to return std::move(*val);. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). + On compilers that do not support ref-qualifiers on member functions + this overload is not present. +
  • +
+

+ space +

+

+ T const& optional<T>::value() const& ; +

+

+ T& + optional<T>::value() & ; +

+
    +
  • + Effects: Equivalent to return bool(*this) ? *val : throw bad_optional_access();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions these two overloads are replaced + with the classical two: a const + and non-const member functions. +
  • +
  • + Example: +
    T v ;
    +optional<T> o0, o1 ( v );
    +assert ( o1.value() == v );
    +
    +try {
    +  o0.value(); // throws
    +  assert ( false );
    +}
    +catch(bad_optional_access&) {
    +  assert ( true );
    +}
    +
    +
  • +
+

+ space +

+

+ T&& + optional<T>::value() && ; +

+
    +
  • + Effects: Equivalent to return bool(*this) ? std::move(*val) : throw bad_optional_access();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ template<class U> T optional<T>::value_or(U && + v) + const& + ; +

+
    +
  • + Effects: Equivalent to if (*this) return **this; else return + std::forward<U>(v);. +
  • +
  • + Remarks: If T + is not CopyConstructible or U && + is not convertible to T, + the program is ill-formed. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is replaced with the + const-qualified member + function. On compilers without rvalue reference support the type of + v becomes U const&. +
  • +
+

+ space +

+

+ template<class U> T optional<T>::value_or(U && + v) + && ; +

+
    +
  • + Effects: Equivalent to if (*this) return std::move(**this); else return std::forward<U>(v);. +
  • +
  • + Remarks: If T + is not MoveConstructible + or U && + is not convertible to T, + the program is ill-formed. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ template<class F> T optional<T>::value_or_eval(F f) const& ; +

+
    +
  • + Requires: T + is CopyConstructible and F models a Generator whose result type + is convertible to T. +
  • +
  • + Effects: if + (*this) return **this; else return f();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is replaced with the + const-qualified member + function. +
  • +
  • + Example: +
    int complain_and_0()
    +{
    +  clog << "no value returned, using default" << endl;
    +  return 0;
    +}
    +
    +optional<int> o1 = 1;
    +optional<int> oN = none;
    +
    +int i = o1.value_or_eval(complain_and_0); // fun not called
    +assert (i == 1);
    +
    +int j = oN.value_or_eval(complain_and_0); // fun called
    +assert (i == 0);
    +
    +
  • +
+

+ space +

+

+ template<class F> T optional<T>::value_or_eval(F f) && + ; +

+
    +
  • + Requires: T + is MoveConstructible + and F models a Generator + whose result type is convertible to T. +
  • +
  • + Effects: if + (*this) return std::move(**this); else return + f();. +
  • +
  • + Notes: On compilers that do not support + ref-qualifiers on member functions this overload is not present. +
  • +
+

+ space +

+

+ template<class F> auto optional<T>::map(F f) const& -> + see below ; +

+

+ template<class F> auto optional<T>::map(F f) & -> see below + ; +

+
    +
  • + Effects: if + (*this) return f(**this); else return + none; +
  • +
  • + Notes: The return type of these overloads + is optional<decltype(f(**this))>. + On compilers that do not support ref-qualifiers on member functions, + these two (as well as the next one) overloads are replaced with good + old const and non-const overloads. +
  • +
  • + Example: +
    auto length = [](const string& s){ return s.size(); };
    +optional<string> o1 {}, o2 {"cat"};
    +optional<size_t> os1 = o1.map(length), os2 = o2.map(length);
    +assert ( !os1 ) ;
    +assert ( os2 ) ;
    +assert ( *os2 == 3 ) ;
    +
    +
  • +
+

+ space +

+

+ template<class F> auto optional<T>::map(F f) && + -> see below + ; +

+
    +
  • + Effects: if + (*this) return f(std::move(**this)); else return + none; +
  • +
  • + Notes: The return type of this overload + is optional<decltype(f(istd::move(**this)))>. +
  • +
+

+ space +

+

+ template<class F> auto optional<T>::flat_map(F f) const& -> + see below ; +

+

+ template<class F> auto optional<T>::flat_map(F f) & -> see below + ; +

+
    +
  • + Requires: The return type of expression + f(**this) + is optional<U> + for some object or reference type U. +
  • +
  • + Effects: if + (*this) return f(**this); else return + none; +
  • +
  • + Notes: The return type of these overloads + is optional<U>. + On compilers that do not support ref-qualifiers on member functions, + these two (as well as the next one) overloads are replaced with good + old const and non-const overloads. +
  • +
  • + Example: +
    optional<char> first_char(const string& s) {
    +  return s.empty() ? none : optional<char>(s[0]);
    +};
    +optional<string> o1 {}, o2 {"cat"};
    +optional<char> os1 = o1.flat_map(first_char), os2 = o2.flat_map(first_char);
    +assert ( !os1 ) ;
    +assert ( os2 ) ;
    +assert ( *os2 == 'c' ) ;
    +
    + space +
  • +
+

+ template<class F> auto optional<T>::flat_map(F f) && + -> see below + ; +

+
    +
  • + Requires: The return type of expression + f(std::move(**this)) + is optional<U> + for some object or reference type U. +
  • +
  • + Effects: if + (*this) return f(std::move(**this)); else return + none; +
  • +
  • + Notes: The return type of this overload + is optional<U>. +
  • +
+

+ space +

+

+ T const& optional<T>::get_value_or( T const& default) const ; +

+

+ T& + optional<T>::get_value_or( + T& + default ) + ; +

+
    +
  • + Deprecated: Use value_or() instead. +
  • +
  • + Returns: A reference to the contained + value, if any, or default. +
  • +
  • + Throws: Nothing. +
  • +
  • + Example: +
    T v, z ;
    +optional<T> def;
    +T const& y = def.get_value_or(z);
    +assert ( y == z ) ;
    +
    +optional<T> opt ( v );
    +T const& u = opt.get_value_or(z);
    +assert ( u == v ) ;
    +assert ( u != z ) ;
    +
    +
  • +
+

+ space +

+

+ T const* optional<T>::get_ptr() const ; +

+

+ T* + optional<T>::get_ptr() + ; +

+
    +
  • + Returns: If *this is initialized, a pointer to the + contained value; else 0 + (null). +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The contained value is permanently + stored within *this, + so you should not hold nor delete this pointer +
  • +
  • + Example: +
    T v;
    +optional<T> opt(v);
    +optional<T> const copt(v);
    +T* p = opt.get_ptr() ;
    +T const* cp = copt.get_ptr();
    +assert ( p == get_pointer(opt) );
    +assert ( cp == get_pointer(copt) ) ;
    +
    +
  • +
+

+ space +

+

+ T const* optional<T>::operator + ->() const + ; +

+

+ T* + optional<T>::operator ->() + ; +

+
    +
  • + Requires: *this is initialized. +
  • +
  • + Returns: A pointer to the contained + value. +
  • +
  • + Throws: Nothing. +
  • +
  • + Notes: The requirement is asserted + via BOOST_ASSERT(). +
  • +
  • + Example: +
    struct X { int mdata ; } ;
    +X x ;
    +optional<X> opt (x);
    +opt->mdata = 2 ;
    +
    +
  • +
+

+ space +

+

+ explicit optional<T>::operator + bool() + const noexcept + ; +

+

+ bool optional<T>::has_value() const noexcept ; +

+
    +
  • + Returns: get_ptr() != 0. +
  • +
  • + Notes: On compilers that do not support + explicit conversion operators this falls back to safe-bool idiom. +
  • +
  • + Example: +
    optional<T> def ;
    +assert ( def == 0 );
    +optional<T> opt ( v ) ;
    +assert ( opt );
    +assert ( opt != 0 );
    +
    +
  • +
+

+ space +

+

+ bool optional<T>::operator!() noexcept + ; +

+
    +
  • + Returns: If *this is uninitialized, true; else false. +
  • +
  • + Notes: This operator is provided for + those compilers which can't use the unspecified-bool-type + operator in certain boolean contexts. +
  • +
  • + Example: +
    optional<T> opt ;
    +assert ( !opt );
    +*opt = some_T ;
    +
    +// Notice the "double-bang" idiom here.
    +assert ( !!opt ) ;
    +
    +
  • +
+

+ space +

+

+ bool optional<T>::is_initialized() const ; +

+
  • + Deprecated: Same as explicit operator + bool () + ; +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header__boost_optional_hpp_.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header__boost_optional_hpp_.html new file mode 100644 index 00000000..8496d372 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header__boost_optional_hpp_.html @@ -0,0 +1,47 @@ + + + +Header <boost/optional.hpp> + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This is an alias for header <boost/optional/optional.hpp>. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_in_place_init.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_in_place_init.html new file mode 100644 index 00000000..ca73fd90 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_in_place_init.html @@ -0,0 +1,61 @@ + + + +Initialization tags + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
namespace boost {
+
+class in_place_init_t { /* see below */ } ;
+const in_place_init_t in_place_init ( /* see below */ ) ;
+
+class in_place_init_if_t { /*see below*/ } ;
+const in_place_init_if_t in_place_init_if ( /*see below*/ ) ;
+
+}
+
+

+ Classes in_place_init_t + and in_place_init_if_t + are empty classes. Their purpose is to control overload resolution in the + initialization of optional objects. They are empty, trivially copyable + classes with disabled default constructor. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_refs.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_refs.html new file mode 100644 index 00000000..3244e972 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_refs.html @@ -0,0 +1,118 @@ + + + +Optional References + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
template <class T>
+class optional<T&> // specialization for lvalue references
+{
+public :
+
+    typedef T& value_type;
+    typedef T& reference_type;
+    typedef T& reference_const_type; // no const propagation
+    typedef T& rval_reference_type;
+    typedef T* pointer_type;
+    typedef T* pointer_const_type;   // no const propagation
+
+    optional () noexcept ; R
+
+    optional ( none_t ) noexcept ; R
+
+    template<class R> optional(R&& r) noexcept ;  R
+
+    template <class R> optional(bool cond, R&& r) noexcept ; R
+
+    optional ( optional const& rhs ) noexcept ; R
+
+    template<class U> explicit optional ( optional<U&> const& rhs ) noexcept ; R
+
+    optional& operator = ( none_t ) noexcept ; R
+
+    optional& operator = ( optional const& rhs ) noexcept; R
+
+    template<class U> optional& operator = ( optional<U&> const& rhs ) noexcept ; R
+
+    template<class R> optional& operator = (R&& r) noexcept ; R
+
+    template<class R> void emplace ( R&& r ) noexcept ; R
+
+    T& get() const ; R
+    T& operator *() const ; R
+
+    T* operator ->() const ; R
+
+    T& value() const& ; R
+
+    template<class R> T& value_or( R && r ) const noexcept ; R
+
+    template<class F> T& value_or_eval( F f ) const ; R
+
+    template<class F> auto map( F f ) const -> see below; R
+
+    template<class F> auto flat_map( F f ) const -> see below; R
+
+    T* get_ptr() const noexcept ; R
+
+    bool has_value() const noexcept ; R
+
+    explicit operator bool() const noexcept ; R
+
+    bool operator!() const noexcept ; R
+
+    void reset() noexcept ; R
+
+    // deprecated methods
+
+    // (deprecated)
+    template<class R> void reset ( R && r ) noexcept ; R
+
+    // (deprecated)
+    bool is_initialized() const noexcept ; R
+
+    // (deprecated)
+    template<class R> T& get_value_or( R && r ) constnoexcept; R
+
+private:
+    T* ref; // exposition only
+};
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html new file mode 100644 index 00000000..80d648a6 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/header__boost_optional_optional_hpp_/header_optional_optional_values.html @@ -0,0 +1,153 @@ + + + +Optional Values + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
template <class T>
+class optional
+{
+public :
+
+    typedef T         value_type ;
+    typedef T &       reference_type ;
+    typedef T const&  reference_const_type ;
+    typedef T &&      rval_reference_type ;
+    typedef T *       pointer_type ;
+    typedef T const*  pointer_const_type ;
+
+    optional () noexcept ; R
+
+    optional ( none_t ) noexcept ; R
+
+    optional ( T const& v ) ; R
+
+    optional ( T&& v ) ; R
+
+    optional ( bool condition, T const& v ) ; R
+
+    optional ( optional const& rhs ) ; R
+
+    optional ( optional&& rhs ) noexcept(see below) ; R
+
+    template<class U> explicit optional ( optional<U> const& rhs ) ; R
+
+    template<class U> explicit optional ( optional<U>&& rhs ) ; R
+
+    template<class... Args> explicit optional ( in_place_init_t, Args&&... args ) ; R
+
+    template<class... Args> explicit optional ( in_place_init_if_t, bool condition, Args&&... args ) ; R
+
+    template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ; R
+
+    template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ; R
+
+    optional& operator = ( none_t ) noexcept ; R
+
+    optional& operator = ( T const& v ) ; R
+
+    optional& operator = ( T&& v ) ; R
+
+    optional& operator = ( optional const& rhs ) ; R
+
+    optional& operator = ( optional&& rhs ) noexcept(see below) ; R
+
+    template<class U> optional& operator = ( optional<U> const& rhs ) ; R
+
+    template<class U> optional& operator = ( optional<U>&& rhs ) ; R
+
+    template<class... Args> void emplace ( Args&&... args ) ; R
+
+    template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ; R
+
+    template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ; R
+
+    T const& get() const ; R
+    T&       get() ; R
+
+    T const* operator ->() const ; R
+    T*       operator ->() ; R
+
+    T const& operator *() const& ; R
+    T&       operator *() & ; R
+    T&&      operator *() && ; R
+
+    T const& value() const& ; R
+    T&       value() & ; R
+    T&&      value() && ; R
+
+    template<class U> T value_or( U && v ) const& ; R
+    template<class U> T value_or( U && v ) && ; R
+
+    template<class F> T value_or_eval( F f ) const& ; R
+    template<class F> T value_or_eval( F f ) && ; R
+
+    template<class F> auto map( F f ) const& -> see below; R
+    template<class F> auto map( F f ) & -> see below; R
+    template<class F> auto map( F f ) && -> see below; R
+
+    template<class F> auto flat_map( F f ) const& -> see below; R
+    template<class F> auto flat_map( F f ) & -> see below; R
+    template<class F> auto flat_map( F f ) && -> see below; R
+
+    T const* get_ptr() const ; R
+    T*       get_ptr() ; R
+
+    bool has_value() const noexcept ; R
+
+    explicit operator bool() const noexcept ; R
+
+    bool operator!() const noexcept ; R
+
+    void reset() noexcept ; R
+
+    // deprecated methods
+
+    // (deprecated)
+    void reset ( T const& ) ; R
+
+    // (deprecated)
+    bool is_initialized() const ; R
+
+    // (deprecated)
+    T const& get_value_or( T const& default ) const ; R
+};
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/io_header.html b/libs/optional/doc/html/boost_optional/reference/io_header.html new file mode 100644 index 00000000..9b33523a --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/io_header.html @@ -0,0 +1,72 @@ + + + +Header <boost/optional/optional_io.hpp> + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ +

+

+
#include <istream>
+#include <ostream>
+#include <boost/optional/optional.hpp>
+
+namespace boost {
+
+template <class CharType, class CharTrait, class T>
+  std::basic_ostream<CharType, CharTrait>&
+  operator<<(std::basic_ostream<CharType, CharTrait>& out, optional<T> const& v); R
+
+  template <class CharType, class CharTrait>
+  std::basic_ostream<CharType, CharTrait>&
+  operator<<(std::basic_ostream<CharType, CharTrait>& out, none_t const&); R
+
+template<class CharType, class CharTrait, class T>
+  std::basic_istream<CharType, CharTrait>&
+  operator>>(std::basic_istream<CharType, CharTrait>& in, optional<T>& v); R
+
+} // namespace boost
+
+

+

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/io_header/io_semantics.html b/libs/optional/doc/html/boost_optional/reference/io_header/io_semantics.html new file mode 100644 index 00000000..f74ff4ac --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/io_header/io_semantics.html @@ -0,0 +1,112 @@ + + + +Detailed semantics + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ template + <class + CharType, + class CharTrait, class T> +
    std::basic_ostream<CharType, CharTrait>&
    operator<<(std::basic_ostream<CharType, CharTrait>& + out, + optional<T> const& v); +

+
    +
  • + Effect: Outputs an implementation-defined + string. The output contains the information about whether the optional + object contains a value or not. If v + contains a value, the output contains result of calling out << + *v. +
  • +
  • + Returns: out. +
  • +
+

+ space +

+

+ template <class CharType, class CharTrait, + class T>
    std::basic_ostream<CharType, CharTrait>& +
    operator<<(std::basic_ostream<CharType, CharTrait>& out, none_t); +

+
    +
  • + Effect: Outputs an implementation-defined + string. +
  • +
  • + Returns: out. +
  • +
+

+ space +

+

+ template <class CharType, class CharTrait, + class T>
    std::basic_ostream<CharType, CharTrait>& +
    operator>>(std::basic_istream<CharType, CharTrait>& in, optional<T>& v); +

+
    +
  • + Requires: T + is DefaultConstructible and + MoveConstructible. +
  • +
  • + Effect: Reads the value of optional + object from in. If + the string representation indicates that the optional object should + contain a value, v + contains a value and its contained value is obtained as if by default-constructing + an object o of type + T and then calling + in >> + o; otherwise v does not contain a value, and the + previously contained value (if any) has been destroyed. +
  • +
  • + Returns: out. +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/reference/relnotes.html b/libs/optional/doc/html/boost_optional/reference/relnotes.html new file mode 100644 index 00000000..c67535ea --- /dev/null +++ b/libs/optional/doc/html/boost_optional/reference/relnotes.html @@ -0,0 +1,183 @@ + + + +Release Notes + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ + Boost Release + X.XX +
+
  • + Now boost::optional is specialized for reference + parameters. This way the sizeof + of optional reference is that of a pointer, and a number of bugs is avoided. +
+
+ + Boost Release + 1.60 +
+
  • + Changed the implementation of boost::none + again. Now it is a const object with internal linkage (as any other tag). + This fixes Trac + #11203. +
+
+ + Boost Release + 1.59 +
+
    +
  • + For C++03 compilers, added 0-argument overload for member function emplace(), + and therewith removed the dependency on <boost/utility/in_place_factory.hpp>. +
  • +
  • + Fixed Trac + #11241. +
  • +
+
+ + Boost Release + 1.58 +
+
    +
  • + boost::none_t is no longer convertible from + literal 0. This avoids a + bug where optional<rational<int>> + oi = + 0; + would initialize an optional object with no contained value. +
  • +
  • + Improved the trick that prevents streaming out optional + without header optional_io.hpp + by using safe-bool idiom. This addresses Trac + #10825. +
  • +
  • + IOStream operators are now mentioned in documentation. +
  • +
  • + Added a way to manually disable move semantics: just define macro BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES. + This can be used to work around Trac + #10399. +
  • +
  • + It is no longer possible to assign optional<U> to optional<T> when U + is not assignable or convertible to T + (Trac #11087). +
  • +
  • + Value accessors now work correctly on rvalues of optional<T&> (Trac + #10839). +
  • +
+
+ + Boost Release + 1.57 +
+
  • + Git pull #9: + "Supply <string> + to fix C++03 compile error on logic_error("...")". +
+
+ + Boost Release + 1.56 +
+
    +
  • + Added support for rvalue references. Now optional<T> works with moveable but non-copyable + T's, +
  • +
  • + Improved swap (now uses + move operations), +
  • +
  • + Added function emplace(). This is the last of the requests from + Trac #1841, +
  • +
  • + optional is moveable, + including conditional noexcept + specifications, which make it move_if_noexcept-friendly, +
  • +
  • + Using explicit operator bool() on platforms that support it (Trac + #4227) (breaking change), +
  • +
  • + Forward declaration of operator<<(ostream&, optional + const&) + to prevent inadvertent incorrect serialization of optional objects, +
  • +
  • + Removed deprecated function reset() from examples (Trac + #9005), +
  • +
  • + Equality comparison with boost::none + does not require that T + be EqualityComparable, +
  • +
  • + Optional rvalue references are explicitly disallowed, +
  • +
  • + Binding temporaries to optional references is explicitly disallowed (breaking + change), +
  • +
  • + More ways to access the contained value, functions value(), value_or(), value_or_eval(), +
  • +
  • + Updated and reorganized documentation, added tutorial and quick guide + sections. +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/relnotes.html b/libs/optional/doc/html/boost_optional/relnotes.html new file mode 100644 index 00000000..ae833827 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/relnotes.html @@ -0,0 +1,384 @@ + + + +Release Notes + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ + Boost + Release 1.79 +

+
    +
  • + Fixed issue + #98. +
  • +
  • + Fixed issue + #92. +
  • +
  • + Added support for BOOST_NO_IOSTREAM. +
  • +
  • + Now aligned storage uses unsigned + char rather than char + to avoid UB. +
  • +
  • + Now using cv-unqualified value_type + with placement new to avoid + UB. +
  • +
+

+ + Boost + Release 1.76 +

+
  • + Fixed MSVC warning C4702. +
+

+ + Boost + Release 1.75 +

+
    +
  • + boost::none is constexpr-declared. +
  • +
  • + Fixed issue + #78. +
  • +
+

+ + Boost + Release 1.73 +

+
    +
  • + Fixed issue + #78. +
  • +
  • + boost::none is now declared as an inline variable + (on compilers that support it): there is only one instance of boost::none across all translation units. +
  • +
  • + Fixed a number of compilation errors in GCC 4.4.7 in optional<T> for trivial Ts. + Thanks to Robert Leahy for the fix. For details see pr + #78. +
  • +
  • + Now suppressing warning -Wweak-vtables. +
  • +
+

+ + Boost + Release 1.69 +

+
    +
  • + Remove deprecation mark from reset() method (without arguments). +
  • +
  • + Fixed issue + #59. +
  • +
  • + Fixed bug with initialization of certain wrapper types in clang with -std=c++03. + See pr #64. +
  • +
+

+ + Boost + Release 1.68 +

+
    +
  • + Added member function has_value() for compatibility with std::optional (issue + #52). +
  • +
  • + Added member function map() for transforming optional<T> into optional<U> using a function of type T -> U. +
  • +
  • + Added member function flat_map() for transforming optional<T> into optional<U> using a function of type T -> optional<U>. +
  • +
+

+ + Boost + Release 1.67 +

+
    +
  • + Fixed issue + #46. +
  • +
  • + Fixed -Wzero-as-null-pointer-constant warnings. +
  • +
+

+ + Boost + Release 1.66 +

+
    +
  • + On newer compilers optional + is now trivially-copyable for scalar Ts. + This uses a different storage (just T + rather than aligned_storage). + We require the compiler to support defaulted functions. +
  • +
  • + Changed the implementation of operator== to get rid of the -Wmaybe-uninitialized false-positive warning + from GCC. +
  • +
+

+ + Boost + Release 1.63 +

+
    +
  • + Added two new in-place constructors. They work similarly to emplace() + functions: they initialize the contained value by perfect-forwarding the + obtained arguments. One constructor always initializes the contained value, + the other based on a boolean condition. +
  • +
  • + Syntax o = + {} now correctly un-initializes + optional, just like in std::optional. +
  • +
  • + Fixed Trac #12203. +
  • +
  • + Fixed Trac #12563. +
  • +
+

+ + Boost + Release 1.62 +

+
+

+ + Boost + Release 1.61 +

+
    +
  • + Now boost::optional is specialized for reference + parameters. This addresses a couple of issues: +
      +
    • + the sizeof of optional + reference is that of a pointer, +
    • +
    • + some bugs connected to copying optional references are gone, +
    • +
    • + all run-time bugs caused by incorrect reference binding on some compilers + are now turned into compile-time errors, +
    • +
    • + you can swap optional references: it is like swapping pointers: shallow, + underlying objects are not affected, +
    • +
    • + optional references to abstract types work. +
    • +
    +
  • +
  • + Documented nested typedefs (Trac + #5193). +
  • +
  • + Made the perfect-forwarding constructor SFINAE-friendly, which fixes Trac #12002. + However, this only works in the newer platforms that correctly implement + C++11 <type_traits>. +
  • +
  • + Fixed Trac #10445. +
  • +
+

+ + Boost + Release 1.60 +

+
  • + Changed the implementation of boost::none + again. Now it is a const object with internal linkage (as any other tag). + This fixes Trac + #11203. +
+

+ + Boost + Release 1.59 +

+
    +
  • + For C++03 compilers, added 0-argument overload for member function emplace(), + and therewith removed the dependency on <boost/utility/in_place_factory.hpp>. +
  • +
  • + Fixed Trac #11241. +
  • +
+

+ + Boost + Release 1.58 +

+
    +
  • + boost::none_t is no longer convertible from + literal 0. This avoids a bug + where optional<rational<int>> oi = 0; would + initialize an optional object with no contained value. +
  • +
  • + Improved the trick that prevents streaming out optional + without header optional_io.hpp + by using safe-bool idiom. This addresses Trac + #10825. +
  • +
  • + IOStream operators are now mentioned in documentation. +
  • +
  • + Added a way to manually disable move semantics: just define macro BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES. + This can be used to work around Trac + #10399. +
  • +
  • + It is no longer possible to assign optional<U> to optional<T> when U + is not assignable or convertible to T + (Trac #11087). +
  • +
  • + Value accessors now work correctly on rvalues of optional<T&> (Trac + #10839). +
  • +
+

+ + Boost + Release 1.57 +

+
  • + Git pull #9: + "Supply <string> + to fix C++03 compile error on logic_error("...")". +
+

+ + Boost + Release 1.56 +

+
    +
  • + Added support for rvalue references. Now optional<T> works with moveable but non-copyable + T's, +
  • +
  • + Improved swap (now uses + move operations), +
  • +
  • + Added function emplace(). This is the last of the requests from + Trac #1841, +
  • +
  • + optional is moveable, including + conditional noexcept specifications, + which make it move_if_noexcept-friendly, +
  • +
  • + Using explicit operator bool() on platforms that support it (Trac + #4227) (breaking change), +
  • +
  • + Forward declaration of operator<<(ostream&, optional + const&) + to prevent inadvertent incorrect serialization of optional objects, +
  • +
  • + Removed deprecated function reset() from examples (Trac + #9005), +
  • +
  • + Equality comparison with boost::none + does not require that T + be EqualityComparable, +
  • +
  • + Optional rvalue references are explicitly disallowed, +
  • +
  • + Binding temporaries to optional references is explicitly disallowed (breaking + change), +
  • +
  • + More ways to access the contained value, functions value(), value_or(), value_or_eval(), +
  • +
  • + Updated and reorganized documentation, added tutorial and quick guide sections. +
  • +
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/synopsis.html b/libs/optional/doc/html/boost_optional/synopsis.html new file mode 100644 index 00000000..0de90e79 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/synopsis.html @@ -0,0 +1,174 @@ + + + +Synopsis + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
// In Header: <boost/optional/optional.hpp>
+
+namespace boost {
+
+template<class T>
+class optional
+{
+    public :
+
+    // (If T is of reference type, the parameters and results by reference are by value)
+
+    optional () noexcept ; R
+
+    optional ( none_t ) noexcept ; R
+
+    optional ( T const& v ) ; R
+
+    optional ( T&& v ) ; R
+
+    // [new in 1.34]
+    optional ( bool condition, T const& v ) ; R
+
+    optional ( optional const& rhs ) ; R
+
+    optional ( optional&& rhs ) noexcept(see below) ; R
+
+    template<class U> explicit optional ( optional<U> const& rhs ) ; R
+
+    template<class U> explicit optional ( optional<U>&& rhs ) ; R
+
+    template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ; R
+
+    template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ; R
+
+    optional& operator = ( none_t ) noexcept ; R
+
+    optional& operator = ( T const& v ) ; R
+
+    optional& operator = ( T&& v ) ; R
+
+    optional& operator = ( optional const& rhs ) ; R
+
+    optional& operator = ( optional&& rhs ) noexcept(see below) ; R
+
+    template<class U> optional& operator = ( optional<U> const& rhs ) ; R
+
+    template<class U> optional& operator = ( optional<U>&& rhs ) ; R
+
+    template<class... Args> void emplace ( Args...&& args ) ; R
+
+    template<class InPlaceFactory> optional& operator = ( InPlaceFactory const& f ) ; R
+
+    template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ; R
+
+    T const& get() const ; R
+    T&       get() ; R
+
+    T const* operator ->() const ; R
+    T*       operator ->() ; R
+
+    T const& operator *() const& ; R
+    T&       operator *() &; R
+    T&&      operator *() &&; R
+
+    T const& value() const& ; R
+    T&       value() & ; R
+    T&&      value() && ; R
+
+    template<class U> T value_or( U && v ) const& ; R
+    template<class U> T value_or( U && v ) && ; R
+
+    T const* get_ptr() const ; R
+    T*       get_ptr() ; R
+
+    explicit operator bool() const ; R
+
+    bool operator!() const noexcept ; R
+
+    // deprecated methods
+
+    // (deprecated)
+    void reset() noexcept ; R
+
+    // (deprecated)
+    void reset ( T const& ) ; R
+
+    // (deprecated)
+    bool is_initialized() const ; R
+
+    // (deprecated)
+    T const& get_value_or( T const& default ) const ; R
+};
+
+template<class T> inline bool operator == ( optional<T> const& x, optional<T> const& y ) ; R
+
+template<class T> inline bool operator != ( optional<T> const& x, optional<T> const& y ) ; R
+
+template<class T> inline bool operator <  ( optional<T> const& x, optional<T> const& y ) ; R
+
+template<class T> inline bool operator >  ( optional<T> const& x, optional<T> const& y ) ; R
+
+template<class T> inline bool operator <= ( optional<T> const& x, optional<T> const& y ) ; R
+
+template<class T> inline bool operator >= ( optional<T> const& x, optional<T> const& y ) ; R
+
+template<class T> inline bool operator == ( optional<T> const& x, none_t ) noexcept ; R
+
+template<class T> inline bool operator != ( optional<T> const& x, none_t ) noexcept ; R
+
+template<class T> inline optional<T> make_optional ( T const& v ) ; R
+
+template<class T> inline optional<T> make_optional ( bool condition, T const& v ) ; R
+
+template<class T> inline T const& get_optional_value_or ( optional<T> const& opt, T const& default ) ; R
+
+template<class T> inline T const& get ( optional<T> const& opt ) ; R
+
+template<class T> inline T& get ( optional<T> & opt ) ; R
+
+template<class T> inline T const* get ( optional<T> const* opt ) ; R
+
+template<class T> inline T* get ( optional<T>* opt ) ; R
+
+template<class T> inline T const* get_pointer ( optional<T> const& opt ) ; R
+
+template<class T> inline T* get_pointer ( optional<T> & opt ) ; R
+
+template<class T> inline void swap( optional<T>& x, optional<T>& y ) ; R
+
+} // namespace boost
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial.html b/libs/optional/doc/html/boost_optional/tutorial.html new file mode 100644 index 00000000..9cee12a2 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial.html @@ -0,0 +1,523 @@ + + + +Tutorial + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Consider these functions which should return a value but which might not + have a value to return: +

+
    +
  • + (A) double sqrt(double n ); +
  • +
  • + (B) char get_async_input(); +
  • +
  • + (C) point polygon::get_any_point_effectively_inside(); +
  • +
+

+ There are different approaches to the issue of not having a value to return. +

+

+ A typical approach is to consider the existence of a valid return value as + a postcondition, so that if the function cannot compute the value to return, + it has either undefined behavior (and can use assert in a debug build) or + uses a runtime check and throws an exception if the postcondition is violated. + This is a reasonable choice for example, for function (A), because the lack + of a proper return value is directly related to an invalid parameter (out + of domain argument), so it is appropriate to require the callee to supply + only parameters in a valid domain for execution to continue normally. +

+

+ However, function (B), because of its asynchronous nature, does not fail + just because it can't find a value to return; so it is incorrect to consider + such a situation an error and assert or throw an exception. This function + must return, and somehow, must tell the callee that it is not returning a + meaningful value. +

+

+ A similar situation occurs with function (C): it is conceptually an error + to ask a null-area polygon to return a point inside + itself, but in many applications, it is just impractical for performance + reasons to treat this as an error (because detecting that the polygon has + no area might be too expensive to be required to be tested previously), and + either an arbitrary point (typically at infinity) is returned, or some efficient + way to tell the callee that there is no such point is used. +

+

+ There are various mechanisms to let functions communicate that the returned + value is not valid. One such mechanism, which is quite common since it has + zero or negligible overhead, is to use a special value which is reserved + to communicate this. Classical examples of such special values are EOF, string::npos, + points at infinity, etc... +

+

+ When those values exist, i.e. the return type can hold all meaningful values + plus the signal value, this mechanism + is quite appropriate and well known. Unfortunately, there are cases when + such values do not exist. In these cases, the usual alternative is either + to use a wider type, such as int + in place of char; or a compound + type, such as std::pair<point,bool>. +

+

+ Returning a std::pair<T,bool>, thus attaching a boolean flag to the + result which indicates if the result is meaningful, has the advantage that + can be turned into a consistent idiom since the first element of the pair + can be whatever the function would conceptually return. For example, the + last two functions could have the following interface: +

+
std::pair<char,bool> get_async_input();
+std::pair<point,bool> polygon::get_any_point_effectively_inside();
+
+

+ These functions use a consistent interface for dealing with possibly nonexistent + results: +

+
std::pair<point,bool> p = poly.get_any_point_effectively_inside();
+if ( p.second )
+    flood_fill(p.first);
+
+

+ However, not only is this quite a burden syntactically, it is also error + prone since the user can easily use the function result (first element of + the pair) without ever checking if it has a valid value. +

+

+ Clearly, we need a better idiom. +

+
+
+ + +
+ +

+ In C++, we can declare an object (a variable) of type + T, and we can give this + variable an initial value (through an initializer. + (cf. 8.5)). When a declaration includes a non-empty initializer (an initial + value is given), it is said that the object has been initialized. If the + declaration uses an empty initializer (no initial value is given), and + neither default nor value initialization applies, it is said that the object + is uninitialized. Its actual value exist + but has an indeterminate initial value (cf. 8.5/11). + optional<T> + intends to formalize the notion of initialization (or lack of it) allowing + a program to test whether an object has been initialized and stating that + access to the value of an uninitialized object is undefined behavior. That + is, when a variable is declared as optional<T> and no initial value is given, the + variable is formally uninitialized. A formally uninitialized + optional object has conceptually no value at all and this situation can + be tested at runtime. It is formally undefined behavior + to try to access the value of an uninitialized optional. An uninitialized + optional can be assigned a value, in which case its initialization state + changes to initialized. Furthermore, given the formal treatment of initialization + states in optional objects, it is even possible to reset an optional to + uninitialized. +

+

+ In C++ there is no formal notion of uninitialized objects, which means + that objects always have an initial value even if indeterminate. As discussed + on the previous section, this has a drawback because you need additional + information to tell if an object has been effectively initialized. One + of the typical ways in which this has been historically dealt with is via + a special value: EOF, + npos, -1, etc... This is + equivalent to adding the special value to the set of possible values of + a given type. This super set of T + plus some nil_t—where nil_t + is some stateless POD—can be modeled in modern languages as a discriminated union of T and nil_t. Discriminated + unions are often called variants. A variant has a + current type, which in our case is either T or nil_t. + Using the Boost.Variant + library, this model can be implemented in terms of boost::variant<T,nil_t>. There is precedent for a discriminated + union as a model for an optional value: the Haskell + Maybe built-in type constructor. Thus, + a discriminated union T+nil_t + serves as a conceptual foundation. +

+

+ A variant<T,nil_t> follows naturally from the traditional + idiom of extending the range of possible values adding an additional sentinel + value with the special meaning of Nothing. However, + this additional Nothing value is largely irrelevant + for our purpose since our goal is to formalize the notion of uninitialized + objects and, while a special extended value can be used to convey that + meaning, it is not strictly necessary in order to do so. +

+

+ The observation made in the last paragraph about the irrelevant nature + of the additional nil_t + with respect to purpose of optional<T> + suggests an alternative model: a container that either + has a value of T or nothing. +

+

+ As of this writing I don't know of any precedent for a variable-size fixed-capacity + (of 1) stack-based container model for optional values, yet I believe this + is the consequence of the lack of practical implementations of such a container + rather than an inherent shortcoming of the container model. +

+

+ In any event, both the discriminated-union or the single-element container + models serve as a conceptual ground for a class representing optional—i.e. + possibly uninitialized—objects. For instance, these models show the + exact semantics required for a wrapper of optional + values: +

+

+ Discriminated-union: +

+
    +
  • + deep-copy semantics: copies of the + variant implies copies of the value. +
  • +
  • + deep-relational semantics: comparisons + between variants matches both current types and values +
  • +
  • + If the variant's current type is T, + it is modeling an initialized optional. +
  • +
  • + If the variant's current type is not T, + it is modeling an uninitialized optional. +
  • +
  • + Testing if the variant's current type is T + models testing if the optional is initialized +
  • +
  • + Trying to extract a T + from a variant when its current type is not T, + models the undefined behavior of trying to access the value of an uninitialized + optional +
  • +
+

+ Single-element container: +

+
    +
  • + deep-copy semantics: copies of the + container implies copies of the value. +
  • +
  • + deep-relational semantics: comparisons + between containers compare container size and if match, contained value +
  • +
  • + If the container is not empty (contains an object of type T), it is modeling an initialized + optional. +
  • +
  • + If the container is empty, it is modeling an uninitialized + optional. +
  • +
  • + Testing if the container is empty models testing if the optional is + initialized +
  • +
  • + Trying to extract a T + from an empty container models the undefined behavior of trying to + access the value of an uninitialized optional +
  • +
+
+
+ +

+ Objects of type optional<T> are intended to be used in places where + objects of type T would + but which might be uninitialized. Hence, optional<T>'s purpose is to formalize the additional + possibly uninitialized state. From the perspective of this role, optional<T> + can have the same operational semantics of T + plus the additional semantics corresponding to this special state. As such, + optional<T> + could be thought of as a supertype of T. Of course, we can't do that in C++, + so we need to compose the desired semantics using a different mechanism. + Doing it the other way around, that is, making optional<T> a subtype of + T is not only conceptually + wrong but also impractical: it is not allowed to derive from a non-class + type, such as a built-in type. +

+

+ We can draw from the purpose of optional<T> the required basic semantics: +

+
    +
  • + Default Construction: To introduce + a formally uninitialized wrapped object. +
  • +
  • + Direct Value Construction via copy: + To introduce a formally initialized wrapped object whose value is obtained + as a copy of some object. +
  • +
  • + Deep Copy Construction: To obtain + a new yet equivalent wrapped object. +
  • +
  • + Direct Value Assignment (upon initialized): + To assign a value to the wrapped object. +
  • +
  • + Direct Value Assignment (upon uninitialized): + To initialize the wrapped object with a value obtained as a copy of + some object. +
  • +
  • + Assignment (upon initialized): To + assign to the wrapped object the value of another wrapped object. +
  • +
  • + Assignment (upon uninitialized): To + initialize the wrapped object with value of another wrapped object. +
  • +
  • + Deep Relational Operations (when supported by + the type T): To compare wrapped object values taking into + account the presence of uninitialized states. +
  • +
  • + Value access: To unwrap the wrapped + object. +
  • +
  • + Initialization state query: To determine + if the object is formally initialized or not. +
  • +
  • + Swap: To exchange wrapped objects. + (with whatever exception safety guarantees are provided by T's swap). +
  • +
  • + De-initialization: To release the + wrapped object (if any) and leave the wrapper in the uninitialized + state. +
  • +
+

+ Additional operations are useful, such as converting constructors and converting + assignments, in-place construction and assignment, and safe value access + via a pointer to the wrapped object or null. +

+
+
+ +

+ Since the purpose of optional is to allow us to use objects with a formal + uninitialized additional state, the interface could try to follow the interface + of the underlying T type + as much as possible. In order to choose the proper degree of adoption of + the native T interface, + the following must be noted: Even if all the operations supported by an + instance of type T are + defined for the entire range of values for such a type, an optional<T> + extends such a set of values with a new value for which most (otherwise + valid) operations are not defined in terms of T. +

+

+ Furthermore, since optional<T> itself is merely a T + wrapper (modeling a T supertype), + any attempt to define such operations upon uninitialized optionals will + be totally artificial w.r.t. T. +

+

+ This library chooses an interface which follows from T's + interface only for those operations which are well defined (w.r.t the type + T) even if any of the operands + are uninitialized. These operations include: construction, copy-construction, + assignment, swap and relational operations. +

+

+ For the value access operations, which are undefined (w.r.t the type T) when the operand is uninitialized, + a different interface is chosen (which will be explained next). +

+

+ Also, the presence of the possibly uninitialized state requires additional + operations not provided by T + itself which are supported by a special interface. +

+
+ + Lexically-hinted + Value Access in the presence of possibly uninitialized optional objects: + The operators * and -> +
+

+ A relevant feature of a pointer is that it can have a null + pointer value. This is a special value + which is used to indicate that the pointer is not referring to any object + at all. In other words, null pointer values convey the notion of nonexistent + objects. +

+

+ This meaning of the null pointer value allowed pointers to became a de + facto standard for handling optional objects because all you + have to do to refer to a value which you don't really have is to use a + null pointer value of the appropriate type. Pointers have been used for + decades—from the days of C APIs to modern C++ libraries—to refer + to optional (that is, possibly nonexistent) objects; particularly as optional + arguments to a function, but also quite often as optional data members. +

+

+ The possible presence of a null pointer value makes the operations that + access the pointee's value possibly undefined, therefore, expressions which + use dereference and access operators, such as: ( + *p + = 2 ) and ( + p->foo() ), implicitly convey the notion of optionality, + and this information is tied to the syntax of the + expressions. That is, the presence of operators * + and -> tell by themselves + —without any additional context— that the expression will be undefined + unless the implied pointee actually exist. +

+

+ Such a de facto idiom for referring to optional objects + can be formalized in the form of a concept: the OptionalPointee + concept. This concept captures the syntactic usage of operators *, -> + and contextual conversion to bool + to convey the notion of optionality. +

+

+ However, pointers are good to refer + to optional objects, but not particularly good to handle the optional objects + in all other respects, such as initializing or moving/copying them. The + problem resides in the shallow-copy of pointer semantics: if you need to + effectively move or copy the object, pointers alone are not enough. The + problem is that copies of pointers do not imply copies of pointees. For + example, as was discussed in the motivation, pointers alone cannot be used + to return optional objects from a function because the object must move + outside from the function and into the caller's context. +

+

+ A solution to the shallow-copy problem that is often used is to resort + to dynamic allocation and use a smart pointer to automatically handle the + details of this. For example, if a function is to optionally return an + object X, it can use shared_ptr<X> + as the return value. However, this requires dynamic allocation of X. If X + is a built-in or small POD, this technique is very poor in terms of required + resources. Optional objects are essentially values so it is very convenient + to be able to use automatic storage and deep-copy semantics to manipulate + optional values just as we do with ordinary values. Pointers do not have + this semantics, so are inappropriate for the initialization and transport + of optional values, yet are quite convenient for handling the access to + the possible undefined value because of the idiomatic aid present in the + OptionalPointee + concept incarnated by pointers. +

+
+ + Optional<T> + as a model of OptionalPointee +
+

+ For value access operations optional<> uses operators * + and -> to lexically warn + about the possibly uninitialized state appealing to the familiar pointer + semantics w.r.t. to null pointers. +

+
+ + + + + +
[Warning]Warning

+ However, it is particularly important to note that optional<> objects are not pointers. optional<> is not, and does not model, a + pointer. +

+

+ For instance, optional<> does not have shallow-copy so does + not alias: two different optionals never refer to the same + value unless T itself is + a reference (but may have equivalent values). The + difference between an optional<T> and a pointer must be kept in mind, + particularly because the semantics of relational operators are different: + since optional<T> + is a value-wrapper, relational operators are deep: they compare optional + values; but relational operators for pointers are shallow: they do not + compare pointee values. As a result, you might be able to replace optional<T> + by T* + on some situations but not always. Specifically, on generic code written + for both, you cannot use relational operators directly, and must use the + template functions equal_pointees() + and less_pointees() + instead. +

+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/a_note_about_optional_bool_.html b/libs/optional/doc/html/boost_optional/tutorial/a_note_about_optional_bool_.html new file mode 100644 index 00000000..ffd5c3dc --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/a_note_about_optional_bool_.html @@ -0,0 +1,108 @@ + + + +A note about optional<bool> + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ optional<bool> should + be used with special caution and consideration. +

+

+ First, it is functionally similar to a tristate boolean (false, maybe, true) + —such as boost::tribool— + except that in a tristate boolean, the maybe state represents + a valid value, unlike the corresponding state of an uninitialized + optional<bool>. + It should be carefully considered if an optional<bool> + instead of a tribool is really + needed. +

+

+ Second, although optional<> provides a contextual conversion + to bool in C++11, this falls + back to an implicit conversion on older compilers. This conversion refers + to the initialization state and not to the contained value. Using optional<bool> can + lead to subtle errors due to the implicit bool + conversion: +

+
void foo ( bool v ) ;
+void bar()
+{
+    optional<bool> v = try();
+
+    // The following intended to pass the value of 'v' to foo():
+    foo(v);
+    // But instead, the initialization state is passed
+    // due to a typo: it should have been foo(*v).
+}
+
+

+ The only implicit conversion is to bool, + and it is safe in the sense that typical integral promotions don't apply + (i.e. if foo() + takes an int instead, it won't + compile). +

+

+ Third, mixed comparisons with bool + work differently than similar mixed comparisons between pointers and bool, so the results might surprise you: +

+
optional<bool> oEmpty(none), oTrue(true), oFalse(false);
+
+if (oEmpty == none);  // renders true
+if (oEmpty == false); // renders false!
+if (oEmpty == true);  // renders false!
+
+if (oFalse == none);  // renders false
+if (oFalse == false); // renders true!
+if (oFalse == true);  // renders false
+
+if (oTrue == none);   // renders false
+if (oTrue == false);  // renders false
+if (oTrue == true);   // renders true
+
+

+ In other words, for optional<>, the following assertion does not + hold: +

+
assert((opt == false) == (!opt));
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/design_overview.html b/libs/optional/doc/html/boost_optional/tutorial/design_overview.html new file mode 100644 index 00000000..c467658c --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/design_overview.html @@ -0,0 +1,184 @@ + + + +Design Overview + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ +

+ In C++, we can declare an object (a variable) of type + T, and we can give this + variable an initial value (through an initializer. + (cf. 8.5)). When a declaration includes a non-empty initializer (an initial + value is given), it is said that the object has been initialized. If the + declaration uses an empty initializer (no initial value is given), and + neither default nor value initialization applies, it is said that the object + is uninitialized. Its actual value exist + but has an indeterminate initial value (cf. 8.5/11). + optional<T> + intends to formalize the notion of initialization (or lack of it) allowing + a program to test whether an object has been initialized and stating that + access to the value of an uninitialized object is undefined behavior. That + is, when a variable is declared as optional<T> and no initial value is given, the + variable is formally uninitialized. A formally uninitialized + optional object has conceptually no value at all and this situation can + be tested at runtime. It is formally undefined behavior + to try to access the value of an uninitialized optional. An uninitialized + optional can be assigned a value, in which case its initialization state + changes to initialized. Furthermore, given the formal treatment of initialization + states in optional objects, it is even possible to reset an optional to + uninitialized. +

+

+ In C++ there is no formal notion of uninitialized objects, which means + that objects always have an initial value even if indeterminate. As discussed + on the previous section, this has a drawback because you need additional + information to tell if an object has been effectively initialized. One + of the typical ways in which this has been historically dealt with is via + a special value: EOF, + npos, -1, etc... This is + equivalent to adding the special value to the set of possible values of + a given type. This super set of T + plus some nil_t—where nil_t + is some stateless POD—can be modeled in modern languages as a discriminated union of T and nil_t. Discriminated + unions are often called variants. A variant has a + current type, which in our case is either T or nil_t. + Using the Boost.Variant + library, this model can be implemented in terms of boost::variant<T,nil_t>. There is precedent for a discriminated + union as a model for an optional value: the Haskell + Maybe built-in type constructor. Thus, + a discriminated union T+nil_t + serves as a conceptual foundation. +

+

+ A variant<T,nil_t> follows naturally from the traditional + idiom of extending the range of possible values adding an additional sentinel + value with the special meaning of Nothing. However, + this additional Nothing value is largely irrelevant + for our purpose since our goal is to formalize the notion of uninitialized + objects and, while a special extended value can be used to convey that + meaning, it is not strictly necessary in order to do so. +

+

+ The observation made in the last paragraph about the irrelevant nature + of the additional nil_t + with respect to purpose of optional<T> + suggests an alternative model: a container that either + has a value of T or nothing. +

+

+ As of this writing I don't know of any precedent for a variable-size fixed-capacity + (of 1) stack-based container model for optional values, yet I believe this + is the consequence of the lack of practical implementations of such a container + rather than an inherent shortcoming of the container model. +

+

+ In any event, both the discriminated-union or the single-element container + models serve as a conceptual ground for a class representing optional—i.e. + possibly uninitialized—objects. For instance, these models show the + exact semantics required for a wrapper of optional + values: +

+

+ Discriminated-union: +

+
    +
  • + deep-copy semantics: copies of the + variant implies copies of the value. +
  • +
  • + deep-relational semantics: comparisons + between variants matches both current types and values +
  • +
  • + If the variant's current type is T, + it is modeling an initialized optional. +
  • +
  • + If the variant's current type is not T, + it is modeling an uninitialized optional. +
  • +
  • + Testing if the variant's current type is T + models testing if the optional is initialized +
  • +
  • + Trying to extract a T + from a variant when its current type is not T, + models the undefined behavior of trying to access the value of an uninitialized + optional +
  • +
+

+ Single-element container: +

+
    +
  • + deep-copy semantics: copies of the + container implies copies of the value. +
  • +
  • + deep-relational semantics: comparisons + between containers compare container size and if match, contained value +
  • +
  • + If the container is not empty (contains an object of type T), it is modeling an initialized + optional. +
  • +
  • + If the container is empty, it is modeling an uninitialized + optional. +
  • +
  • + Testing if the container is empty models testing if the optional is + initialized +
  • +
  • + Trying to extract a T + from an empty container models the undefined behavior of trying to + access the value of an uninitialized optional +
  • +
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/design_overview/the_interface.html b/libs/optional/doc/html/boost_optional/tutorial/design_overview/the_interface.html new file mode 100644 index 00000000..f0bbc860 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/design_overview/the_interface.html @@ -0,0 +1,187 @@ + + + +The Interface + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Since the purpose of optional is to allow us to use objects with a formal + uninitialized additional state, the interface could try to follow the interface + of the underlying T type + as much as possible. In order to choose the proper degree of adoption of + the native T interface, + the following must be noted: Even if all the operations supported by an + instance of type T are + defined for the entire range of values for such a type, an optional<T> + extends such a set of values with a new value for which most (otherwise + valid) operations are not defined in terms of T. +

+

+ Furthermore, since optional<T> itself is merely a T + wrapper (modeling a T supertype), + any attempt to define such operations upon uninitialized optionals will + be totally artificial w.r.t. T. +

+

+ This library chooses an interface which follows from T's + interface only for those operations which are well defined (w.r.t the type + T) even if any of the operands + are uninitialized. These operations include: construction, copy-construction, + assignment, swap and relational operations. +

+

+ For the value access operations, which are undefined (w.r.t the type T) when the operand is uninitialized, + a different interface is chosen (which will be explained next). +

+

+ Also, the presence of the possibly uninitialized state requires additional + operations not provided by T + itself which are supported by a special interface. +

+
+ + Lexically-hinted + Value Access in the presence of possibly uninitialized optional objects: + The operators * and -> +
+

+ A relevant feature of a pointer is that it can have a null + pointer value. This is a special value + which is used to indicate that the pointer is not referring to any object + at all. In other words, null pointer values convey the notion of nonexistent + objects. +

+

+ This meaning of the null pointer value allowed pointers to became a de + facto standard for handling optional objects because all you + have to do to refer to a value which you don't really have is to use a + null pointer value of the appropriate type. Pointers have been used for + decades—from the days of C APIs to modern C++ libraries—to refer + to optional (that is, possibly nonexistent) objects; particularly as optional + arguments to a function, but also quite often as optional data members. +

+

+ The possible presence of a null pointer value makes the operations that + access the pointee's value possibly undefined, therefore, expressions which + use dereference and access operators, such as: ( + *p + = 2 ) and ( + p->foo() ), implicitly convey the notion of optionality, + and this information is tied to the syntax of the + expressions. That is, the presence of operators * + and -> tell by themselves + —without any additional context— that the expression will be undefined + unless the implied pointee actually exist. +

+

+ Such a de facto idiom for referring to optional objects + can be formalized in the form of a concept: the OptionalPointee concept. This + concept captures the syntactic usage of operators *, + -> and contextual conversion + to bool to convey the notion + of optionality. +

+

+ However, pointers are good to refer + to optional objects, but not particularly good to handle the optional objects + in all other respects, such as initializing or moving/copying them. The + problem resides in the shallow-copy of pointer semantics: if you need to + effectively move or copy the object, pointers alone are not enough. The + problem is that copies of pointers do not imply copies of pointees. For + example, as was discussed in the motivation, pointers alone cannot be used + to return optional objects from a function because the object must move + outside from the function and into the caller's context. +

+

+ A solution to the shallow-copy problem that is often used is to resort + to dynamic allocation and use a smart pointer to automatically handle the + details of this. For example, if a function is to optionally return an + object X, it can use shared_ptr<X> + as the return value. However, this requires dynamic allocation of X. If X + is a built-in or small POD, this technique is very poor in terms of required + resources. Optional objects are essentially values so it is very convenient + to be able to use automatic storage and deep-copy semantics to manipulate + optional values just as we do with ordinary values. Pointers do not have + this semantics, so are inappropriate for the initialization and transport + of optional values, yet are quite convenient for handling the access to + the possible undefined value because of the idiomatic aid present in the + OptionalPointee + concept incarnated by pointers. +

+
+ + Optional<T> + as a model of OptionalPointee +
+

+ For value access operations optional<> uses operators * + and -> to lexically warn + about the possibly uninitialized state appealing to the familiar pointer + semantics w.r.t. to null pointers. +

+
+ + + + + +
[Caution]Caution

+ However, it is particularly important to note that optional<> objects are not pointers. optional<> is not, and does not model, a + pointer. +

+

+ For instance, optional<> does not have shallow-copy so does + not alias: two different optionals never refer to the same + value unless T itself is + a reference (but may have equivalent values). The + difference between an optional<T> and a pointer must be kept in mind, + particularly because the semantics of relational operators are different: + since optional<T> + is a value-wrapper, relational operators are deep: they compare optional + values; but relational operators for pointers are shallow: they do not + compare pointee values. As a result, you might be able to replace optional<T> + by T* + on some situations but not always. Specifically, on generic code written + for both, you cannot use relational operators directly, and must use the + template functions equal_pointees() + and less_pointees() + instead. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/design_overview/the_semantics.html b/libs/optional/doc/html/boost_optional/tutorial/design_overview/the_semantics.html new file mode 100644 index 00000000..58e52267 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/design_overview/the_semantics.html @@ -0,0 +1,121 @@ + + + +The semantics + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Objects of type optional<T> are intended to be used in places where + objects of type T would + but which might be uninitialized. Hence, optional<T>'s purpose is to formalize the additional + possibly uninitialized state. From the perspective of this role, optional<T> + can have the same operational semantics of T + plus the additional semantics corresponding to this special state. As such, + optional<T> + could be thought of as a supertype of T. Of course, we can't do that in C++, + so we need to compose the desired semantics using a different mechanism. + Doing it the other way around, that is, making optional<T> a subtype of + T is not only conceptually + wrong but also impractical: it is not allowed to derive from a non-class + type, such as a built-in type. +

+

+ We can draw from the purpose of optional<T> the required basic semantics: +

+
    +
  • + Default Construction: To introduce + a formally uninitialized wrapped object. +
  • +
  • + Direct Value Construction via copy: + To introduce a formally initialized wrapped object whose value is obtained + as a copy of some object. +
  • +
  • + Deep Copy Construction: To obtain + a new yet equivalent wrapped object. +
  • +
  • + Direct Value Assignment (upon initialized): + To assign a value to the wrapped object. +
  • +
  • + Direct Value Assignment (upon uninitialized): + To initialize the wrapped object with a value obtained as a copy of + some object. +
  • +
  • + Assignment (upon initialized): To + assign to the wrapped object the value of another wrapped object. +
  • +
  • + Assignment (upon uninitialized): To + initialize the wrapped object with value of another wrapped object. +
  • +
  • + Deep Relational Operations (when supported by + the type T): To compare wrapped object values taking into + account the presence of uninitialized states. +
  • +
  • + Value access: To unwrap the wrapped + object. +
  • +
  • + Initialization state query: To determine + if the object is formally initialized or not. +
  • +
  • + Swap: To exchange wrapped objects. + (with whatever exception safety guarantees are provided by T's swap). +
  • +
  • + De-initialization: To release the + wrapped object (if any) and leave the wrapper in the uninitialized + state. +
  • +
+

+ Additional operations are useful, such as converting constructors and converting + assignments, in-place construction and assignment, and safe value access + via a pointer to the wrapped object or null. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/exception_safety_guarantees.html b/libs/optional/doc/html/boost_optional/tutorial/exception_safety_guarantees.html new file mode 100644 index 00000000..90d817cc --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/exception_safety_guarantees.html @@ -0,0 +1,175 @@ + + + +Exception Safety Guarantees + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This library assumes that T's + destructor does not throw exceptions. If it does, the behaviour of many operations + on optional<T> is + undefined. +

+

+ The following mutating operations never throw exceptions: +

+
    +
  • + optional<T>::operator= ( none_t + ) noexcept +
  • +
  • + optional<T>::reset() noexcept +
  • +
+

+ In addition, the following constructors and the destructor never throw exceptions: +

+
    +
  • + optional<T>::optional() + noexcept +
  • +
  • + optional<T>::optional( + none_t ) + noexcept +
  • +
+

+ Regarding the following assignment functions: +

+
    +
  • + optional<T>::operator= ( optional<T> const& ) +
  • +
  • + optional<T>::operator= ( T const& ) +
  • +
  • + template<class U> optional<T>::operator= ( optional<U> const& ) +
  • +
  • + template<class InPlaceFactory> optional<T>::operator= ( InPlaceFactory + const& + ) +
  • +
  • + template<class TypedInPlaceFactory> optional<T>::operator= ( TypedInPlaceFactory + const& + ) +
  • +
  • + optional<T>::reset( T const& ) +
  • +
+

+ They forward calls to the corresponding T's + constructors or assignments (depending on whether the optional object is + initialized or not); so if both T's + constructor and the assignment provide strong exception safety guarantee, + optional<T>'s + assignment also provides strong exception safety guarantee; otherwise we + only get the basic guarantee. Additionally, if both involved T's constructor and the assignment never + throw, optional<T>'s + assignment also never throws. +

+

+ Unless T's constructor or + assignment throws, assignments to optional<T> + do not throw anything else on its own. A throw during assignment never changes + the initialization state of any optional object involved: +

+
optional<T> opt1(val1);
+optional<T> opt2(val2);
+assert(opt1);
+assert(opt2);
+
+try
+{
+  opt1 = opt2; // throws
+}
+catch(...)
+{
+  assert(opt1);
+  assert(opt2);
+}
+
+

+ This also applies to move assignments/constructors. However, move operations + are made no-throw more often. +

+

+ Operation emplace provides + basic exception safety guarantee. If it throws, the optional object becomes + uninitialized regardless of its initial state, and its previous contained + value (if any) is destroyed. It doesn't call any assignment or move/copy + constructor on T. +

+
+ + Swap +
+

+ Unless swap on optional is + customized, its primary implementation forwards calls to T's + swap or move constructor + (depending on the initialization state of the optional objects). Thus, if + both T's swap + and move constructor never throw, swap + on optional<T> never + throws. similarly, if both T's + swap and move constructor + offer strong guarantee, swap + on optional<T> also + offers a strong guarantee. +

+

+ In case swap on optional + is customized, the call to T's + move constructor are replaced with the calls to T's + default constructor followed by swap. + (This is more useful on older compilers that do not support move semantics, + when one wants to achieve stronger exception safety guarantees.) In this + case the exception safety guarantees for swap + are reliant on the guarantees of T's + swap and default constructor +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/gotchas.html b/libs/optional/doc/html/boost_optional/tutorial/gotchas.html new file mode 100644 index 00000000..9382442d --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/gotchas.html @@ -0,0 +1,112 @@ + + + +Gotchas + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ +

+ optional<bool> + should be used with special caution and consideration. +

+

+ First, it is functionally similar to a tristate boolean (false, maybe, + true) —such as boost::tribool— + except that in a tristate boolean, the maybe state represents + a valid value, unlike the corresponding state of an uninitialized + optional<bool>. + It should be carefully considered if an optional<bool> instead of a tribool + is really needed. +

+

+ Second, although optional<> provides a contextual conversion + to bool in C++11, this falls + back to an implicit conversion on older compilers. This conversion refers + to the initialization state and not to the contained value. Using optional<bool> + can lead to subtle errors due to the implicit bool + conversion: +

+
void foo ( bool v ) ;
+void bar()
+{
+    optional<bool> v = try();
+
+    // The following intended to pass the value of 'v' to foo():
+    foo(v);
+    // But instead, the initialization state is passed
+    // due to a typo: it should have been foo(*v).
+}
+
+

+ The only implicit conversion is to bool, + and it is safe in the sense that typical integral promotions don't apply + (i.e. if foo() + takes an int instead, it won't + compile). +

+

+ Third, mixed comparisons with bool + work differently than similar mixed comparisons between pointers and bool, so the results might surprise you: +

+
optional<bool> oEmpty(none), oTrue(true), oFalse(false);
+
+if (oEmpty == none);  // renders true
+if (oEmpty == false); // renders false!
+if (oEmpty == true);  // renders false!
+
+if (oFalse == none);  // renders false
+if (oFalse == false); // renders true!
+if (oFalse == true);  // renders false
+
+if (oTrue == none);   // renders false
+if (oTrue == false);  // renders false
+if (oTrue == true);   // renders true
+
+

+ In other words, for optional<>, the following assertion does not + hold: +

+
assert((opt == false) == (!opt));
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/gotchas/false_positive_with__wmaybe_uninitialized.html b/libs/optional/doc/html/boost_optional/tutorial/gotchas/false_positive_with__wmaybe_uninitialized.html new file mode 100644 index 00000000..0228f2ea --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/gotchas/false_positive_with__wmaybe_uninitialized.html @@ -0,0 +1,77 @@ + + + +False positive with -Wmaybe-uninitialized + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Sometimes on GCC compilers below version 5.1 you may get an -Wmaybe-uninitialized + warning when compiling with option -02 on a perfectly valid boost::optional usage. For instance in this + program: +

+
#include <boost/optional.hpp>
+
+boost::optional<int> getitem();
+
+int main(int argc, const char *[])
+{
+  boost::optional<int> a = getitem();
+  boost::optional<int> b;
+
+  if (argc > 0)
+    b = argc;
+
+  if (a != b)
+    return 1;
+
+  return 0;
+}
+
+

+ This is a bug in the compiler. As a workaround (provided in this + Stack Overflow question) use the following way of initializing + an optional containing no value: +

+
boost::optional<int> b = boost::make_optional(false, int());
+
+

+ This is obviously redundant, but makes the warning disappear. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/gotchas/mixed_relational_comparisons.html b/libs/optional/doc/html/boost_optional/tutorial/gotchas/mixed_relational_comparisons.html new file mode 100644 index 00000000..c89f67d9 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/gotchas/mixed_relational_comparisons.html @@ -0,0 +1,59 @@ + + + +Mixed relational comparisons + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Because T is convertible + to optional<T> + and because optional<T> + is LessThanComparable when T is LessThanComparable, you can sometimes + get an unexpected runtime result where you would rather expect a compiler + error: +

+
optional<double> Flight_plan::weight(); // sometimes no weight can be returned
+
+bool is_aircraft_too_heavy(Flight_plan const& p)
+{
+   return p.weight() > p.aircraft().max_weight(); // compiles!
+}                                                 // returns false when the optional contains no value 
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/gotchas/moved_from__optional_.html b/libs/optional/doc/html/boost_optional/tutorial/gotchas/moved_from__optional_.html new file mode 100644 index 00000000..7924e618 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/gotchas/moved_from__optional_.html @@ -0,0 +1,63 @@ + + + +Moved-from optional + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ When an optional object that contains a value is moved from (is a source + of move constructor or assignment) it still contains a value and its contained + value is left in a moved-from state. This can be illustrated with the following + example. +

+
optional<std::unique_ptr<int>> opi {std::make_unique<int>(1)};
+optional<std::unique_ptr<int>> opj = std::move(opi);
+assert (opi);
+assert (*opi == nullptr);
+
+

+ Quite a lot of people expect that when an object that contains a value + is moved from, its contained value should be destroyed. This is not so, + for performance reasons. Current semantics allow the implementation of + boost::optional<T> + to be trivially copyable when T + is trivial. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/in_place_factories.html b/libs/optional/doc/html/boost_optional/tutorial/in_place_factories.html new file mode 100644 index 00000000..10e62baa --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/in_place_factories.html @@ -0,0 +1,197 @@ + + + +In-Place Factories + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ One of the typical problems with wrappers and containers is that their interfaces + usually provide an operation to initialize or assign the contained object + as a copy of some other object. This not only requires the underlying type + to be CopyConstructible, but also requires + the existence of a fully constructed object, often temporary, just to follow + the copy from: +

+
struct X
+{
+    X ( int, std::string ) ;
+} ;
+
+class W
+{
+    X wrapped_ ;
+
+    public:
+
+    W ( X const& x ) : wrapped_(x) {}
+} ;
+
+void foo()
+{
+    // Temporary object created.
+    W ( X(123,"hello") ) ;
+}
+
+

+ A solution to this problem is to support direct construction of the contained + object right in the container's storage. In this scheme, the user only needs + to supply the arguments to the constructor to use in the wrapped object construction. +

+
class W
+{
+    X wrapped_ ;
+
+    public:
+
+    W ( X const& x ) : wrapped_(x) {}
+    W ( int a0, std::string a1) : wrapped_(a0,a1) {}
+} ;
+
+void foo()
+{
+    // Wrapped object constructed in-place
+    // No temporary created.
+    W (123,"hello") ;
+}
+
+

+ A limitation of this method is that it doesn't scale well to wrapped objects + with multiple constructors nor to generic code were the constructor overloads + are unknown. +

+

+ The solution presented in this library is the family of InPlaceFactories + and TypedInPlaceFactories. These factories + are a family of classes which encapsulate an increasing number of arbitrary + constructor parameters and supply a method to construct an object of a given + type using those parameters at an address specified by the user via placement + new. +

+

+ For example, one member of this family looks like: +

+
template<class T,class A0, class A1>
+class TypedInPlaceFactory2
+{
+    A0 m_a0 ; A1 m_a1 ;
+
+    public:
+
+    TypedInPlaceFactory2( A0 const& a0, A1 const& a1 ) : m_a0(a0), m_a1(a1) {}
+
+    void construct ( void* p ) { new (p) T(m_a0,m_a1) ; }
+ } ;
+
+

+ A wrapper class aware of this can use it as: +

+
class W
+{
+    X wrapped_ ;
+
+    public:
+
+    W ( X const& x ) : wrapped_(x) {}
+    W ( TypedInPlaceFactory2 const& fac ) { fac.construct(&wrapped_) ; }
+} ;
+
+void foo()
+{
+    // Wrapped object constructed in-place via a TypedInPlaceFactory.
+    // No temporary created.
+    W ( TypedInPlaceFactory2<X,int,std::string>(123,"hello")) ;
+}
+
+

+ The factories are divided in two groups: +

+
    +
  • + TypedInPlaceFactories: those which + take the target type as a primary template parameter. +
  • +
  • + InPlaceFactories: those with a + template construct(void*) + member function taking the target type. +
  • +
+

+ Within each group, all the family members differ only in the number of parameters + allowed. +

+

+ This library provides an overloaded set of helper template functions to construct + these factories without requiring unnecessary template parameters: +

+
template<class A0,...,class AN>
+InPlaceFactoryN <A0,...,AN> in_place ( A0 const& a0, ..., AN const& aN) ;
+
+template<class T,class A0,...,class AN>
+TypedInPlaceFactoryN <T,A0,...,AN> in_place ( T const& a0, A0 const& a0, ..., AN const& aN) ;
+
+

+ In-place factories can be used generically by the wrapper and user as follows: +

+
class W
+{
+    X wrapped_ ;
+
+    public:
+
+    W ( X const& x ) : wrapped_(x) {}
+
+    template< class InPlaceFactory >
+    W ( InPlaceFactory const& fac ) { fac.template <X>construct(&wrapped_) ; }
+
+} ;
+
+void foo()
+{
+    // Wrapped object constructed in-place via a InPlaceFactory.
+    // No temporary created.
+    W ( in_place(123,"hello") ) ;
+}
+
+

+ The factories are implemented in the headers: in_place_factory.hpp + and typed_in_place_factory.hpp +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/io_operators.html b/libs/optional/doc/html/boost_optional/tutorial/io_operators.html new file mode 100644 index 00000000..d6d9dcbd --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/io_operators.html @@ -0,0 +1,87 @@ + + + +IO operators + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ It is possible to use optional<T> + with IO streams, provided that T + can be used with streams. IOStream operators are defined in a separate header. +

+

+

+
#include <iostream>
+#include <boost/optional/optional_io.hpp>
+
+int main()
+{
+  boost::optional<int> o1 = 1, oN = boost::none;
+  std::cout << o1;
+  std::cin >> oN;
+}
+
+

+

+

+ The current implementation does not guarantee any particular output. What + it guarantees is that if streaming out and then back in T + gives the same value, then streaming out and then back in optional<T> + will also give back the same result: +

+

+

+
#include <cassert>
+#include <sstream>
+#include <boost/optional/optional_io.hpp>
+
+int main()
+{
+  boost::optional<int> o1 = 1, oN = boost::none;
+  boost::optional<int> x1, x2;
+  std::stringstream s;
+  s << o1 << oN;
+  s >> x1 >> x2;
+  assert (o1 == x1);
+  assert (oN == x2);
+}
+
+

+

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/motivation.html b/libs/optional/doc/html/boost_optional/tutorial/motivation.html new file mode 100644 index 00000000..3b9f43cf --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/motivation.html @@ -0,0 +1,129 @@ + + + +Motivation + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Consider these functions which should return a value but which might not + have a value to return: +

+
    +
  • + (A) double sqrt(double n ); +
  • +
  • + (B) char get_async_input(); +
  • +
  • + (C) point polygon::get_any_point_effectively_inside(); +
  • +
+

+ There are different approaches to the issue of not having a value to return. +

+

+ A typical approach is to consider the existence of a valid return value as + a postcondition, so that if the function cannot compute the value to return, + it has either undefined behavior (and can use assert in a debug build) or + uses a runtime check and throws an exception if the postcondition is violated. + This is a reasonable choice for example, for function (A), because the lack + of a proper return value is directly related to an invalid parameter (out + of domain argument), so it is appropriate to require the callee to supply + only parameters in a valid domain for execution to continue normally. +

+

+ However, function (B), because of its asynchronous nature, does not fail + just because it can't find a value to return; so it is incorrect to consider + such a situation an error and assert or throw an exception. This function + must return, and somehow, must tell the callee that it is not returning a + meaningful value. +

+

+ A similar situation occurs with function (C): it is conceptually an error + to ask a null-area polygon to return a point inside + itself, but in many applications, it is just impractical for performance + reasons to treat this as an error (because detecting that the polygon has + no area might be too expensive to be required to be tested previously), and + either an arbitrary point (typically at infinity) is returned, or some efficient + way to tell the callee that there is no such point is used. +

+

+ There are various mechanisms to let functions communicate that the returned + value is not valid. One such mechanism, which is quite common since it has + zero or negligible overhead, is to use a special value which is reserved + to communicate this. Classical examples of such special values are EOF, string::npos, + points at infinity, etc... +

+

+ When those values exist, i.e. the return type can hold all meaningful values + plus the signal value, this mechanism + is quite appropriate and well known. Unfortunately, there are cases when + such values do not exist. In these cases, the usual alternative is either + to use a wider type, such as int + in place of char; or a compound + type, such as std::pair<point,bool>. +

+

+ Returning a std::pair<T,bool>, thus attaching a boolean flag to the + result which indicates if the result is meaningful, has the advantage that + can be turned into a consistent idiom since the first element of the pair + can be whatever the function would conceptually return. For example, the + last two functions could have the following interface: +

+
std::pair<char,bool> get_async_input();
+std::pair<point,bool> polygon::get_any_point_effectively_inside();
+
+

+ These functions use a consistent interface for dealing with possibly nonexistent + results: +

+
std::pair<point,bool> p = poly.get_any_point_effectively_inside();
+if ( p.second )
+    flood_fill(p.first);
+
+

+ However, not only is this quite a burden syntactically, it is also error + prone since the user can easily use the function result (first element of + the pair) without ever checking if it has a valid value. +

+

+ Clearly, we need a better idiom. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/optional_references.html b/libs/optional/doc/html/boost_optional/tutorial/optional_references.html new file mode 100644 index 00000000..ff16598d --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/optional_references.html @@ -0,0 +1,117 @@ + + + +Optional references + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ +

+ This library allows the template parameter T + to be of reference type: T&, and to some extent, T const&. +

+

+ However, since references are not real objects some restrictions apply + and some operations are not available in this case: +

+
    +
  • + Converting constructors +
  • +
  • + Converting assignment +
  • +
  • + InPlace construction +
  • +
  • + InPlace assignment +
  • +
  • + Value-access via pointer +
  • +
+

+ Also, even though optional<T&> treats it wrapped pseudo-object + much as a real value, a true real reference is stored so aliasing will + occur: +

+
    +
  • + Copies of optional<T&> will copy the references but + all these references will nonetheless refer to the same object. +
  • +
  • + Value-access will actually provide access to the referenced object + rather than the reference itself. +
  • +
+
+ + + + + +
[Caution]Caution

+ On compilers that do not conform to Standard C++ rules of reference binding, + some operations on optional references are disabled in order to prevent + subtle bugs. For more details see Dependencies + and Portability section. +

+
+ + Rvalue + references +
+

+ Rvalue references and lvalue references to const have the ability in C++ + to extend the life time of a temporary they bind to. Optional references + do not have this capability, therefore to avoid surprising effects it is + not possible to initialize an optional references from a temporary. Optional + rvalue references are disabled altogether. Also, the initialization and + assignment of an optional reference to const from rvalue reference is disabled. +

+
const int& i = 1;            // legal
+optional<const int&> oi = 1; // illegal
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/optional_references/rebinding_semantics_for_assignment_of_optional_references.html b/libs/optional/doc/html/boost_optional/tutorial/optional_references/rebinding_semantics_for_assignment_of_optional_references.html new file mode 100644 index 00000000..112eb5da --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/optional_references/rebinding_semantics_for_assignment_of_optional_references.html @@ -0,0 +1,147 @@ + + + +Rebinding semantics for assignment of optional references + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ If you assign to an uninitialized optional<T&> the effect is to bind (for the + first time) to the object. Clearly, there is no other choice. +

+
int x = 1 ;
+int& rx = x ;
+optional<int&> ora ;
+optional<int&> orb(x) ;
+ora = orb ; // now 'ora' is bound to 'x' through 'rx'
+*ora = 2 ; // Changes value of 'x' through 'ora'
+assert(x==2);
+
+

+ If you assign to a bare C++ reference, the assignment is forwarded to the + referenced object; its value changes but the reference is never rebound. +

+
int a = 1 ;
+int& ra = a ;
+int b = 2 ;
+int& rb = b ;
+ra = rb ; // Changes the value of 'a' to 'b'
+assert(a==b);
+b = 3 ;
+assert(ra!=b); // 'ra' is not rebound to 'b'
+
+

+ Now, if you assign to an initialized optional<T&>, + the effect is to rebind to the new object + instead of assigning the referee. This is unlike bare C++ references. +

+
int a = 1 ;
+int b = 2 ;
+int& ra = a ;
+int& rb = b ;
+optional<int&> ora(ra) ;
+optional<int&> orb(rb) ;
+ora = orb ; // 'ora' is rebound to 'b'
+*ora = 3 ; // Changes value of 'b' (not 'a')
+assert(a==1);
+assert(b==3);
+
+
+ + Rationale +
+

+ Rebinding semantics for the assignment of initialized + optional references has + been chosen to provide consistency among initialization + states even at the expense of lack of consistency with the semantics + of bare C++ references. It is true that optional<U> strives to behave as much as possible + as U does whenever it is + initialized; but in the case when U + is T&, + doing so would result in inconsistent behavior w.r.t to the lvalue initialization + state. +

+

+ Imagine optional<T&> + forwarding assignment to the referenced object (thus changing the referenced + object value but not rebinding), and consider the following code: +

+
optional<int&> a = get();
+int x = 1 ;
+int& rx = x ;
+optional<int&> b(rx);
+a = b ;
+
+

+ What does the assignment do? +

+

+ If a is uninitialized, + the answer is clear: it binds to x + (we now have another reference to x). + But what if a is already + initialized? it would change the value of the referenced + object (whatever that is); which is inconsistent with the other possible + case. +

+

+ If optional<T&> + would assign just like T& does, you would never be able to use + Optional's assignment without explicitly handling the previous initialization + state unless your code is capable of functioning whether after the assignment, + a aliases the same object + as b or not. +

+

+ That is, you would have to discriminate in order to be consistent. +

+

+ If in your code rebinding to another object is not an option, then it is + very likely that binding for the first time isn't either. In such case, + assignment to an uninitialized optional<T&> shall be prohibited. It is quite + possible that in such a scenario it is a precondition that the lvalue must + be already initialized. If it isn't, then binding for the first time is + OK while rebinding is not which is IMO very unlikely. In such a scenario, + you can assign the value itself directly, as in: +

+
assert(!!opt);
+*opt=value;
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/performance_considerations.html b/libs/optional/doc/html/boost_optional/tutorial/performance_considerations.html new file mode 100644 index 00000000..e20cf61a --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/performance_considerations.html @@ -0,0 +1,265 @@ + + + +Performance considerations + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Technical details aside, the memory layout of optional<T> + for a generic T is more-less + this: +

+
template <typename T>
+class optional
+{
+  bool _initialized;
+  std::aligned_storage_t<sizeof(t), alignof(T)> _storage;
+};
+
+

+ Lifetime of the T inside + _storage is manually controlled + with placement-news and pseudo-destructor + calls. However, for scalar Ts + we use a different way of storage, by simply holding a T: +

+
template <typename T>
+class optional
+{
+  bool _initialized;
+  T _storage;
+};
+
+

+ We call it a direct storage. This makes optional<T> a + trivially-copyable type for scalar Ts. + This only works for compilers that support defaulted functions (including + defaulted move assignment and constructor). On compilers without defaulted + functions we still use the direct storage, but optional<T> + is no longer recognized as trivially-copyable. Apart from scalar types, we + leave the programmer a way of customizing her type, so that it is recognized + by optional as candidate + for optimized storage, by specializing type trait boost::optional_config::optional_uses_direct_storage_for: +

+
struct X // not trivial
+{
+  X() {}
+};
+
+namespace boost { namespace optional_config {
+
+  template <> struct optional_uses_direct_storage_for<X> : boost::true_type {};
+
+}}
+
+
+ + Controlling + the size +
+

+ For the purpose of the following analysis, considering memory layouts, we + can think of it as: +

+
template <typename T>
+class optional
+{
+  bool _initialized;
+  T _storage;
+};
+
+

+ Given type optional<int>, and + assuming that sizeof(int) == + 4, we will get sizeof(optional<int>) + == 8. + This is so because of the alignment rules, for our two members we get the + following alignment: +

+

+ opt_align1 +

+

+ This means you can fit twice as many ints + as optional<int>s into + the same space of memory. Therefore, if the size of the objects is critical + for your application (e.g., because you want to utilize your CPU cache in + order to gain performance) and you have determined you are willing to trade + the code clarity, it is recommended that you simply go with type int and use some 'magic value' to represent + not-an-int, or use something like markable library. +

+

+ Even if you cannot spare any value of int + to represent not-an-int (e.g., because every value is + useful, or you do want to signal not-an-int explicitly), + at least for Trivial types + you should consider storing the value and the bool + flag representing the null-state separately. Consider + the following class: +

+
struct Record
+{
+  optional<int> _min;
+  optional<int> _max;
+};
+
+

+ Its memory layout can be depicted as follows: +

+

+ opt_align2 +

+

+ This is exactly the same as if we had the following members: +

+
struct Record
+{
+  bool _has_min;
+  int  _min;
+  bool _has_max;
+  int  _max;
+};
+
+

+ But when they are stored separately, we at least have an option to reorder + them like this: +

+
struct Record
+{
+  bool _has_min;
+  bool _has_max;
+  int  _min;
+  int  _max;
+};
+
+

+ Which gives us the following layout (and smaller total size): +

+

+ opt_align3 +

+

+ Sometimes it requires detailed consideration what data we make optional. + In our case above, if we determine that both minimum and maximum value can + be provided or not provided together, but one is never provided without the + other, we can make only one optional member: +

+
struct Limits
+{
+  int  _min;
+  int  _max;
+};
+
+struct Record
+{
+  optional<Limits> _limits;
+};
+
+

+ This would give us the following layout: +

+

+ opt_align4 +

+
+ + Optional + function parameters +
+

+ Having function parameters of type const + optional<T>& + may incur certain unexpected run-time cost connected to copy construction + of T. Consider the following + code. +

+
void fun(const optional<Big>& v)
+{
+  if (v) doSomethingWith(*v);
+  else   doSomethingElse();
+}
+
+int main()
+{
+  optional<Big> ov;
+  Big v;
+  fun(none);
+  fun(ov); // no copy
+  fun(v);  // copy constructor of Big
+}
+
+

+ No copy elision or move semantics can save us from copying type Big here. Not that we need any copy, but + this is how optional works. + In order to avoid copying in this case, one could provide second overload + of fun: +

+
void fun(const Big& v)
+{
+  doSomethingWith(v);
+}
+
+int main()
+{
+  optional<Big> ov;
+  Big v;
+  fun(ov); // no copy
+  fun(v);  // no copy: second overload selected
+}
+
+

+ Alternatively, you could consider using an optional reference instead: +

+
void fun(optional<const Big&> v) // note where the reference is
+{
+  if (v) doSomethingWith(*v);
+  else   doSomethingElse();
+}
+
+int main()
+{
+  optional<Big> ov;
+  Big v;
+  fun(none);
+  fun(ov); // doesn't compile
+  fun(v);  // no copy
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/rebinding_semantics_for_assignment_of_optional_references.html b/libs/optional/doc/html/boost_optional/tutorial/rebinding_semantics_for_assignment_of_optional_references.html new file mode 100644 index 00000000..ee693eee --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/rebinding_semantics_for_assignment_of_optional_references.html @@ -0,0 +1,149 @@ + + + +Rebinding semantics for assignment of optional references + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ If you assign to an uninitialized optional<T&> + the effect is to bind (for the first time) to the object. Clearly, there + is no other choice. +

+
int x = 1 ;
+int& rx = x ;
+optional<int&> ora ;
+optional<int&> orb(x) ;
+ora = orb ; // now 'ora' is bound to 'x' through 'rx'
+*ora = 2 ; // Changes value of 'x' through 'ora'
+assert(x==2);
+
+

+ If you assign to a bare C++ reference, the assignment is forwarded to the + referenced object; its value changes but the reference is never rebound. +

+
int a = 1 ;
+int& ra = a ;
+int b = 2 ;
+int& rb = b ;
+ra = rb ; // Changes the value of 'a' to 'b'
+assert(a==b);
+b = 3 ;
+assert(ra!=b); // 'ra' is not rebound to 'b'
+
+

+ Now, if you assign to an initialized optional<T&>, + the effect is to rebind to the new object + instead of assigning the referee. This is unlike bare C++ references. +

+
int a = 1 ;
+int b = 2 ;
+int& ra = a ;
+int& rb = b ;
+optional<int&> ora(ra) ;
+optional<int&> orb(rb) ;
+ora = orb ; // 'ora' is rebound to 'b'
+*ora = 3 ; // Changes value of 'b' (not 'a')
+assert(a==1);
+assert(b==3);
+
+
+ + Rationale +
+

+ Rebinding semantics for the assignment of initialized + optional references has been + chosen to provide consistency among initialization + states even at the expense of lack of consistency with the semantics + of bare C++ references. It is true that optional<U> + strives to behave as much as possible as U + does whenever it is initialized; but in the case when U + is T&, + doing so would result in inconsistent behavior w.r.t to the lvalue initialization + state. +

+

+ Imagine optional<T&> + forwarding assignment to the referenced object (thus changing the referenced + object value but not rebinding), and consider the following code: +

+
optional<int&> a = get();
+int x = 1 ;
+int& rx = x ;
+optional<int&> b(rx);
+a = b ;
+
+

+ What does the assignment do? +

+

+ If a is uninitialized, + the answer is clear: it binds to x + (we now have another reference to x). + But what if a is already + initialized? it would change the value of the referenced + object (whatever that is); which is inconsistent with the other possible + case. +

+

+ If optional<T&> + would assign just like T& does, you would never be able to use + Optional's assignment without explicitly handling the previous initialization + state unless your code is capable of functioning whether after the assignment, + a aliases the same object + as b or not. +

+

+ That is, you would have to discriminate in order to be consistent. +

+

+ If in your code rebinding to another object is not an option, then it is + very likely that binding for the first time isn't either. In such case, assignment + to an uninitialized optional<T&> + shall be prohibited. It is quite possible that in such a scenario it is a + precondition that the lvalue must be already initialized. If it isn't, then + binding for the first time is OK while rebinding is not which is IMO very + unlikely. In such a scenario, you can assign the value itself directly, as + in: +

+
assert(!!opt);
+*opt=value;
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/relational_operators.html b/libs/optional/doc/html/boost_optional/tutorial/relational_operators.html new file mode 100644 index 00000000..e384ab07 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/relational_operators.html @@ -0,0 +1,113 @@ + + + +Relational operators + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Type optional<T> is + EqualityComparable whenever T is EqualityComparable. Two optional + objects containing a value compare in the same way as their contained values. + The uninitialized state of optional<T> + is treated as a distinct value, equal to itself, and unequal to any value + of type T: +

+
boost::optional<int> oN = boost::none;
+boost::optional<int> o0 = 0;
+boost::optional<int> o1 = 1;
+
+assert(oN != o0);
+assert(o1 != oN);
+assert(o0 != o1);
+assert(oN == oN);
+assert(o0 == o0);
+
+

+ The converting constructor from T + as well as from boost::none implies the existence and semantics + of the mixed comparison between T + and optional<T> as + well as between none_t and + optional<T>: +

+
assert(oN != 0);
+assert(o1 != boost::none);
+assert(o0 != 1);
+assert(oN == boost::none);
+assert(o0 == 0);
+
+

+ This mixed comparison has a practical interpretation, which is occasionally + useful: +

+
boost::optional<int> choice = ask_user();
+if (choice == 2)
+    start_procedure_2();
+
+

+ In the above example, the meaning of the comparison is 'user chose number + 2'. If user chose nothing, he didn't choose number 2. +

+

+ In case where optional<T> is + compared to none, it is not + required that T be EqualityComparable. +

+

+ In a similar manner, type optional<T> + is LessThanComparable whenever T is LessThanComparable. The optional + object containing no value is compared less than any value of T. To illustrate this, if the default ordering + of size_t is {0, 1, + 2, ...}, the default ordering + of optional<size_t> + is {boost::none, 0, + 1, 2, + ...}. This order does not have a practical interpretation. The goal is to + have any semantically correct default ordering in order for optional<T> to + be usable in ordered associative containers (wherever T + is usable). +

+

+ Mixed relational operators are the only case where the contained value of + an optional object can be inspected without the usage of value accessing + function (operator*, + value, value_or). +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/type_requirements.html b/libs/optional/doc/html/boost_optional/tutorial/type_requirements.html new file mode 100644 index 00000000..9eac69df --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/type_requirements.html @@ -0,0 +1,109 @@ + + + +Type requirements + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ The very minimum requirement of optional<T> + is that T is a complete type + and that it has a publicly accessible destructor. T + doesn't even need to be constructible. You can use a very minimum interface: +

+
optional<T> o;     // uninitialized
+assert(o == none); // check if initialized
+assert(!o);        //
+o.value();         // always throws
+
+

+ But this is practically useless. In order for optional<T> + to be able to do anything useful and offer all the spectrum of ways of accessing + the contained value, T needs + to have at least one accessible constructor. In that case you need to initialize + the optional object with function emplace(), or if your compiler does not support it, + resort to In-Place + Factories: +

+
optional<T> o;
+o.emplace("T", "ctor", "params");
+
+

+ If T is MoveConstructible, + optional<T> is + also MoveConstructible and + can be easily initialized from an rvalue of type T + and be passed by value: +

+
optional<T> o = make_T();
+optional<T> p = optional<T>();
+
+

+ If T is CopyConstructible, optional<T> is + also CopyConstructible + and can be easily initialized from an lvalue of type T: +

+
T v = make_T();
+optional<T> o = v;
+optional<T> p = o;
+
+

+ If T is not MoveAssignable, it is still possible to + reset the value of optional<T> + using function emplace(): +

+
optional<const T> o = make_T();
+o.emplace(make_another_T());
+
+

+ If T is Moveable + (both MoveConstructible and + MoveAssignable) then optional<T> is + also Moveable and additionally + can be constructed and assigned from an rvalue of type T. +

+

+ Similarly, if T is Copyable (both CopyConstructible and CopyAssignable) then optional<T> + is also Copyable and additionally + can be constructed and assigned from an lvalue of type T. +

+

+ T is not + required to be DefaultConstructible. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/tutorial/when_to_use_optional.html b/libs/optional/doc/html/boost_optional/tutorial/when_to_use_optional.html new file mode 100644 index 00000000..7fa6810e --- /dev/null +++ b/libs/optional/doc/html/boost_optional/tutorial/when_to_use_optional.html @@ -0,0 +1,142 @@ + + + +When to use Optional + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ It is recommended to use optional<T> + in situations where there is exactly one, clear (to all parties) reason for + having no value of type T, + and where the lack of value is as natural as having any regular value of + T. One example of such situation + is asking the user in some GUI form to optionally specify some limit on an + int value, but the user is allowed + to say 'I want the number not to be constrained by the maximum'. For another + example, consider a config parameter specifying how many threads the application + should launch. Leaving this parameter unspecified means that the application + should decide itself. For yet another example, consider a function returning + the index of the smallest element in a vector. + We need to be prepared for the situation, where the vector + is empty. Therefore a natural signature for such function would be: +

+
template <typename T>
+optional<size_t> find_smallest_elem(const std::vector<T>& vec);
+
+

+ Here, having received an empty vec + and having no size_t to return + is not a failure but a normal, + albeit irregular, situation. +

+

+ Another typical situation is to indicate that we do not have a value yet, + but we expect to have it later. This notion can be used in implementing solutions + like lazy initialization or a two-phase initialization. +

+

+ optional can be used to take + a non-DefaultConstructible type T and create a sibling type with a default + constructor. This is a way to add a null-state to any + type that doesn't have it already. +

+

+ Sometimes type T already + provides a built-in null-state, but it may still be useful to wrap it into + optional. Consider std::string. + When you read a piece of text from a GUI form or a DB table, it is hardly + ever that the empty string indicates anything else but a missing text. And + some data bases do not even distinguish between a null string entry and a + non-null string of length 0. Still, it may be practical to use optional<string> + to indicate in the returned type that we want to treat the empty string in + a special dedicated program path: +

+
if(boost::optional<std::string> name = ask_user_name()) {
+    assert(*name != "");
+    logon_as(*name);
+}
+else {
+    skip_logon();
+}
+
+

+ In the example above, the assertion indicates that if we choose to use this + technique, we must translate the empty string state to an optional object + with no contained value (inside function ask_user_name). +

+
+ + Not + recommended usages +
+

+ It is not recommended to use optional + to indicate that we were not able to compute a value because of a failure. + It is difficult to define what a failure is, but it usually has one common + characteristic: an associated information on the cause of the failure. This + can be the type and member data of an exception object, or an error code. + It is a bad design to signal a failure and not inform about the cause. If + you do not want to use exceptions, and do not like the fact that by returning + error codes you cannot return the computed value, you can use Expected + library. It is sort of Boost.Variant + that contains either a computed value or a reason why the computation failed. +

+

+ Sometimes the distinction into what is a failure and what is a valid but + irregular result is blurry and depends on a particular usage and personal + preference. Consider a function that converts a string + to an int. Is it a failure that + you cannot convert? It might in some cases, but in other you may call it + exactly for the purpose of figuring out if a given string + is convertible, and you are not even interested in the resulting value. Sometimes + when a conversion fails you may not consider it a failure, but you need to + know why it cannot be converted; for instance at which character it is determined + that the conversion is impossible. In this case returning optional<T> + will not suffice. Finally, there is a use case where an input string that + does not represent an int is + not a failure condition, but during the conversion we use resources whose + acquisition may fail. In that case the natural representation is to both + return optional<int> and + signal failure: +

+
optional<int> convert1(const string& str); // throws
+expected<ErrorT, optional<int>> convert2(const string& str); // return either optional or error
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/boost_optional/type_requirements.html b/libs/optional/doc/html/boost_optional/type_requirements.html new file mode 100644 index 00000000..e1ee7778 --- /dev/null +++ b/libs/optional/doc/html/boost_optional/type_requirements.html @@ -0,0 +1,61 @@ + + + +Type requirements + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ At the very minimum for optional<T> + to work with a minimum interface it is required that T + has a publicly accessible no-throw destructor. In that case you need to initialize + the optional object with function emplace() or use InPlaceFactories. + Additionally, if T is Moveable, optional<T> + is also Moveable and can be + easily initialized from an rvalue of type T + and be passed by value. Additionally, if T + is Copyable, optional<T> is + also Copyable and can be easily + initialized from an lvalue of type T. +

+

+ T is + not required to be Default + Constructible. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/images/callouts/R.png b/libs/optional/doc/html/images/callouts/R.png new file mode 100644 index 0000000000000000000000000000000000000000..bee36a1ddd846ec8b96557a7887a831291a80ee6 GIT binary patch literal 293 zcmV+=0owkFP)DI+HApacn~vn(@Ak|Y5DIF17mLDMw! zJWq@S$8p@9(ljMW9>>9P9Pj^=o9CHzUDHVL3L=7{C@!3B+t~LVWm!^4qU$=kt_u-C zmSu?J7@t?768-`)PvMl)e%{@sH#BqG-<9Rs<0(mJAMG*iX48ym}Mu~qpW8e2I risE`kr4;(Uf7d6p)=)}4oPY2QW%&Wf_>p!N00000NkvXXu0mjf`K)=O literal 0 HcmV?d00001 diff --git a/libs/optional/doc/html/images/opt_align1.png b/libs/optional/doc/html/images/opt_align1.png new file mode 100644 index 0000000000000000000000000000000000000000..50e0205eab4aef06bdc02ac4490dd20ca50e887b GIT binary patch literal 417 zcmeAS@N?(olHy`uVBq!ia0y~yV9W%v1vuD%*=8cRV(+fa+p`U_zvmWtOm(idUVN%_zTQ7>*?qC!j0MGHfWgY( M>FVdQ&MBb@0CoSNbpQYW literal 0 HcmV?d00001 diff --git a/libs/optional/doc/html/images/opt_align2.png b/libs/optional/doc/html/images/opt_align2.png new file mode 100644 index 0000000000000000000000000000000000000000..fd7c079c9303f4797523b7ef10c775d2b42f959f GIT binary patch literal 472 zcmeAS@N?(olHy`uVBq!ia0y~yV9W%v1vuD%*?YcQW5v|j-eluqr}mVk@^Y?Hy-AQ zxD~O!Q*E1*uVcmso;i)l65Q3fz9u)SapjkB_DEFR9e$&t3_qX%+-B;_+ z+q6jI)q(f-xnlm#bAKB)r`G-H-G?`7?>_IHd);=P+ulbDZM#qHK0NvA9b2QHdvc;L zRnGHf*F0@BA=hpCDXr?5w)NR>>wi45<^K9($<3x}f7wU-UhkiO!RoE|?`5a>?B5^0 z{no?k^V!$I5j=5Aa#p>+UA=Ge_qBFb3yUK?fhzL$Uz}KyJQPVY^2Xh!^qEH{s4#5|FE0wsoOJ$Lg+};Pvt?E{*v-#} WC01}`)pr47gTd3)&t;ucLK6U}S-J!O literal 0 HcmV?d00001 diff --git a/libs/optional/doc/html/images/opt_align3.png b/libs/optional/doc/html/images/opt_align3.png new file mode 100644 index 0000000000000000000000000000000000000000..7ca6ec800eb037540b8598efab9014c68701e4ad GIT binary patch literal 468 zcmeAS@N?(olHy`uVBq!ia0y~yV9W%v1vuD%Z39%YlSDF>nFWGVcGfTs$Kds^U40^k%1!Lk37$2 z{q=m^p6z9|YU%S2-amF|O8B8^f3-d@GQMWq6}R8W{!yIf>pvlC)zeDmJ-_sRYU<1r z``pD-r|PbMX>j3RyZZ0STYbyk=YF`qy=``=RqyqnYe}g$-@h&Lv0vM_<=KigPkUCy z8k<&6-Ex0L&Xv8J?s#TzQ=2QG$Rgmtz$nh>b*puzB8NglgPMb9cHR>D3N~KXuF#t- zA*7U0x$E*Tp0p#ACr$g?CNrUM#n+ym$Ig!gziXu|u6LGqR*V1k*dSR87!wShu6{1- HoD!MliF_`N=}RMZtFHX(d0zRmL~dE8mFWC-(Te|7Yj5RN zS%y5_e0b~cwEOETPqS88Pd;tF$A{TZ z+5{9F6x0?hNzMzRo7j(f?zmGb&a*hK?Ax_@`*o*l?`}U)l-%X9V7u|ojGfZr{~5EV W#(tY5{-PZi!VI3SelF{r5}E+l@}j2z literal 0 HcmV?d00001 diff --git a/libs/optional/doc/html/images/space.png b/libs/optional/doc/html/images/space.png new file mode 100644 index 0000000000000000000000000000000000000000..8e6dcfbcf1c1e3092a5dc60e36d7bd45ec07923e GIT binary patch literal 81 zcmeAS@N?(olHy`uVBq!ia0vp^tU#>7!2~4F{Y_T{QWBmnjv*QolmGnxZ_g~0kmSI+ f_)nmnogD+)duG?Oe9uIHY8X6S{an^LB{Ts5&4?7e literal 0 HcmV?d00001 diff --git a/libs/optional/doc/html/index.html b/libs/optional/doc/html/index.html new file mode 100644 index 00000000..9f97b8b0 --- /dev/null +++ b/libs/optional/doc/html/index.html @@ -0,0 +1,154 @@ + + + +Boost.Optional + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
Next
+
+
+

+Boost.Optional

+

+Fernando Luis Cacciola Carballal +

+
+
+
+

+ 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) +

+
+
+ +
+ +

+ Class template optional is + a wrapper for representing 'optional' (or 'nullable') objects who may not (yet) + contain a valid value. Optional objects offer full value semantics; they are + good for passing by value and usage inside STL containers. This is a header-only + library. +

+

+ + Problem +

+

+ Suppose we want to read a parameter from a config file which represents some + integral value, let's call it "MaxValue". + It is possible that this parameter is not specified; such situation is no error. + It is valid to not specify the parameter and in that case the program is supposed + to behave slightly differently. Also, suppose that any possible value of type + int is a valid value for "MaxValue", so we cannot just use + -1 + to represent the absence of the parameter in the config file. +

+

+ + Solution +

+

+ This is how you solve it with boost::optional: +

+
#include <boost/optional.hpp>
+
+boost::optional<int> getConfigParam(std::string name);  // return either an int or a `not-an-int`
+
+int main()
+{
+  if (boost::optional<int> oi = getConfigParam("MaxValue")) // did I get a real int?
+    runWithMax(*oi);                                        // use my int
+  else
+    runWithNoMax();
+}
+
+
+
+ + + +

Last revised: March 26, 2022 at 22:47:53 GMT

+
+
Next
+ + diff --git a/libs/optional/doc/html/optional/reference.html b/libs/optional/doc/html/optional/reference.html new file mode 100644 index 00000000..1cbeafab --- /dev/null +++ b/libs/optional/doc/html/optional/reference.html @@ -0,0 +1,89 @@ + + + +Reference + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +
+ +

+

+
namespace boost {
+
+class none_t {/* see below */};
+
+inline constexpr none_t none (/* see below */);
+
+} // namespace boost
+
+

+

+

+ Class none_t is meant to + serve as a tag for selecting appropriate overloads of from optional's interface. It is an empty, + trivially copyable class with disabled default constructor. +

+

+ Constant none is used to + indicate an optional object that does not contain a value in initialization, + assignment and relational operations of optional. +

+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/optional/reference/header__boost_optional_optional_hpp_.html b/libs/optional/doc/html/optional/reference/header__boost_optional_optional_hpp_.html new file mode 100644 index 00000000..c905bfce --- /dev/null +++ b/libs/optional/doc/html/optional/reference/header__boost_optional_optional_hpp_.html @@ -0,0 +1,111 @@ + + + +Header <boost/optional/optional.hpp> + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ +
// In Header: <boost/optional/optional.hpp>
+
+namespace boost {
+
+class in_place_init_t { /* see below */ } ; R
+const in_place_init_t in_place_init ( /* see below */ ) ;
+
+class in_place_init_if_t { /*see below*/ } ; R
+const in_place_init_if_t in_place_init_if ( /*see below*/ ) ;
+
+template <class T>
+class optional ; R
+
+template <class T>
+class optional<T&> ; R
+
+template<class T> inline bool operator == ( optional<T> const& x, optional<T> const& y ) ; R
+
+template<class T> inline bool operator != ( optional<T> const& x, optional<T> const& y ) ; R
+
+template<class T> inline bool operator <  ( optional<T> const& x, optional<T> const& y ) ; R
+
+template<class T> inline bool operator >  ( optional<T> const& x, optional<T> const& y ) ; R
+
+template<class T> inline bool operator <= ( optional<T> const& x, optional<T> const& y ) ; R
+
+template<class T> inline bool operator >= ( optional<T> const& x, optional<T> const& y ) ; R
+
+template<class T> inline bool operator == ( optional<T> const& x, none_t ) noexcept ; R
+
+template<class T> inline bool operator != ( optional<T> const& x, none_t ) noexcept ; R
+
+template<class T> inline optional<T> make_optional ( T const& v ) ; R
+
+template<class T> inline optional<std::decay_t<T>> make_optional ( T && v ) ; R
+
+template<class T> inline optional<T> make_optional ( bool condition, T const& v ) ; R
+
+template<class T> inline optional<std::decay_t<T>> make_optional ( bool condition, T && v ) ; R
+
+template<class T> inline auto get_optional_value_or ( optional<T> const& opt, typename optional<T>::reference_const_type def ) -> typename optional<T>::reference_const_type; R
+
+template<class T> inline auto get_optional_value_or ( optional<T> const& opt, typename optional<T>::reference_type def ) -> typename optional<T>::reference_type ; R
+
+template<class T> inline T const& get ( optional<T> const& opt ) ; R
+
+template<class T> inline T& get ( optional<T> & opt ) ; R
+
+template<class T> inline T const* get ( optional<T> const* opt ) ; R
+
+template<class T> inline T* get ( optional<T>* opt ) ; R
+
+template<class T> inline auto get_pointer ( optional<T> const& opt ) -> see below; R
+
+template<class T> inline auto get_pointer ( optional<T> & opt ) -> see below; R
+
+template<class T> inline void swap( optional<T>& x, optional<T>& y ) ; R
+
+template<class T> inline void swap( optional<T&>& x, optional<T&>& y ) ; R
+
+} // namespace boost
+
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/html/optional/tutorial.html b/libs/optional/doc/html/optional/tutorial.html new file mode 100644 index 00000000..1331750c --- /dev/null +++ b/libs/optional/doc/html/optional/tutorial.html @@ -0,0 +1,153 @@ + + + +Tutorial + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Consider these functions which should return a value but which might not + have a value to return: +

+
    +
  • + (A) double sqrt(double n ); +
  • +
  • + (B) char get_async_input(); +
  • +
  • + (C) point polygon::get_any_point_effectively_inside(); +
  • +
+

+ There are different approaches to the issue of not having a value to return. +

+

+ A typical approach is to consider the existence of a valid return value as + a postcondition, so that if the function cannot compute the value to return, + it has either undefined behavior (and can use assert in a debug build) or + uses a runtime check and throws an exception if the postcondition is violated. + This is a reasonable choice for example, for function (A), because the lack + of a proper return value is directly related to an invalid parameter (out + of domain argument), so it is appropriate to require the callee to supply + only parameters in a valid domain for execution to continue normally. +

+

+ However, function (B), because of its asynchronous nature, does not fail + just because it can't find a value to return; so it is incorrect to consider + such a situation an error and assert or throw an exception. This function + must return, and somehow, must tell the callee that it is not returning a + meaningful value. +

+

+ A similar situation occurs with function (C): it is conceptually an error + to ask a null-area polygon to return a point inside + itself, but in many applications, it is just impractical for performance + reasons to treat this as an error (because detecting that the polygon has + no area might be too expensive to be required to be tested previously), and + either an arbitrary point (typically at infinity) is returned, or some efficient + way to tell the callee that there is no such point is used. +

+

+ There are various mechanisms to let functions communicate that the returned + value is not valid. One such mechanism, which is quite common since it has + zero or negligible overhead, is to use a special value which is reserved + to communicate this. Classical examples of such special values are EOF, string::npos, + points at infinity, etc... +

+

+ When those values exist, i.e. the return type can hold all meaningful values + plus the signal value, this mechanism + is quite appropriate and well known. Unfortunately, there are cases when + such values do not exist. In these cases, the usual alternative is either + to use a wider type, such as int + in place of char; or a compound + type, such as std::pair<point,bool>. +

+

+ Returning a std::pair<T,bool>, thus attaching a boolean flag to the + result which indicates if the result is meaningful, has the advantage that + can be turned into a consistent idiom since the first element of the pair + can be whatever the function would conceptually return. For example, the + last two functions could have the following interface: +

+
std::pair<char,bool> get_async_input();
+std::pair<point,bool> polygon::get_any_point_effectively_inside();
+
+

+ These functions use a consistent interface for dealing with possibly nonexistent + results: +

+
std::pair<point,bool> p = poly.get_any_point_effectively_inside();
+if ( p.second )
+    flood_fill(p.first);
+
+

+ However, not only is this quite a burden syntactically, it is also error + prone since the user can easily use the function result (first element of + the pair) without ever checking if it has a valid value. +

+

+ Clearly, we need a better idiom. +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/libs/optional/doc/images/opt_align1.png b/libs/optional/doc/images/opt_align1.png new file mode 100644 index 0000000000000000000000000000000000000000..50e0205eab4aef06bdc02ac4490dd20ca50e887b GIT binary patch literal 417 zcmeAS@N?(olHy`uVBq!ia0y~yV9W%v1vuD%*=8cRV(+fa+p`U_zvmWtOm(idUVN%_zTQ7>*?qC!j0MGHfWgY( M>FVdQ&MBb@0CoSNbpQYW literal 0 HcmV?d00001 diff --git a/libs/optional/doc/images/opt_align2.png b/libs/optional/doc/images/opt_align2.png new file mode 100644 index 0000000000000000000000000000000000000000..fd7c079c9303f4797523b7ef10c775d2b42f959f GIT binary patch literal 472 zcmeAS@N?(olHy`uVBq!ia0y~yV9W%v1vuD%*?YcQW5v|j-eluqr}mVk@^Y?Hy-AQ zxD~O!Q*E1*uVcmso;i)l65Q3fz9u)SapjkB_DEFR9e$&t3_qX%+-B;_+ z+q6jI)q(f-xnlm#bAKB)r`G-H-G?`7?>_IHd);=P+ulbDZM#qHK0NvA9b2QHdvc;L zRnGHf*F0@BA=hpCDXr?5w)NR>>wi45<^K9($<3x}f7wU-UhkiO!RoE|?`5a>?B5^0 z{no?k^V!$I5j=5Aa#p>+UA=Ge_qBFb3yUK?fhzL$Uz}KyJQPVY^2Xh!^qEH{s4#5|FE0wsoOJ$Lg+};Pvt?E{*v-#} WC01}`)pr47gTd3)&t;ucLK6U}S-J!O literal 0 HcmV?d00001 diff --git a/libs/optional/doc/images/opt_align3.png b/libs/optional/doc/images/opt_align3.png new file mode 100644 index 0000000000000000000000000000000000000000..7ca6ec800eb037540b8598efab9014c68701e4ad GIT binary patch literal 468 zcmeAS@N?(olHy`uVBq!ia0y~yV9W%v1vuD%Z39%YlSDF>nFWGVcGfTs$Kds^U40^k%1!Lk37$2 z{q=m^p6z9|YU%S2-amF|O8B8^f3-d@GQMWq6}R8W{!yIf>pvlC)zeDmJ-_sRYU<1r z``pD-r|PbMX>j3RyZZ0STYbyk=YF`qy=``=RqyqnYe}g$-@h&Lv0vM_<=KigPkUCy z8k<&6-Ex0L&Xv8J?s#TzQ=2QG$Rgmtz$nh>b*puzB8NglgPMb9cHR>D3N~KXuF#t- zA*7U0x$E*Tp0p#ACr$g?CNrUM#n+ym$Ig!gziXu|u6LGqR*V1k*dSR87!wShu6{1- HoD!MliF_`N=}RMZtFHX(d0zRmL~dE8mFWC-(Te|7Yj5RN zS%y5_e0b~cwEOETPqS88Pd;tF$A{TZ z+5{9F6x0?hNzMzRo7j(f?zmGb&a*hK?Ax_@`*o*l?`}U)l-%X9V7u|ojGfZr{~5EV W#(tY5{-PZi!VI3SelF{r5}E+l@}j2z literal 0 HcmV?d00001 diff --git a/libs/optional/include/boost/none.hpp b/libs/optional/include/boost/none.hpp new file mode 100644 index 00000000..5f927cc3 --- /dev/null +++ b/libs/optional/include/boost/none.hpp @@ -0,0 +1,59 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2014, 2015 Andrzej Krzemienski. +// +// 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#ifndef BOOST_NONE_17SEP2003_HPP +#define BOOST_NONE_17SEP2003_HPP + +#include "boost/config.hpp" +#include "boost/none_t.hpp" + +// NOTE: Borland users have to include this header outside any precompiled headers +// (bcc<=5.64 cannot include instance data in a precompiled header) +// -- * To be verified, now that there's no unnamed namespace + +namespace boost { + +#ifdef BOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE + +BOOST_INLINE_VARIABLE none_t BOOST_CONSTEXPR_OR_CONST none = (static_cast(0)) ; + +#elif defined BOOST_OPTIONAL_USE_SINGLETON_DEFINITION_OF_NONE + +namespace detail { namespace optional_detail { + + // the trick here is to make boost::none defined once as a global but in a header file + template + struct none_instance + { + static const T instance; + }; + + template + const T none_instance::instance = T(); // global, but because 'tis a template, no cpp file required + +} } // namespace detail::optional_detail + + +namespace { + // TU-local + const none_t& none = detail::optional_detail::none_instance::instance; +} + +#else + +BOOST_INLINE_VARIABLE BOOST_CONSTEXPR_OR_CONST none_t none ((none_t::init_tag())); + +#endif // older definitions + +} // namespace boost + +#endif // header guard diff --git a/libs/optional/include/boost/none_t.hpp b/libs/optional/include/boost/none_t.hpp new file mode 100644 index 00000000..419a7286 --- /dev/null +++ b/libs/optional/include/boost/none_t.hpp @@ -0,0 +1,49 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2014, 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#ifndef BOOST_NONE_T_17SEP2003_HPP +#define BOOST_NONE_T_17SEP2003_HPP + +#include +#include + +#if defined (BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_REF_QUALIFIERS) \ +|| defined(BOOST_NO_CXX11_LAMBDAS) || defined(BOOST_NO_CXX11_DECLTYPE_N3276) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_NO_CXX11_DEFAULTED_MOVES) || defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + +BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Optional 1.83 and will be removed in Boost.Optional 1.86.") + +#endif + +namespace boost { + +#ifdef BOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE + +namespace detail { struct none_helper{}; } +typedef int detail::none_helper::*none_t ; + +#elif defined BOOST_OPTIONAL_USE_SINGLETON_DEFINITION_OF_NONE + +class none_t {}; + +#else + +struct none_t +{ + struct init_tag{}; + explicit BOOST_CONSTEXPR none_t(init_tag){} // to disable default constructor +}; + +#endif // old implementation workarounds + +} // namespace boost + +#endif // header guard diff --git a/libs/optional/include/boost/optional.hpp b/libs/optional/include/boost/optional.hpp new file mode 100644 index 00000000..40cf12e6 --- /dev/null +++ b/libs/optional/include/boost/optional.hpp @@ -0,0 +1,18 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#ifndef BOOST_OPTIONAL_FLC_19NOV2002_HPP +#define BOOST_OPTIONAL_FLC_19NOV2002_HPP + +#include "boost/optional/optional.hpp" + +#endif + diff --git a/libs/optional/include/boost/optional/bad_optional_access.hpp b/libs/optional/include/boost/optional/bad_optional_access.hpp new file mode 100644 index 00000000..add78675 --- /dev/null +++ b/libs/optional/include/boost/optional/bad_optional_access.hpp @@ -0,0 +1,41 @@ +// Copyright (C) 2014, Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com +// +#ifndef BOOST_BAD_OPTIONAL_ACCESS_22MAY2014_HPP +#define BOOST_BAD_OPTIONAL_ACCESS_22MAY2014_HPP + +#include +#if __cplusplus < 201103L +#include // to make converting-ctor std::string(char const*) visible +#endif + +namespace boost { + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +class bad_optional_access : public std::logic_error +{ +public: + bad_optional_access() + : std::logic_error("Attempted to access the value of an uninitialized optional object.") + {} +}; + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + +} // namespace boost + +#endif diff --git a/libs/optional/include/boost/optional/detail/experimental_traits.hpp b/libs/optional/include/boost/optional/detail/experimental_traits.hpp new file mode 100644 index 00000000..b51f5f10 --- /dev/null +++ b/libs/optional/include/boost/optional/detail/experimental_traits.hpp @@ -0,0 +1,104 @@ +// Copyright (C) 2017 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP +#define BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP + +#include +#include +#include +#include + +// The condition to use POD implementation + +#ifdef BOOST_OPTIONAL_CONFIG_NO_POD_SPEC +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif defined BOOST_OPTIONAL_CONFIG_NO_SPEC_FOR_TRIVIAL_TYPES +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif !defined BOOST_HAS_TRIVIAL_CONSTRUCTOR +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif !defined BOOST_HAS_TRIVIAL_MOVE_ASSIGN +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif !defined BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif !defined BOOST_HAS_TRIVIAL_COPY +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif !defined BOOST_HAS_TRIVIAL_ASSIGN +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif !defined BOOST_HAS_TRIVIAL_DESTRUCTOR +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif BOOST_WORKAROUND(BOOST_GCC, < 50000) +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#endif + +// GCC 5 or higher, or clang with libc++ or clang with libstdc++ 5 or higher +#if __cplusplus >= 201103L +# if BOOST_WORKAROUND(BOOST_GCC, >= 50000) +# define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS +# elif (defined BOOST_CLANG) +# if BOOST_LIB_STD_CXX > 0 +# define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS +# elif BOOST_LIB_STD_GNU >= 441200023 && BOOST_LIB_STD_GNU != 450600023 && BOOST_LIB_STD_GNU != 450600026 && BOOST_LIB_STD_GNU != 460800003 && BOOST_LIB_STD_GNU != 450400026 && BOOST_LIB_STD_GNU != 460700026 +# define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS +# endif +# endif +#endif + + +#ifndef BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS +# define BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T) BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) +#else +# include +# define BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T) std::is_trivially_default_constructible::value +#endif + + +namespace boost { namespace optional_detail { + +#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +template +struct is_type_trivially_copyable + : boost::conditional<(boost::has_trivial_copy_constructor::value && + boost::has_trivial_move_constructor::value && + boost::has_trivial_destructor::value && + boost::has_trivial_move_assign::value && + boost::has_trivial_assign::value), + boost::true_type, boost::false_type>::type +{}; +#else +template +struct is_type_trivially_copyable +: boost::conditional<(boost::is_scalar::value && !boost::is_const::value && !boost::is_volatile::value), + boost::true_type, boost::false_type>::type +{}; +#endif + + + +#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +template +struct optional_uses_direct_storage_for_ + : boost::conditional< (is_type_trivially_copyable::value && BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T)) || + (boost::is_scalar::value && !boost::is_const::value && !boost::is_volatile::value) + , boost::true_type, boost::false_type>::type +{}; +#else +template +struct optional_uses_direct_storage_for_ + : boost::conditional<(boost::is_scalar::value && !boost::is_const::value && !boost::is_volatile::value) + , boost::true_type, boost::false_type>::type +{}; +#endif + + +}} // boost::optional_detail + +#endif diff --git a/libs/optional/include/boost/optional/detail/old_optional_implementation.hpp b/libs/optional/include/boost/optional/detail/old_optional_implementation.hpp new file mode 100644 index 00000000..75d4bdcf --- /dev/null +++ b/libs/optional/include/boost/optional/detail/old_optional_implementation.hpp @@ -0,0 +1,1059 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2014-2016 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the maintainer at: +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_DETAIL_OLD_OPTIONAL_IMPLEMENTATION_AJK_28JAN2015_HPP +#define BOOST_OPTIONAL_DETAIL_OLD_OPTIONAL_IMPLEMENTATION_AJK_28JAN2015_HPP + +#include +#include +#include +#include +#include + +namespace boost { + +namespace optional_detail { + + +template +struct types_when_isnt_ref +{ + typedef T const& reference_const_type ; + typedef T & reference_type ; +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + typedef T && rval_reference_type ; + typedef T && reference_type_of_temporary_wrapper; +#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES + // GCC 4.4 has support for an early draft of rvalue references. The conforming version below + // causes warnings about returning references to a temporary. + static T&& move(T&& r) { return r; } +#else + static rval_reference_type move(reference_type r) { return boost::move(r); } +#endif +#endif + typedef T const* pointer_const_type ; + typedef T * pointer_type ; + typedef T const& argument_type ; +} ; + +template +struct types_when_is_ref +{ + typedef BOOST_DEDUCED_TYPENAME remove_reference::type raw_type ; + + typedef raw_type& reference_const_type ; + typedef raw_type& reference_type ; +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + typedef BOOST_DEDUCED_TYPENAME remove_const::type&& rval_reference_type ; + typedef raw_type& reference_type_of_temporary_wrapper; + static reference_type move(reference_type r) { return r; } +#endif + typedef raw_type* pointer_const_type ; + typedef raw_type* pointer_type ; + typedef raw_type& argument_type ; +} ; + +template +void prevent_binding_rvalue_ref_to_optional_lvalue_ref() +{ +#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES + BOOST_STATIC_ASSERT_MSG( + !boost::is_lvalue_reference::value || !boost::is_rvalue_reference::value, + "binding rvalue references to optional lvalue references is disallowed"); +#endif +} + +struct optional_tag {} ; + +template +class optional_base : public optional_tag +{ + private : + + typedef +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) + BOOST_DEDUCED_TYPENAME +#endif + ::boost::detail::make_reference_content::type internal_type ; + + typedef aligned_storage storage_type ; + + typedef types_when_isnt_ref types_when_not_ref ; + typedef types_when_is_ref types_when_ref ; + + typedef optional_base this_type ; + + protected : + + typedef T value_type ; + + typedef true_type is_reference_tag ; + typedef false_type is_not_reference_tag ; + + typedef BOOST_DEDUCED_TYPENAME is_reference::type is_reference_predicate ; + + public: + typedef BOOST_DEDUCED_TYPENAME conditional::type types ; + + protected: + typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ; + typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ; +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type rval_reference_type ; + typedef BOOST_DEDUCED_TYPENAME types::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ; +#endif + typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ; + typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ; + typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ; + + // Creates an optional uninitialized. + // No-throw + optional_base() + : + m_initialized(false) {} + + // Creates an optional uninitialized. + // No-throw + optional_base ( none_t ) + : + m_initialized(false) {} + + // Creates an optional initialized with 'val'. + // Can throw if T::T(T const&) does + optional_base ( argument_type val ) + : + m_initialized(false) + { + construct(val); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // move-construct an optional initialized from an rvalue-ref to 'val'. + // Can throw if T::T(T&&) does + optional_base ( rval_reference_type val ) + : + m_initialized(false) + { + construct( boost::move(val) ); + } +#endif + + // Creates an optional initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional. + // Can throw if T::T(T const&) does + optional_base ( bool cond, argument_type val ) + : + m_initialized(false) + { + if ( cond ) + construct(val); + } + + // Creates a deep copy of another optional + // Can throw if T::T(T const&) does + optional_base ( optional_base const& rhs ) + : + m_initialized(false) + { + if ( rhs.is_initialized() ) + construct(rhs.get_impl()); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Creates a deep move of another optional + // Can throw if T::T(T&&) does + optional_base ( optional_base&& rhs ) + : + m_initialized(false) + { + if ( rhs.is_initialized() ) + construct( boost::move(rhs.get_impl()) ); + } +#endif + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + template + explicit optional_base ( Expr&& expr, PtrExpr const* tag ) + : + m_initialized(false) + { + construct(boost::forward(expr),tag); + } + +#else + // This is used for both converting and in-place constructions. + // Derived classes use the 'tag' to select the appropriate + // implementation (the correct 'construct()' overload) + template + explicit optional_base ( Expr const& expr, Expr const* tag ) + : + m_initialized(false) + { + construct(expr,tag); + } + +#endif + + + // No-throw (assuming T::~T() doesn't) + ~optional_base() { destroy() ; } + + // Assigns from another optional (deep-copies the rhs value) + void assign ( optional_base const& rhs ) + { + if (is_initialized()) + { + if ( rhs.is_initialized() ) + assign_value(rhs.get_impl(), is_reference_predicate() ); + else destroy(); + } + else + { + if ( rhs.is_initialized() ) + construct(rhs.get_impl()); + } + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Assigns from another optional (deep-moves the rhs value) + void assign ( optional_base&& rhs ) + { + if (is_initialized()) + { + if ( rhs.is_initialized() ) + assign_value(boost::move(rhs.get_impl()), is_reference_predicate() ); + else destroy(); + } + else + { + if ( rhs.is_initialized() ) + construct(boost::move(rhs.get_impl())); + } + } +#endif + + // Assigns from another _convertible_ optional (deep-copies the rhs value) + template + void assign ( optional const& rhs ) + { + if (is_initialized()) + { + if ( rhs.is_initialized() ) +#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES + assign_value(rhs.get(), is_reference_predicate() ); +#else + assign_value(static_cast(rhs.get()), is_reference_predicate() ); +#endif + + else destroy(); + } + else + { + if ( rhs.is_initialized() ) +#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES + construct(rhs.get()); +#else + construct(static_cast(rhs.get())); +#endif + } + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // move-assigns from another _convertible_ optional (deep-moves from the rhs value) + template + void assign ( optional&& rhs ) + { + typedef BOOST_DEDUCED_TYPENAME optional::rval_reference_type ref_type; + if (is_initialized()) + { + if ( rhs.is_initialized() ) + assign_value(static_cast(rhs.get()), is_reference_predicate() ); + else destroy(); + } + else + { + if ( rhs.is_initialized() ) + construct(static_cast(rhs.get())); + } + } +#endif + + // Assigns from a T (deep-copies the rhs value) + void assign ( argument_type val ) + { + if (is_initialized()) + assign_value(val, is_reference_predicate() ); + else construct(val); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Assigns from a T (deep-moves the rhs value) + void assign ( rval_reference_type val ) + { + if (is_initialized()) + assign_value( boost::move(val), is_reference_predicate() ); + else construct( boost::move(val) ); + } +#endif + + // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED + // No-throw (assuming T::~T() doesn't) + void assign ( none_t ) BOOST_NOEXCEPT { destroy(); } + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + template + void assign_expr ( Expr&& expr, ExprPtr const* tag ) + { + if (is_initialized()) + assign_expr_to_initialized(boost::forward(expr),tag); + else construct(boost::forward(expr),tag); + } +#else + template + void assign_expr ( Expr const& expr, Expr const* tag ) + { + if (is_initialized()) + assign_expr_to_initialized(expr,tag); + else construct(expr,tag); + } +#endif + +#endif + + public : + + // Destroys the current value, if any, leaving this UNINITIALIZED + // No-throw (assuming T::~T() doesn't) + void reset() BOOST_NOEXCEPT { destroy(); } + + // **DEPRECATED** Replaces the current value -if any- with 'val' + void reset ( argument_type val ) { assign(val); } + + // Returns a pointer to the value if this is initialized, otherwise, + // returns NULL. + // No-throw + pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; } + pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; } + + bool is_initialized() const { return m_initialized ; } + + protected : + + void construct ( argument_type val ) + { + ::new (m_storage.address()) internal_type(val) ; + m_initialized = true ; + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + void construct ( rval_reference_type val ) + { + ::new (m_storage.address()) internal_type( types::move(val) ) ; + m_initialized = true ; + } +#endif + + +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) + // Constructs in-place + // upon exception *this is always uninitialized + template + void emplace_assign ( Args&&... args ) + { + destroy(); + ::new (m_storage.address()) internal_type( boost::forward(args)... ); + m_initialized = true ; + } +#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + template + void emplace_assign ( Arg&& arg ) + { + destroy(); + ::new (m_storage.address()) internal_type( boost::forward(arg) ); + m_initialized = true ; + } + + void emplace_assign () + { + destroy(); + ::new (m_storage.address()) internal_type(); + m_initialized = true ; + } +#else + template + void emplace_assign ( const Arg& arg ) + { + destroy(); + ::new (m_storage.address()) internal_type( arg ); + m_initialized = true ; + } + + template + void emplace_assign ( Arg& arg ) + { + destroy(); + ::new (m_storage.address()) internal_type( arg ); + m_initialized = true ; + } + + void emplace_assign () + { + destroy(); + ::new (m_storage.address()) internal_type(); + m_initialized = true ; + } +#endif + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Constructs in-place using the given factory + template + void construct ( Expr&& factory, in_place_factory_base const* ) + { + BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ; + boost_optional_detail::construct(factory, m_storage.address()); + m_initialized = true ; + } + + // Constructs in-place using the given typed factory + template + void construct ( Expr&& factory, typed_in_place_factory_base const* ) + { + BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ; + factory.apply(m_storage.address()) ; + m_initialized = true ; + } + + template + void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } + + // Constructs in-place using the given typed factory + template + void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } + +#else + // Constructs in-place using the given factory + template + void construct ( Expr const& factory, in_place_factory_base const* ) + { + BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ; + boost_optional_detail::construct(factory, m_storage.address()); + m_initialized = true ; + } + + // Constructs in-place using the given typed factory + template + void construct ( Expr const& factory, typed_in_place_factory_base const* ) + { + BOOST_STATIC_ASSERT ( !is_reference_predicate::value ) ; + factory.apply(m_storage.address()) ; + m_initialized = true ; + } + + template + void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } + + // Constructs in-place using the given typed factory + template + void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } +#endif + +#endif + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Constructs using any expression implicitly convertible to the single argument + // of a one-argument T constructor. + // Converting constructions of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting constructor of T from U. + template + void construct ( Expr&& expr, void const* ) + { + new (m_storage.address()) internal_type(boost::forward(expr)) ; + m_initialized = true ; + } + + // Assigns using a form any expression implicitly convertible to the single argument + // of a T's assignment operator. + // Converting assignments of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting assignment of T from U. + template + void assign_expr_to_initialized ( Expr&& expr, void const* ) + { + assign_value(boost::forward(expr), is_reference_predicate()); + } +#else + // Constructs using any expression implicitly convertible to the single argument + // of a one-argument T constructor. + // Converting constructions of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting constructor of T from U. + template + void construct ( Expr const& expr, void const* ) + { + new (m_storage.address()) internal_type(expr) ; + m_initialized = true ; + } + + // Assigns using a form any expression implicitly convertible to the single argument + // of a T's assignment operator. + // Converting assignments of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting assignment of T from U. + template + void assign_expr_to_initialized ( Expr const& expr, void const* ) + { + assign_value(expr, is_reference_predicate()); + } + +#endif + +#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION + // BCB5.64 (and probably lower versions) workaround. + // The in-place factories are supported by means of catch-all constructors + // and assignment operators (the functions are parameterized in terms of + // an arbitrary 'Expr' type) + // This compiler incorrectly resolves the overload set and sinks optional and optional + // to the 'Expr'-taking functions even though explicit overloads are present for them. + // Thus, the following overload is needed to properly handle the case when the 'lhs' + // is another optional. + // + // For VC<=70 compilers this workaround doesn't work because the compiler issues and error + // instead of choosing the wrong overload + // +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Notice that 'Expr' will be optional or optional (but not optional_base<..>) + template + void construct ( Expr&& expr, optional_tag const* ) + { + if ( expr.is_initialized() ) + { + // An exception can be thrown here. + // It it happens, THIS will be left uninitialized. + new (m_storage.address()) internal_type(types::move(expr.get())) ; + m_initialized = true ; + } + } +#else + // Notice that 'Expr' will be optional or optional (but not optional_base<..>) + template + void construct ( Expr const& expr, optional_tag const* ) + { + if ( expr.is_initialized() ) + { + // An exception can be thrown here. + // It it happens, THIS will be left uninitialized. + new (m_storage.address()) internal_type(expr.get()) ; + m_initialized = true ; + } + } +#endif +#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION + + void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; } + void assign_value ( argument_type val, is_reference_tag ) { construct(val); } +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast(val); } + void assign_value ( rval_reference_type val, is_reference_tag ) { construct( static_cast(val) ); } +#endif + + void destroy() + { + if ( m_initialized ) + destroy_impl(is_reference_predicate()) ; + } + + reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; } + reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; } + + pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; } + pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; } + + private : + + // internal_type can be either T or reference_content +#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS) + // This workaround is supposed to silence GCC warnings about broken strict aliasing rules + internal_type const* get_object() const + { + union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() }; + return caster.as_ptype; + } + internal_type * get_object() + { + union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() }; + return caster.as_ptype; + } +#else + internal_type const* get_object() const { return static_cast(m_storage.address()); } + internal_type * get_object() { return static_cast (m_storage.address()); } +#endif + + // reference_content lacks an implicit conversion to T&, so the following is needed to obtain a proper reference. + reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; } + reference_type dereference( internal_type* p, is_not_reference_tag ) { return *p ; } + reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; } + reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; } + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x581)) + void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; } +#else + void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->~T() ; m_initialized = false ; } +#endif + + void destroy_impl ( is_reference_tag ) { m_initialized = false ; } + + // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error. + // Decent compilers should disallow conversions from reference_content* to T*, but just in case, + // the following overloads are used to filter out the case and guarantee an error in case of T being a reference. + pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; } + pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; } + pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; } + pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; } + + bool m_initialized ; + storage_type m_storage ; +} ; + +} // namespace optional_detail + +template +class optional : public optional_detail::optional_base +{ + typedef optional_detail::optional_base base ; + + public : + + typedef optional this_type ; + + typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ; + typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ; + typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ; +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ; + typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ; +#endif + typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ; + typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ; + typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ; + + // Creates an optional uninitialized. + // No-throw + optional() BOOST_NOEXCEPT : base() {} + + // Creates an optional uninitialized. + // No-throw + optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {} + + // Creates an optional initialized with 'val'. + // Can throw if T::T(T const&) does + optional ( argument_type val ) : base(val) {} + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Creates an optional initialized with 'move(val)'. + // Can throw if T::T(T &&) does + optional ( rval_reference_type val ) : base( boost::forward(val) ) + {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref();} +#endif + + // Creates an optional initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional. + // Can throw if T::T(T const&) does + optional ( bool cond, argument_type val ) : base(cond,val) {} + + // NOTE: MSVC needs templated versions first + + // Creates a deep copy of another convertible optional + // Requires a valid conversion from U to T. + // Can throw if T::T(U const&) does + template + explicit optional ( optional const& rhs ) + : + base() + { + if ( rhs.is_initialized() ) + this->construct(rhs.get()); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Creates a deep move of another convertible optional + // Requires a valid conversion from U to T. + // Can throw if T::T(U&&) does + template + explicit optional ( optional && rhs ) + : + base() + { + if ( rhs.is_initialized() ) + this->construct( boost::move(rhs.get()) ); + } +#endif + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + // Creates an optional with an expression which can be either + // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n); + // (b) An instance of TypedInPlaceFactory ( i.e. in_place(a,b,...,n); + // (c) Any expression implicitly convertible to the single type + // of a one-argument T's constructor. + // (d*) Weak compilers (BCB) might also resolved Expr as optional and optional + // even though explicit overloads are present for these. + // Depending on the above some T ctor is called. + // Can throw if the resolved T ctor throws. +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + + template + explicit optional ( Expr&& expr, + BOOST_DEDUCED_TYPENAME boost::disable_if_c< + (boost::is_base_of::type>::value) || + boost::is_same::type, none_t>::value, bool >::type = true + ) + : base(boost::forward(expr),boost::addressof(expr)) + {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref();} + +#else + template + explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {} +#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +#endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + + // Creates a deep copy of another optional + // Can throw if T::T(T const&) does + optional ( optional const& rhs ) : base( static_cast(rhs) ) {} + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Creates a deep move of another optional + // Can throw if T::T(T&&) does + optional ( optional && rhs ) + BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value) + : base( boost::move(rhs) ) + {} + +#endif + // No-throw (assuming T::~T() doesn't) + ~optional() {} + +#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) + // Assigns from an expression. See corresponding constructor. + // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + template + BOOST_DEDUCED_TYPENAME boost::disable_if_c< + boost::is_base_of::type>::value || + boost::is_same::type, none_t>::value, + optional& + >::type + operator= ( Expr&& expr ) + { + optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref(); + this->assign_expr(boost::forward(expr),boost::addressof(expr)); + return *this ; + } + +#else + template + optional& operator= ( Expr const& expr ) + { + this->assign_expr(expr,boost::addressof(expr)); + return *this ; + } +#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +#endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) + + // Copy-assigns from another convertible optional (converts && deep-copies the rhs value) + // Requires a valid conversion from U to T. + // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED + template + optional& operator= ( optional const& rhs ) + { + this->assign(rhs); + return *this ; + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Move-assigns from another convertible optional (converts && deep-moves the rhs value) + // Requires a valid conversion from U to T. + // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED + template + optional& operator= ( optional && rhs ) + { + this->assign(boost::move(rhs)); + return *this ; + } +#endif + + // Assigns from another optional (deep-copies the rhs value) + // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED + // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw) + optional& operator= ( optional const& rhs ) + { + this->assign( static_cast(rhs) ) ; + return *this ; + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Assigns from another optional (deep-moves the rhs value) + optional& operator= ( optional && rhs ) + BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value) + { + this->assign( static_cast(rhs) ) ; + return *this ; + } +#endif + + // Assigns from a T (deep-copies the rhs value) + // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED + optional& operator= ( argument_type val ) + { + this->assign( val ) ; + return *this ; + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Assigns from a T (deep-moves the rhs value) + optional& operator= ( rval_reference_type val ) + { + optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref(); + this->assign( boost::move(val) ) ; + return *this ; + } +#endif + + // Assigns from a "none" + // Which destroys the current value, if any, leaving this UNINITIALIZED + // No-throw (assuming T::~T() doesn't) + optional& operator= ( none_t none_ ) BOOST_NOEXCEPT + { + this->assign( none_ ) ; + return *this ; + } + +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) + // Constructs in-place + // upon exception *this is always uninitialized + template + void emplace ( Args&&... args ) + { + this->emplace_assign( boost::forward(args)... ); + } +#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + template + void emplace ( Arg&& arg ) + { + this->emplace_assign( boost::forward(arg) ); + } + + void emplace () + { + this->emplace_assign(); + } +#else + template + void emplace ( const Arg& arg ) + { + this->emplace_assign( arg ); + } + + template + void emplace ( Arg& arg ) + { + this->emplace_assign( arg ); + } + + void emplace () + { + this->emplace_assign(); + } +#endif + + void swap( optional & arg ) + BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value) + { + // allow for Koenig lookup + boost::core::invoke_swap(*this, arg); + } + + + // Returns a reference to the value if this is initialized, otherwise, + // the behaviour is UNDEFINED + // No-throw + reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); } + reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); } + + // Returns a copy of the value if this is initialized, 'v' otherwise + reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; } + reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; } + + // Returns a pointer to the value if this is initialized, otherwise, + // the behaviour is UNDEFINED + // No-throw + pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; } + pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; } + + // Returns a reference to the value if this is initialized, otherwise, + // the behaviour is UNDEFINED + // No-throw +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + reference_const_type operator *() const& { return this->get() ; } + reference_type operator *() & { return this->get() ; } + reference_type_of_temporary_wrapper operator *() && { return base::types::move(this->get()) ; } +#else + reference_const_type operator *() const { return this->get() ; } + reference_type operator *() { return this->get() ; } +#endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS + +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + reference_const_type value() const& + { + if (this->is_initialized()) + return this->get() ; + else + throw_exception(bad_optional_access()); + } + + reference_type value() & + { + if (this->is_initialized()) + return this->get() ; + else + throw_exception(bad_optional_access()); + } + + reference_type_of_temporary_wrapper value() && + { + if (this->is_initialized()) + return base::types::move(this->get()) ; + else + throw_exception(bad_optional_access()); + } + +#else + reference_const_type value() const + { + if (this->is_initialized()) + return this->get() ; + else + throw_exception(bad_optional_access()); + } + + reference_type value() + { + if (this->is_initialized()) + return this->get() ; + else + throw_exception(bad_optional_access()); + } +#endif + + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + template + value_type value_or ( U&& v ) const& + { + if (this->is_initialized()) + return get(); + else + return boost::forward(v); + } + + template + value_type value_or ( U&& v ) && + { + if (this->is_initialized()) + return base::types::move(get()); + else + return boost::forward(v); + } +#elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + template + value_type value_or ( U&& v ) const + { + if (this->is_initialized()) + return get(); + else + return boost::forward(v); + } +#else + template + value_type value_or ( U const& v ) const + { + if (this->is_initialized()) + return get(); + else + return v; + } + + template + value_type value_or ( U& v ) const + { + if (this->is_initialized()) + return get(); + else + return v; + } +#endif + + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + template + value_type value_or_eval ( F f ) const& + { + if (this->is_initialized()) + return get(); + else + return f(); + } + + template + value_type value_or_eval ( F f ) && + { + if (this->is_initialized()) + return base::types::move(get()); + else + return f(); + } +#else + template + value_type value_or_eval ( F f ) const + { + if (this->is_initialized()) + return get(); + else + return f(); + } +#endif + + bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; } + + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() +} ; + +} // namespace boost + + +#endif // header guard diff --git a/libs/optional/include/boost/optional/detail/optional_aligned_storage.hpp b/libs/optional/include/boost/optional/detail/optional_aligned_storage.hpp new file mode 100644 index 00000000..b290921d --- /dev/null +++ b/libs/optional/include/boost/optional/detail/optional_aligned_storage.hpp @@ -0,0 +1,71 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2016 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_ALIGNED_STORAGE_AJK_12FEB2016_HPP +#define BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_ALIGNED_STORAGE_AJK_12FEB2016_HPP + +namespace boost { + +namespace optional_detail { +// This local class is used instead of that in "aligned_storage.hpp" +// because I've found the 'official' class to ICE BCB5.5 +// when some types are used with optional<> +// (due to sizeof() passed down as a non-type template parameter) +template +class aligned_storage +{ + // Borland ICEs if unnamed unions are used for this! + // BOOST_MAY_ALIAS works around GCC warnings about breaking strict aliasing rules when casting storage address to T* + union BOOST_MAY_ALIAS dummy_u + { + unsigned char data[ sizeof(T) ]; + BOOST_DEDUCED_TYPENAME type_with_alignment< + ::boost::alignment_of::value >::type aligner_; + } dummy_ ; + + public: + +#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS) + void const* address() const { return &dummy_; } + void * address() { return &dummy_; } +#else + void const* address() const { return dummy_.data; } + void * address() { return dummy_.data; } +#endif + +#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS) + // This workaround is supposed to silence GCC warnings about broken strict aliasing rules + T const* ptr_ref() const + { + union { void const* ap_pvoid; T const* as_ptype; } caster = { address() }; + return caster.as_ptype; + } + T * ptr_ref() + { + union { void* ap_pvoid; T* as_ptype; } caster = { address() }; + return caster.as_ptype; + } +#else + T const* ptr_ref() const { return static_cast(address()); } + T * ptr_ref() { return static_cast (address()); } +#endif + + T const& ref() const { return *ptr_ref(); } + T & ref() { return *ptr_ref(); } + +} ; + +} // namespace optional_detail +} // namespace boost + +#endif // header guard diff --git a/libs/optional/include/boost/optional/detail/optional_config.hpp b/libs/optional/include/boost/optional/detail/optional_config.hpp new file mode 100644 index 00000000..b5040a47 --- /dev/null +++ b/libs/optional/include/boost/optional/detail/optional_config.hpp @@ -0,0 +1,135 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2015 - 2017 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_CONFIG_AJK_28JAN2015_HPP +#define BOOST_OPTIONAL_DETAIL_OPTIONAL_CONFIG_AJK_28JAN2015_HPP + +#include +#include + +#if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES) +# define BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +#endif + +#if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700) +// AFAICT only Intel 7 correctly resolves the overload set +// that includes the in-place factory taking functions, +// so for the other icc versions, in-place factory support +// is disabled +# define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT +#endif + +#if BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x551) +// BCB (5.5.1) cannot parse the nested template struct in an inplace factory. +# define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT +#endif + +#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) \ + && defined BOOST_BCB_PARTIAL_SPECIALIZATION_BUG +// BCB (up to 5.64) has the following bug: +// If there is a member function/operator template of the form +// template mfunc( Expr expr ) ; +// some calls are resolved to this even if there are other better matches. +// The effect of this bug is that calls to converting ctors and assignments +// are incorrectly sink to this general catch-all member function template as shown above. +# define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION +#endif + +#if !defined(BOOST_NO_MAY_ALIAS) +// GCC since 3.3 and some other compilers have may_alias attribute that helps to alleviate +// optimizer issues with regard to violation of the strict aliasing rules. The optional< T > +// storage type is marked with this attribute in order to let the compiler know that it will +// alias objects of type T and silence compilation warnings. +# define BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS +#endif + +#if (defined(_MSC_VER) && _MSC_VER <= 1800) +// on MSVC 2013 and earlier an unwanted temporary is created when you assign from +// a const lvalue of integral type. Thus we bind not to the original address but +// to a temporary. +# define BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT +#endif + +#if (defined __GNUC__) && (!defined BOOST_INTEL_CXX_VERSION) && (!defined __clang__) +// On some GCC versions an unwanted temporary is created when you copy-initialize +// from a const lvalue of integral type. Thus we bind not to the original address but +// to a temporary. + +# if (__GNUC__ < 4) +# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT +# endif + +# if (__GNUC__ == 4 && __GNUC_MINOR__ <= 5) +# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT +# endif + +# if (__GNUC__ == 5 && __GNUC_MINOR__ < 2) +# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT +# endif + +# if (__GNUC__ == 5 && __GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ == 0) +# define BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT +# endif + +#endif // defined(__GNUC__) + +#if (defined __GNUC__) && (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) +// On some initial rvalue reference implementations GCC does it in a strange way, +// preferring perfect-forwarding constructor to implicit copy constructor. + +# if (__GNUC__ == 4 && __GNUC_MINOR__ == 4) +# define BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF +# endif + +# if (__GNUC__ == 4 && __GNUC_MINOR__ == 5) +# define BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF +# endif + +#endif // defined(__GNUC__) + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500) && !defined(__SUNPRO_CC) + // this condition is a copy paste from is_constructible.hpp + // I also disable SUNPRO, as it seems not to support type_traits correctly +#else +# define BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT +#endif + +#if defined __SUNPRO_CC +# define BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS +#elif (defined _MSC_FULL_VER) && (_MSC_FULL_VER < 190023026) +# define BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS +#elif defined BOOST_GCC && !defined BOOST_GCC_CXX11 +# define BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS +#elif defined BOOST_GCC_VERSION && BOOST_GCC_VERSION < 40800 +# define BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS +#endif + + +// Detect support for defaulting move operations +// (some older compilers implement rvalue references, +// defaulted functions but move operations are not special members and cannot be defaulted) + +#ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +# define BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS +#elif BOOST_WORKAROUND(BOOST_MSVC, < 1900) +# define BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS +#elif BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40600) +# define BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS +#endif + + +#ifdef BOOST_OPTIONAL_CONFIG_NO_DIRECT_STORAGE_SPEC +# define BOOST_OPTIONAL_DETAIL_NO_DIRECT_STORAGE_SPEC +#endif + + +#endif // header guard diff --git a/libs/optional/include/boost/optional/detail/optional_factory_support.hpp b/libs/optional/include/boost/optional/detail/optional_factory_support.hpp new file mode 100644 index 00000000..efff92a5 --- /dev/null +++ b/libs/optional/include/boost/optional/detail/optional_factory_support.hpp @@ -0,0 +1,36 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2016 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_FACTORY_SUPPORT_AJK_12FEB2016_HPP +#define BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_FACTORY_SUPPORT_AJK_12FEB2016_HPP + +// Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<> +// member template of a factory as used in the optional<> implementation. +// He proposed this simple fix which is to move the call to apply<> outside +// namespace boost. +namespace boost_optional_detail +{ + template + inline void construct(Factory const& factory, void* address) + { + factory.BOOST_NESTED_TEMPLATE apply(address); + } +} + +namespace boost +{ + class in_place_factory_base ; + class typed_in_place_factory_base ; +} + +#endif // header guard diff --git a/libs/optional/include/boost/optional/detail/optional_hash.hpp b/libs/optional/include/boost/optional/detail/optional_hash.hpp new file mode 100644 index 00000000..234ee7b6 --- /dev/null +++ b/libs/optional/include/boost/optional/detail/optional_hash.hpp @@ -0,0 +1,49 @@ +// Copyright (C) 2022 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_HASH_AJK_20MAY2022_HPP +#define BOOST_OPTIONAL_DETAIL_OPTIONAL_HASH_AJK_20MAY2022_HPP + +#include +#include + +#if !defined(BOOST_OPTIONAL_CONFIG_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) + +#include + +namespace std +{ + template + struct hash > + { + typedef std::size_t result_type; + typedef boost::optional argument_type; + + BOOST_CONSTEXPR result_type operator()(const argument_type& arg) const { + return arg ? std::hash()(*arg) : result_type(); + } + }; + + template + struct hash > + { + typedef std::size_t result_type; + typedef boost::optional argument_type; + + BOOST_CONSTEXPR result_type operator()(const argument_type& arg) const { + return arg ? std::hash()(*arg) : result_type(); + } + }; +} + +#endif // !defined(BOOST_OPTIONAL_CONFIG_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) + +#endif // header guard diff --git a/libs/optional/include/boost/optional/detail/optional_reference_spec.hpp b/libs/optional/include/boost/optional/detail/optional_reference_spec.hpp new file mode 100644 index 00000000..b013f0b5 --- /dev/null +++ b/libs/optional/include/boost/optional/detail/optional_reference_spec.hpp @@ -0,0 +1,279 @@ +// Copyright (C) 2015-2018 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP +#define BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP + +#ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT +#include +#include +#endif + +# if 1 + +namespace boost { + +namespace detail { + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + +template +void prevent_binding_rvalue() +{ +#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES + BOOST_STATIC_ASSERT_MSG(boost::is_lvalue_reference::value, + "binding rvalue references to optional lvalue references is disallowed"); +#endif +} + +template +BOOST_DEDUCED_TYPENAME boost::remove_reference::type& forward_reference(T&& r) +{ + BOOST_STATIC_ASSERT_MSG(boost::is_lvalue_reference::value, + "binding rvalue references to optional lvalue references is disallowed"); + return boost::forward(r); +} + +#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + +template +struct is_const_integral +{ + static const bool value = boost::is_const::value && boost::is_integral::value; +}; + +template +struct is_const_integral_bad_for_conversion +{ +#if (!defined BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES) && (defined BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT) + static const bool value = boost::is_const::value && boost::is_integral::value; +#else + static const bool value = false; +#endif +}; + +template +void prevent_assignment_from_false_const_integral() +{ +#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES +#ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT + // MSVC compiler without rvalue references: we need to disable the assignment from + // const integral lvalue reference, as it may be an invalid temporary + BOOST_STATIC_ASSERT_MSG(!is_const_integral::value, + "binding const lvalue references to integral types is disabled in this compiler"); +#endif +#endif +} + + +template +struct is_optional_ +{ + static const bool value = false; +}; + +template +struct is_optional_< ::boost::optional > +{ + static const bool value = true; +}; + +template +struct is_no_optional +{ + static const bool value = !is_optional_::type>::value; +}; + + +template + struct is_same_decayed + { + static const bool value = ::boost::is_same::type>::value + || ::boost::is_same::type>::value; + }; + +template +struct no_unboxing_cond +{ + static const bool value = is_no_optional::value && !is_same_decayed::value; +}; + + +} // namespace detail + +template +class optional : public optional_detail::optional_tag +{ + T* ptr_; + +public: + typedef T& value_type; + typedef T& reference_type; + typedef T& reference_const_type; + typedef T& rval_reference_type; + typedef T* pointer_type; + typedef T* pointer_const_type; + + optional() BOOST_NOEXCEPT : ptr_() {} + optional(none_t) BOOST_NOEXCEPT : ptr_() {} + + template + explicit optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {} + optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {} + + // the following two implement a 'conditionally explicit' constructor: condition is a hack for buggy compilers with screwed conversion construction from const int + template + explicit optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && detail::is_const_integral_bad_for_conversion::value, bool>::type = true) BOOST_NOEXCEPT + : ptr_(boost::addressof(rhs)) {} + + template + optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && !detail::is_const_integral_bad_for_conversion::value, bool>::type = true) BOOST_NOEXCEPT + : ptr_(boost::addressof(rhs)) {} + + optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; } + template + optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; } + optional& operator=(none_t) BOOST_NOEXCEPT { ptr_ = 0; return *this; } + + + void swap(optional& rhs) BOOST_NOEXCEPT { std::swap(ptr_, rhs.ptr_); } + T& get() const { BOOST_ASSERT(ptr_); return *ptr_; } + + T* get_ptr() const BOOST_NOEXCEPT { return ptr_; } + T* operator->() const { BOOST_ASSERT(ptr_); return ptr_; } + T& operator*() const { BOOST_ASSERT(ptr_); return *ptr_; } + + T& value() const + { + if (this->is_initialized()) + return this->get(); + else + throw_exception(bad_optional_access()); + } + + bool operator!() const BOOST_NOEXCEPT { return ptr_ == 0; } + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + + void reset() BOOST_NOEXCEPT { ptr_ = 0; } + + bool is_initialized() const BOOST_NOEXCEPT { return ptr_ != 0; } + bool has_value() const BOOST_NOEXCEPT { return ptr_ != 0; } + + template + optional::type> map(F f) const + { + if (this->has_value()) + return f(this->get()); + else + return none; + } + + template + optional::type>::type> flat_map(F f) const + { + if (this->has_value()) + return f(get()); + else + return none; + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + optional(T&& /* rhs */) BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); } + + template + optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT + : ptr_(boost::addressof(r)) { detail::prevent_binding_rvalue(); } + + template + optional(bool cond, R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT + : ptr_(cond ? boost::addressof(r) : 0) { detail::prevent_binding_rvalue(); } + + template + BOOST_DEDUCED_TYPENAME boost::enable_if, optional&>::type + operator=(R&& r) BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); ptr_ = boost::addressof(r); return *this; } + + template + void emplace(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT + { detail::prevent_binding_rvalue(); ptr_ = boost::addressof(r); } + + template + T& get_value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) const BOOST_NOEXCEPT + { detail::prevent_binding_rvalue(); return ptr_ ? *ptr_ : r; } + + template + T& value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) const BOOST_NOEXCEPT + { detail::prevent_binding_rvalue(); return ptr_ ? *ptr_ : r; } + + template + void reset(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT + { detail::prevent_binding_rvalue(); ptr_ = boost::addressof(r); } + + template + T& value_or_eval(F f) const { return ptr_ ? *ptr_ : detail::forward_reference(f()); } + +#else // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + + // the following two implement a 'conditionally explicit' constructor + template + explicit optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && detail::is_const_integral_bad_for_conversion::value, bool>::type = true) BOOST_NOEXCEPT + : ptr_(boost::addressof(v)) { } + + template + optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && !detail::is_const_integral_bad_for_conversion::value, bool>::type = true) BOOST_NOEXCEPT + : ptr_(boost::addressof(v)) { } + + template + optional(bool cond, U& v, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(v) : 0) {} + + template + BOOST_DEDUCED_TYPENAME boost::enable_if, optional&>::type + operator=(U& v) BOOST_NOEXCEPT + { + detail::prevent_assignment_from_false_const_integral(); + ptr_ = boost::addressof(v); return *this; + } + + template + void emplace(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT + { ptr_ = boost::addressof(v); } + + template + T& get_value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) const BOOST_NOEXCEPT + { return ptr_ ? *ptr_ : v; } + + template + T& value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) const BOOST_NOEXCEPT + { return ptr_ ? *ptr_ : v; } + + template + void reset(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT + { ptr_ = boost::addressof(v); } + + template + T& value_or_eval(F f) const { return ptr_ ? *ptr_ : f(); } + +#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +}; + +template + void swap ( optional& x, optional& y) BOOST_NOEXCEPT +{ + x.swap(y); +} + +} // namespace boost + +#endif // 1/0 + +#endif // header guard diff --git a/libs/optional/include/boost/optional/detail/optional_relops.hpp b/libs/optional/include/boost/optional/detail/optional_relops.hpp new file mode 100644 index 00000000..1c155787 --- /dev/null +++ b/libs/optional/include/boost/optional/detail/optional_relops.hpp @@ -0,0 +1,196 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_RELOPS_AJK_03OCT2015_HPP +#define BOOST_OPTIONAL_DETAIL_OPTIONAL_RELOPS_AJK_03OCT2015_HPP + +namespace boost { + +// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values). +// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointees() in generic code instead. + + +// +// optional vs optional cases +// + +template +inline +bool operator == ( optional const& x, optional const& y ) +{ return bool(x) && bool(y) ? *x == *y : bool(x) == bool(y); } + +template +inline +bool operator < ( optional const& x, optional const& y ) +{ return less_pointees(x,y); } + +template +inline +bool operator != ( optional const& x, optional const& y ) +{ return !( x == y ) ; } + +template +inline +bool operator > ( optional const& x, optional const& y ) +{ return y < x ; } + +template +inline +bool operator <= ( optional const& x, optional const& y ) +{ return !( y < x ) ; } + +template +inline +bool operator >= ( optional const& x, optional const& y ) +{ return !( x < y ) ; } + + +// +// optional vs T cases +// +template +inline +bool operator == ( optional const& x, T const& y ) +{ return equal_pointees(x, optional(y)); } + +template +inline +bool operator < ( optional const& x, T const& y ) +{ return less_pointees(x, optional(y)); } + +template +inline +bool operator != ( optional const& x, T const& y ) +{ return !( x == y ) ; } + +template +inline +bool operator > ( optional const& x, T const& y ) +{ return y < x ; } + +template +inline +bool operator <= ( optional const& x, T const& y ) +{ return !( y < x ) ; } + +template +inline +bool operator >= ( optional const& x, T const& y ) +{ return !( x < y ) ; } + +// +// T vs optional cases +// + +template +inline +bool operator == ( T const& x, optional const& y ) +{ return equal_pointees( optional(x), y ); } + +template +inline +bool operator < ( T const& x, optional const& y ) +{ return less_pointees( optional(x), y ); } + +template +inline +bool operator != ( T const& x, optional const& y ) +{ return !( x == y ) ; } + +template +inline +bool operator > ( T const& x, optional const& y ) +{ return y < x ; } + +template +inline +bool operator <= ( T const& x, optional const& y ) +{ return !( y < x ) ; } + +template +inline +bool operator >= ( T const& x, optional const& y ) +{ return !( x < y ) ; } + + +// +// optional vs none cases +// + +template +inline +bool operator == ( optional const& x, none_t ) BOOST_NOEXCEPT +{ return !x; } + +template +inline +bool operator < ( optional const& x, none_t ) +{ return less_pointees(x,optional() ); } + +template +inline +bool operator != ( optional const& x, none_t ) BOOST_NOEXCEPT +{ return bool(x); } + +template +inline +bool operator > ( optional const& x, none_t y ) +{ return y < x ; } + +template +inline +bool operator <= ( optional const& x, none_t y ) +{ return !( y < x ) ; } + +template +inline +bool operator >= ( optional const& x, none_t y ) +{ return !( x < y ) ; } + +// +// none vs optional cases +// + +template +inline +bool operator == ( none_t , optional const& y ) BOOST_NOEXCEPT +{ return !y; } + +template +inline +bool operator < ( none_t , optional const& y ) +{ return less_pointees(optional() ,y); } + +template +inline +bool operator != ( none_t, optional const& y ) BOOST_NOEXCEPT +{ return bool(y); } + +template +inline +bool operator > ( none_t x, optional const& y ) +{ return y < x ; } + +template +inline +bool operator <= ( none_t x, optional const& y ) +{ return !( y < x ) ; } + +template +inline +bool operator >= ( none_t x, optional const& y ) +{ return !( x < y ) ; } + +} // namespace boost + +#endif // header guard + diff --git a/libs/optional/include/boost/optional/detail/optional_swap.hpp b/libs/optional/include/boost/optional/detail/optional_swap.hpp new file mode 100644 index 00000000..f4eceabb --- /dev/null +++ b/libs/optional/include/boost/optional/detail/optional_swap.hpp @@ -0,0 +1,117 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP +#define BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP + +#include +#include + +namespace boost { + +namespace optional_detail { + +template struct swap_selector; + +template <> +struct swap_selector +{ + template + static void optional_swap ( optional& x, optional& y ) + { + const bool hasX = !!x; + const bool hasY = !!y; + + if ( !hasX && !hasY ) + return; + + if( !hasX ) + x.emplace(); + else if ( !hasY ) + y.emplace(); + + // Boost.Core.Swap will take care of ADL and workarounds for broken compilers + boost::core::invoke_swap(x.get(), y.get()); + + if( !hasX ) + y = boost::none ; + else if( !hasY ) + x = boost::none ; + } +}; + +#ifdef BOOST_OPTIONAL_DETAIL_MOVE +# undef BOOST_OPTIONAL_DETAIL_MOVE +#endif + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) boost::move(EXPR_) +#else +# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) EXPR_ +#endif + +template <> +struct swap_selector +{ + template + static void optional_swap ( optional& x, optional& y ) + //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && BOOST_NOEXCEPT_EXPR(boost::core::invoke_swap(*x, *y))) + { + if (x) + { + if (y) + { + boost::core::invoke_swap(*x, *y); + } + else + { + y = BOOST_OPTIONAL_DETAIL_MOVE(*x); + x = boost::none; + } + } + else + { + if (y) + { + x = BOOST_OPTIONAL_DETAIL_MOVE(*y); + y = boost::none; + } + } + } +}; + +} // namespace optional_detail + +#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_CONFIG_RESTORE_OBSOLETE_SWAP_IMPLEMENTATION) + +template +struct optional_swap_should_use_default_constructor : boost::false_type {} ; + +#else + +template +struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor {} ; + +#endif + +template +inline void swap ( optional& x, optional& y ) +//BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && BOOST_NOEXCEPT_EXPR(boost::core::invoke_swap(*x, *y))) +{ + optional_detail::swap_selector::value>::optional_swap(x, y); +} + +} // namespace boost + +#undef BOOST_OPTIONAL_DETAIL_MOVE + +#endif // header guard diff --git a/libs/optional/include/boost/optional/detail/optional_trivially_copyable_base.hpp b/libs/optional/include/boost/optional/detail/optional_trivially_copyable_base.hpp new file mode 100644 index 00000000..8d98a844 --- /dev/null +++ b/libs/optional/include/boost/optional/detail/optional_trivially_copyable_base.hpp @@ -0,0 +1,510 @@ +// Copyright (C) 2017 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +// trivially-copyable version of the storage + +template +class tc_optional_base : public optional_tag +{ + private : + + typedef tc_optional_base this_type ; + + protected : + + typedef T value_type ; + + protected: + typedef T & reference_type ; + typedef T const& reference_const_type ; +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + typedef T && rval_reference_type ; + typedef T && reference_type_of_temporary_wrapper ; +#endif + typedef T * pointer_type ; + typedef T const* pointer_const_type ; + typedef T const& argument_type ; + + tc_optional_base() + : + m_initialized(false) {} + + tc_optional_base ( none_t ) + : + m_initialized(false) {} + + tc_optional_base ( init_value_tag, argument_type val ) + : + m_initialized(true), m_storage(val) {} + + tc_optional_base ( bool cond, argument_type val ) + : + m_initialized(cond), m_storage(val) {} + + // tc_optional_base ( tc_optional_base const& ) = default; + + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + template + explicit tc_optional_base ( Expr&& expr, PtrExpr const* tag ) + : + m_initialized(false) + { + construct(boost::forward(expr),tag); + } + +#else + // This is used for both converting and in-place constructions. + // Derived classes use the 'tag' to select the appropriate + // implementation (the correct 'construct()' overload) + template + explicit tc_optional_base ( Expr const& expr, Expr const* tag ) + : + m_initialized(false) + { + construct(expr,tag); + } + +#endif + + // tc_optional_base& operator= ( tc_optional_base const& ) = default; + // ~tc_optional_base() = default; + + // Assigns from another optional (deep-copies the rhs value) + void assign ( tc_optional_base const& rhs ) + { + *this = rhs; + } + + // Assigns from another _convertible_ optional (deep-copies the rhs value) + template + void assign ( optional const& rhs ) + { + if ( rhs.is_initialized() ) +#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES + m_storage = rhs.get(); +#else + m_storage = static_cast(rhs.get()); +#endif + + m_initialized = rhs.is_initialized(); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // move-assigns from another _convertible_ optional (deep-moves from the rhs value) + template + void assign ( optional&& rhs ) + { + typedef BOOST_DEDUCED_TYPENAME optional::rval_reference_type ref_type; + if ( rhs.is_initialized() ) + m_storage = static_cast(rhs.get()); + m_initialized = rhs.is_initialized(); + } +#endif + + void assign ( argument_type val ) + { + construct(val); + } + + void assign ( none_t ) { destroy(); } + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + template + void assign_expr ( Expr&& expr, ExprPtr const* tag ) + { + construct(boost::forward(expr),tag); + } +#else + template + void assign_expr ( Expr const& expr, Expr const* tag ) + { + construct(expr,tag); + } +#endif + +#endif + + public : + + // Destroys the current value, if any, leaving this UNINITIALIZED + // No-throw (assuming T::~T() doesn't) + void reset() BOOST_NOEXCEPT { destroy(); } + + // **DEPRECATED** Replaces the current value -if any- with 'val' + void reset ( argument_type val ) BOOST_NOEXCEPT { assign(val); } + + // Returns a pointer to the value if this is initialized, otherwise, + // returns NULL. + // No-throw + pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; } + pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; } + + bool is_initialized() const { return m_initialized ; } + + protected : + + void construct ( argument_type val ) + { + m_storage = val ; + m_initialized = true ; + } + + +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) + // Constructs in-place + // upon exception *this is always uninitialized + template + void construct ( in_place_init_t, Args&&... args ) + { + m_storage = value_type( boost::forward(args)... ) ; + m_initialized = true ; + } + + template + void emplace_assign ( Args&&... args ) + { + construct(in_place_init, boost::forward(args)...); + } + + template + explicit tc_optional_base ( in_place_init_t, Args&&... args ) + : + m_initialized(false) + { + construct(in_place_init, boost::forward(args)...); + } + + template + explicit tc_optional_base ( in_place_init_if_t, bool cond, Args&&... args ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init, boost::forward(args)...); + } +#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + template + void construct ( in_place_init_t, Arg&& arg ) + { + m_storage = value_type( boost::forward(arg) ); + m_initialized = true ; + } + + void construct ( in_place_init_t ) + { + m_storage = value_type(); + m_initialized = true ; + } + + template + void emplace_assign ( Arg&& arg ) + { + construct(in_place_init, boost::forward(arg)) ; + } + + void emplace_assign () + { + construct(in_place_init) ; + } + + template + explicit tc_optional_base ( in_place_init_t, Arg&& arg ) + : + m_initialized(false) + { + construct(in_place_init, boost::forward(arg)); + } + + explicit tc_optional_base ( in_place_init_t ) + : + m_initialized(false), m_storage() {} + + template + explicit tc_optional_base ( in_place_init_if_t, bool cond, Arg&& arg ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init, boost::forward(arg)); + } + + explicit tc_optional_base ( in_place_init_if_t, bool cond ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init); + } + +#else + + template + void construct ( in_place_init_t, const Arg& arg ) + { + m_storage = value_type( arg ); + m_initialized = true ; + } + + template + void construct ( in_place_init_t, Arg& arg ) + { + m_storage = value_type( arg ); + m_initialized = true ; + } + + void construct ( in_place_init_t ) + { + m_storage = value_type(); + m_initialized = true ; + } + + template + void emplace_assign ( const Arg& arg ) + { + construct(in_place_init, arg); + } + + template + void emplace_assign ( Arg& arg ) + { + construct(in_place_init, arg); + } + + void emplace_assign () + { + construct(in_place_init); + } + + template + explicit tc_optional_base ( in_place_init_t, const Arg& arg ) + : m_initialized(false) + { + construct(in_place_init, arg); + } + + template + explicit tc_optional_base ( in_place_init_t, Arg& arg ) + : m_initialized(false) + { + construct(in_place_init, arg); + } + + explicit tc_optional_base ( in_place_init_t ) + : m_initialized(false) + { + construct(in_place_init); + } + + template + explicit tc_optional_base ( in_place_init_if_t, bool cond, const Arg& arg ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init, arg); + } + + template + explicit tc_optional_base ( in_place_init_if_t, bool cond, Arg& arg ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init, arg); + } + + explicit tc_optional_base ( in_place_init_if_t, bool cond ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init); + } +#endif + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Constructs in-place using the given factory + template + void construct ( Expr&& factory, in_place_factory_base const* ) + { + boost_optional_detail::construct(factory, boost::addressof(m_storage)); + m_initialized = true ; + } + + // Constructs in-place using the given typed factory + template + void construct ( Expr&& factory, typed_in_place_factory_base const* ) + { + factory.apply(boost::addressof(m_storage)) ; + m_initialized = true ; + } + + template + void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } + + // Constructs in-place using the given typed factory + template + void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } + +#else + // Constructs in-place using the given factory + template + void construct ( Expr const& factory, in_place_factory_base const* ) + { + boost_optional_detail::construct(factory, boost::addressof(m_storage)); + m_initialized = true ; + } + + // Constructs in-place using the given typed factory + template + void construct ( Expr const& factory, typed_in_place_factory_base const* ) + { + factory.apply(boost::addressof(m_storage)) ; + m_initialized = true ; + } + + template + void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } + + // Constructs in-place using the given typed factory + template + void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } +#endif + +#endif + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Constructs using any expression implicitly convertible to the single argument + // of a one-argument T constructor. + // Converting constructions of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting constructor of T from U. + template + void construct ( Expr&& expr, void const* ) + { + m_storage = value_type(boost::forward(expr)) ; + m_initialized = true ; + } + + // Assigns using a form any expression implicitly convertible to the single argument + // of a T's assignment operator. + // Converting assignments of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting assignment of T from U. + template + void assign_expr_to_initialized ( Expr&& expr, void const* ) + { + assign_value( boost::forward(expr) ); + } +#else + // Constructs using any expression implicitly convertible to the single argument + // of a one-argument T constructor. + // Converting constructions of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting constructor of T from U. + template + void construct ( Expr const& expr, void const* ) + { + m_storage = value_type(expr) ; + m_initialized = true ; + } + + // Assigns using a form any expression implicitly convertible to the single argument + // of a T's assignment operator. + // Converting assignments of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting assignment of T from U. + template + void assign_expr_to_initialized ( Expr const& expr, void const* ) + { + assign_value(expr); + } + +#endif + +#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION + // BCB5.64 (and probably lower versions) workaround. + // The in-place factories are supported by means of catch-all constructors + // and assignment operators (the functions are parameterized in terms of + // an arbitrary 'Expr' type) + // This compiler incorrectly resolves the overload set and sinks optional and optional + // to the 'Expr'-taking functions even though explicit overloads are present for them. + // Thus, the following overload is needed to properly handle the case when the 'lhs' + // is another optional. + // + // For VC<=70 compilers this workaround doesn't work because the compiler issues and error + // instead of choosing the wrong overload + // +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Notice that 'Expr' will be optional or optional (but not tc_optional_base<..>) + template + void construct ( Expr&& expr, optional_tag const* ) + { + if ( expr.is_initialized() ) + { + // An exception can be thrown here. + // It it happens, THIS will be left uninitialized. + m_storage = value_type(boost::move(expr.get())) ; + m_initialized = true ; + } + } +#else + // Notice that 'Expr' will be optional or optional (but not tc_optional_base<..>) + template + void construct ( Expr const& expr, optional_tag const* ) + { + if ( expr.is_initialized() ) + { + // An exception can be thrown here. + // It it happens, THIS will be left uninitialized. + m_storage = value_type(expr.get()) ; + m_initialized = true ; + } + } +#endif +#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION + + void assign_value ( argument_type val ) { m_storage = val; } +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + void assign_value ( rval_reference_type val ) { m_storage = static_cast(val); } +#endif + + void destroy() + { + m_initialized = false; + } + + reference_const_type get_impl() const { return m_storage ; } + reference_type get_impl() { return m_storage ; } + + pointer_const_type get_ptr_impl() const { return boost::addressof(m_storage); } + pointer_type get_ptr_impl() { return boost::addressof(m_storage); } + + private : + + bool m_initialized ; + T m_storage ; +} ; diff --git a/libs/optional/include/boost/optional/optional.hpp b/libs/optional/include/boost/optional/optional.hpp new file mode 100644 index 00000000..f5fdf992 --- /dev/null +++ b/libs/optional/include/boost/optional/optional.hpp @@ -0,0 +1,1666 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2014 - 2021 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +// Revisions: +// 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen +// 05 May 2014 (Added move semantics) Andrzej Krzemienski +// +#ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP +#define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP + +#include +#ifndef BOOST_NO_IOSTREAM +#include +#endif // BOOST_NO_IOSTREAM + +#ifdef BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost { namespace optional_detail { + +template +struct optional_value_type +{ +}; + +template +struct optional_value_type< ::boost::optional > +{ + typedef T type; +}; + +}} // namespace boost::optional_detail + +#ifdef BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL +#include +#else +namespace boost { + +namespace optional_ns { + +// a tag for in-place initialization of contained value +struct in_place_init_t +{ + struct init_tag{}; + explicit in_place_init_t(init_tag){} +}; +const in_place_init_t in_place_init ((in_place_init_t::init_tag())); + +// a tag for conditional in-place initialization of contained value +struct in_place_init_if_t +{ + struct init_tag{}; + explicit in_place_init_if_t(init_tag){} +}; +const in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag())); + +} // namespace optional_ns + +using optional_ns::in_place_init_t; +using optional_ns::in_place_init; +using optional_ns::in_place_init_if_t; +using optional_ns::in_place_init_if; + +namespace optional_detail { + +struct init_value_tag {}; + +struct optional_tag {}; + + +template +class optional_base : public optional_tag +{ + private : + + typedef aligned_storage storage_type ; + typedef optional_base this_type ; + + protected : + + typedef T value_type ; + typedef typename boost::remove_const::type unqualified_value_type; + + protected: + typedef T & reference_type ; + typedef T const& reference_const_type ; +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + typedef T && rval_reference_type ; + typedef T && reference_type_of_temporary_wrapper ; +#endif + typedef T * pointer_type ; + typedef T const* pointer_const_type ; + typedef T const& argument_type ; + + // Creates an optional uninitialized. + // No-throw + optional_base() + : + m_initialized(false) {} + + // Creates an optional uninitialized. + // No-throw + optional_base ( none_t ) + : + m_initialized(false) {} + + // Creates an optional initialized with 'val'. + // Can throw if T::T(T const&) does + optional_base ( init_value_tag, argument_type val ) + : + m_initialized(false) + { + construct(val); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // move-construct an optional initialized from an rvalue-ref to 'val'. + // Can throw if T::T(T&&) does + optional_base ( init_value_tag, rval_reference_type val ) + : + m_initialized(false) + { + construct( boost::move(val) ); + } +#endif + + // Creates an optional initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional. + // Can throw if T::T(T const&) does + optional_base ( bool cond, argument_type val ) + : + m_initialized(false) + { + if ( cond ) + construct(val); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Creates an optional initialized with 'move(val)' IFF cond is true, otherwise creates an uninitialized optional. + // Can throw if T::T(T &&) does + optional_base ( bool cond, rval_reference_type val ) + : + m_initialized(false) + { + if ( cond ) + construct(boost::move(val)); + } +#endif + + // Creates a deep copy of another optional + // Can throw if T::T(T const&) does + optional_base ( optional_base const& rhs ) + : + m_initialized(false) + { + if ( rhs.is_initialized() ) + construct(rhs.get_impl()); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Creates a deep move of another optional + // Can throw if T::T(T&&) does + optional_base ( optional_base&& rhs ) + BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value) + : + m_initialized(false) + { + if ( rhs.is_initialized() ) + construct( boost::move(rhs.get_impl()) ); + } +#endif + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + template + explicit optional_base ( Expr&& expr, PtrExpr const* tag ) + : + m_initialized(false) + { + construct(boost::forward(expr),tag); + } + +#else + // This is used for both converting and in-place constructions. + // Derived classes use the 'tag' to select the appropriate + // implementation (the correct 'construct()' overload) + template + explicit optional_base ( Expr const& expr, Expr const* tag ) + : + m_initialized(false) + { + construct(expr,tag); + } + +#endif + + optional_base& operator= ( optional_base const& rhs ) + { + this->assign(rhs); + return *this; + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + optional_base& operator= ( optional_base && rhs ) + BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value) + { + this->assign(static_cast(rhs)); + return *this; + } +#endif + + // No-throw (assuming T::~T() doesn't) + ~optional_base() { destroy() ; } + + // Assigns from another optional (deep-copies the rhs value) + void assign ( optional_base const& rhs ) + { + if (is_initialized()) + { + if ( rhs.is_initialized() ) + assign_value(rhs.get_impl()); + else destroy(); + } + else + { + if ( rhs.is_initialized() ) + construct(rhs.get_impl()); + } + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Assigns from another optional (deep-moves the rhs value) + void assign ( optional_base&& rhs ) + { + if (is_initialized()) + { + if ( rhs.is_initialized() ) + assign_value( boost::move(rhs.get_impl()) ); + else destroy(); + } + else + { + if ( rhs.is_initialized() ) + construct(boost::move(rhs.get_impl())); + } + } +#endif + + // Assigns from another _convertible_ optional (deep-copies the rhs value) + template + void assign ( optional const& rhs ) + { + if (is_initialized()) + { + if ( rhs.is_initialized() ) +#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES + assign_value( rhs.get() ); +#else + assign_value( static_cast(rhs.get()) ); +#endif + + else destroy(); + } + else + { + if ( rhs.is_initialized() ) +#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES + construct(rhs.get()); +#else + construct(static_cast(rhs.get())); +#endif + } + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // move-assigns from another _convertible_ optional (deep-moves from the rhs value) + template + void assign ( optional&& rhs ) + { + typedef BOOST_DEDUCED_TYPENAME optional::rval_reference_type ref_type; + if (is_initialized()) + { + if ( rhs.is_initialized() ) + assign_value( static_cast(rhs.get()) ); + else destroy(); + } + else + { + if ( rhs.is_initialized() ) + construct(static_cast(rhs.get())); + } + } +#endif + + // Assigns from a T (deep-copies the rhs value) + void assign ( argument_type val ) + { + if (is_initialized()) + assign_value(val); + else construct(val); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Assigns from a T (deep-moves the rhs value) + void assign ( rval_reference_type val ) + { + if (is_initialized()) + assign_value( boost::move(val) ); + else construct( boost::move(val) ); + } +#endif + + // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED + // No-throw (assuming T::~T() doesn't) + void assign ( none_t ) BOOST_NOEXCEPT { destroy(); } + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + template + void assign_expr ( Expr&& expr, ExprPtr const* tag ) + { + if (is_initialized()) + assign_expr_to_initialized(boost::forward(expr),tag); + else construct(boost::forward(expr),tag); + } +#else + template + void assign_expr ( Expr const& expr, Expr const* tag ) + { + if (is_initialized()) + assign_expr_to_initialized(expr,tag); + else construct(expr,tag); + } +#endif + +#endif + + public : + + // Destroys the current value, if any, leaving this UNINITIALIZED + // No-throw (assuming T::~T() doesn't) + void reset() BOOST_NOEXCEPT { destroy(); } + + // **DEPRECATED** Replaces the current value -if any- with 'val' + void reset ( argument_type val ) { assign(val); } + + // Returns a pointer to the value if this is initialized, otherwise, + // returns NULL. + // No-throw + pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; } + pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; } + + bool is_initialized() const BOOST_NOEXCEPT { return m_initialized ; } + + protected : + + void construct ( argument_type val ) + { + ::new (m_storage.address()) unqualified_value_type(val) ; + m_initialized = true ; + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + void construct ( rval_reference_type val ) + { + ::new (m_storage.address()) unqualified_value_type( boost::move(val) ) ; + m_initialized = true ; + } +#endif + + +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) + // Constructs in-place + // upon exception *this is always uninitialized + template + void construct ( in_place_init_t, Args&&... args ) + { + ::new (m_storage.address()) unqualified_value_type( boost::forward(args)... ) ; + m_initialized = true ; + } + + template + void emplace_assign ( Args&&... args ) + { + destroy(); + construct(in_place_init, boost::forward(args)...); + } + + template + explicit optional_base ( in_place_init_t, Args&&... args ) + : + m_initialized(false) + { + construct(in_place_init, boost::forward(args)...); + } + + template + explicit optional_base ( in_place_init_if_t, bool cond, Args&&... args ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init, boost::forward(args)...); + } +#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + template + void construct ( in_place_init_t, Arg&& arg ) + { + ::new (m_storage.address()) unqualified_value_type( boost::forward(arg) ); + m_initialized = true ; + } + + void construct ( in_place_init_t ) + { + ::new (m_storage.address()) unqualified_value_type(); + m_initialized = true ; + } + + template + void emplace_assign ( Arg&& arg ) + { + destroy(); + construct(in_place_init, boost::forward(arg)) ; + } + + void emplace_assign () + { + destroy(); + construct(in_place_init) ; + } + + template + explicit optional_base ( in_place_init_t, Arg&& arg ) + : + m_initialized(false) + { + construct(in_place_init, boost::forward(arg)); + } + + explicit optional_base ( in_place_init_t ) + : + m_initialized(false) + { + construct(in_place_init); + } + + template + explicit optional_base ( in_place_init_if_t, bool cond, Arg&& arg ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init, boost::forward(arg)); + } + + explicit optional_base ( in_place_init_if_t, bool cond ) + : + m_initialized(false) + { + if ( cond ) + construct(in_place_init); + } + +#else + + template + void construct ( in_place_init_t, const Arg& arg ) + { + ::new (m_storage.address()) unqualified_value_type( arg ); + m_initialized = true ; + } + + template + void construct ( in_place_init_t, Arg& arg ) + { + ::new (m_storage.address()) unqualified_value_type( arg ); + m_initialized = true ; + } + + void construct ( in_place_init_t ) + { + ::new (m_storage.address()) unqualified_value_type(); + m_initialized = true ; + } + + template + void emplace_assign ( const Arg& arg ) + { + destroy(); + construct(in_place_init, arg); + } + + template + void emplace_assign ( Arg& arg ) + { + destroy(); + construct(in_place_init, arg); + } + + void emplace_assign () + { + destroy(); + construct(in_place_init); + } + + template + explicit optional_base ( in_place_init_t, const Arg& arg ) + : m_initialized(false) + { + construct(in_place_init, arg); + } + + template + explicit optional_base ( in_place_init_t, Arg& arg ) + : m_initialized(false) + { + construct(in_place_init, arg); + } + + explicit optional_base ( in_place_init_t ) + : m_initialized(false) + { + construct(in_place_init); + } + + template + explicit optional_base ( in_place_init_if_t, bool cond, const Arg& arg ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init, arg); + } + + template + explicit optional_base ( in_place_init_if_t, bool cond, Arg& arg ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init, arg); + } + + explicit optional_base ( in_place_init_if_t, bool cond ) + : m_initialized(false) + { + if ( cond ) + construct(in_place_init); + } +#endif + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Constructs in-place using the given factory + template + void construct ( Expr&& factory, in_place_factory_base const* ) + { + boost_optional_detail::construct(factory, m_storage.address()); + m_initialized = true ; + } + + // Constructs in-place using the given typed factory + template + void construct ( Expr&& factory, typed_in_place_factory_base const* ) + { + factory.apply(m_storage.address()) ; + m_initialized = true ; + } + + template + void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } + + // Constructs in-place using the given typed factory + template + void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } + +#else + // Constructs in-place using the given factory + template + void construct ( Expr const& factory, in_place_factory_base const* ) + { + boost_optional_detail::construct(factory, m_storage.address()); + m_initialized = true ; + } + + // Constructs in-place using the given typed factory + template + void construct ( Expr const& factory, typed_in_place_factory_base const* ) + { + factory.apply(m_storage.address()) ; + m_initialized = true ; + } + + template + void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } + + // Constructs in-place using the given typed factory + template + void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag ) + { + destroy(); + construct(factory,tag); + } +#endif + +#endif + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Constructs using any expression implicitly convertible to the single argument + // of a one-argument T constructor. + // Converting constructions of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting constructor of T from U. + template + void construct ( Expr&& expr, void const* ) + { + new (m_storage.address()) unqualified_value_type(boost::forward(expr)) ; + m_initialized = true ; + } + + // Assigns using a form any expression implicitly convertible to the single argument + // of a T's assignment operator. + // Converting assignments of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting assignment of T from U. + template + void assign_expr_to_initialized ( Expr&& expr, void const* ) + { + assign_value( boost::forward(expr) ); + } +#else + // Constructs using any expression implicitly convertible to the single argument + // of a one-argument T constructor. + // Converting constructions of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting constructor of T from U. + template + void construct ( Expr const& expr, void const* ) + { + new (m_storage.address()) unqualified_value_type(expr) ; + m_initialized = true ; + } + + // Assigns using a form any expression implicitly convertible to the single argument + // of a T's assignment operator. + // Converting assignments of optional from optional uses this function with + // 'Expr' being of type 'U' and relying on a converting assignment of T from U. + template + void assign_expr_to_initialized ( Expr const& expr, void const* ) + { + assign_value(expr); + } + +#endif + +#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION + // BCB5.64 (and probably lower versions) workaround. + // The in-place factories are supported by means of catch-all constructors + // and assignment operators (the functions are parameterized in terms of + // an arbitrary 'Expr' type) + // This compiler incorrectly resolves the overload set and sinks optional and optional + // to the 'Expr'-taking functions even though explicit overloads are present for them. + // Thus, the following overload is needed to properly handle the case when the 'lhs' + // is another optional. + // + // For VC<=70 compilers this workaround doesn't work because the compiler issues and error + // instead of choosing the wrong overload + // +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Notice that 'Expr' will be optional or optional (but not optional_base<..>) + template + void construct ( Expr&& expr, optional_tag const* ) + { + if ( expr.is_initialized() ) + { + // An exception can be thrown here. + // It it happens, THIS will be left uninitialized. + new (m_storage.address()) unqualified_value_type(boost::move(expr.get())) ; + m_initialized = true ; + } + } +#else + // Notice that 'Expr' will be optional or optional (but not optional_base<..>) + template + void construct ( Expr const& expr, optional_tag const* ) + { + if ( expr.is_initialized() ) + { + // An exception can be thrown here. + // It it happens, THIS will be left uninitialized. + new (m_storage.address()) unqualified_value_type(expr.get()) ; + m_initialized = true ; + } + } +#endif +#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION + + void assign_value ( argument_type val ) { get_impl() = val; } +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + void assign_value ( rval_reference_type val ) { get_impl() = static_cast(val); } +#endif + + void destroy() + { + if ( m_initialized ) + destroy_impl() ; + } + + reference_const_type get_impl() const { return m_storage.ref() ; } + reference_type get_impl() { return m_storage.ref() ; } + + pointer_const_type get_ptr_impl() const { return m_storage.ptr_ref(); } + pointer_type get_ptr_impl() { return m_storage.ptr_ref(); } + + private : + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1900)) + void destroy_impl ( ) { m_storage.ptr_ref()->~T() ; m_initialized = false ; } +#else + void destroy_impl ( ) { m_storage.ref().T::~T() ; m_initialized = false ; } +#endif + + bool m_initialized ; + storage_type m_storage ; +} ; + +#include + +// definition of metafunction is_optional_val_init_candidate +template +struct is_optional_or_tag + : boost::conditional< boost::is_base_of::type>::value + || boost::is_same::type, none_t>::value + || boost::is_same::type, in_place_init_t>::value + || boost::is_same::type, in_place_init_if_t>::value, + boost::true_type, boost::false_type>::type +{}; + +template +struct has_dedicated_constructor + : boost::disjunction, boost::is_same::type> > +{}; + +template +struct is_in_place_factory + : boost::disjunction< boost::is_base_of::type>, + boost::is_base_of::type> > +{}; + +#if !defined(BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT) + +template +struct is_factory_or_constructible_to_T + : boost::disjunction< is_in_place_factory, boost::is_constructible > +{}; + +template +struct is_optional_constructible : boost::is_constructible +{}; + +#else + +template +struct is_factory_or_constructible_to_T : boost::true_type +{}; + +template +struct is_optional_constructible : boost::true_type +{}; + +#endif // is_convertible condition + +#if !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) +// for is_assignable + +#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) +// On some initial rvalue reference implementations GCC does it in a strange way, +// preferring perfect-forwarding constructor to implicit copy constructor. + +template +struct is_opt_assignable + : boost::conjunction, boost::is_assignable > +{}; + +#else + +template +struct is_opt_assignable + : boost::conjunction, boost::is_assignable > +{}; + +#endif + +#else + +template +struct is_opt_assignable : boost::is_convertible +{}; + +#endif + +template +struct is_factory_or_opt_assignable_to_T + : boost::disjunction< is_in_place_factory, is_opt_assignable > +{}; + +template ::value> +struct is_optional_val_init_candidate + : boost::false_type +{}; + +template +struct is_optional_val_init_candidate + : is_factory_or_constructible_to_T +{}; + +template ::value> +struct is_optional_val_assign_candidate + : boost::false_type +{}; + +template +struct is_optional_val_assign_candidate + : is_factory_or_opt_assignable_to_T +{}; + +} // namespace optional_detail + +namespace optional_config { + +template +struct optional_uses_direct_storage_for + : boost::conditional<(boost::is_scalar::value && !boost::is_const::value && !boost::is_volatile::value) + , boost::true_type, boost::false_type>::type +{}; + +} // namespace optional_config + + +#ifndef BOOST_OPTIONAL_DETAIL_NO_DIRECT_STORAGE_SPEC +# define BOOST_OPTIONAL_BASE_TYPE(T) boost::conditional< optional_config::optional_uses_direct_storage_for::value, \ + optional_detail::tc_optional_base, \ + optional_detail::optional_base \ + >::type +#else +# define BOOST_OPTIONAL_BASE_TYPE(T) optional_detail::optional_base +#endif + +template +class optional + : public BOOST_OPTIONAL_BASE_TYPE(T) +{ + typedef typename BOOST_OPTIONAL_BASE_TYPE(T) base ; + + public : + + typedef optional this_type ; + + typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ; + typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ; + typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ; +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ; + typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ; +#endif + typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ; + typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ; + typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ; + + // Creates an optional uninitialized. + // No-throw + optional() BOOST_NOEXCEPT : base() {} + + // Creates an optional uninitialized. + // No-throw + optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {} + + // Creates an optional initialized with 'val'. + // Can throw if T::T(T const&) does + optional ( argument_type val ) : base(optional_detail::init_value_tag(), val) {} + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Creates an optional initialized with 'move(val)'. + // Can throw if T::T(T &&) does + optional ( rval_reference_type val ) : base(optional_detail::init_value_tag(), boost::forward(val)) + {} +#endif + + // Creates an optional initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional. + // Can throw if T::T(T const&) does + optional ( bool cond, argument_type val ) : base(cond,val) {} + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + /// Creates an optional initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional. + // Can throw if T::T(T &&) does + optional ( bool cond, rval_reference_type val ) : base( cond, boost::forward(val) ) + {} +#endif + + // NOTE: MSVC needs templated versions first + + // Creates a deep copy of another convertible optional + // Requires a valid conversion from U to T. + // Can throw if T::T(U const&) does + template + explicit optional ( optional const& rhs +#ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS + ,BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_constructible, bool>::type = true +#endif + ) + : + base() + { + if ( rhs.is_initialized() ) + this->construct(rhs.get()); + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Creates a deep move of another convertible optional + // Requires a valid conversion from U to T. + // Can throw if T::T(U&&) does + template + explicit optional ( optional && rhs +#ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS + ,BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_constructible, bool>::type = true +#endif + ) + : + base() + { + if ( rhs.is_initialized() ) + this->construct( boost::move(rhs.get()) ); + } +#endif + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + // Creates an optional with an expression which can be either + // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n); + // (b) An instance of TypedInPlaceFactory ( i.e. in_place(a,b,...,n); + // (c) Any expression implicitly convertible to the single type + // of a one-argument T's constructor. + // (d*) Weak compilers (BCB) might also resolved Expr as optional and optional + // even though explicit overloads are present for these. + // Depending on the above some T ctor is called. + // Can throw if the resolved T ctor throws. +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + + template + explicit optional ( Expr&& expr, + BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate, bool>::type = true + ) + : base(boost::forward(expr),boost::addressof(expr)) + {} + +#else + template + explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {} +#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +#endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + + // Creates a deep copy of another optional + // Can throw if T::T(T const&) does +#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS + optional ( optional const& ) = default; +#else + optional ( optional const& rhs ) : base( static_cast(rhs) ) {} +#endif + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Creates a deep move of another optional + // Can throw if T::T(T&&) does + +#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS + optional ( optional && ) = default; +#else + optional ( optional && rhs ) + BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value) + : base( boost::move(rhs) ) + {} +#endif + +#endif + +#if BOOST_WORKAROUND(_MSC_VER, <= 1600) + // On old MSVC compilers the implicitly declared dtor is not called + ~optional() {} +#endif + + +#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) + // Assigns from an expression. See corresponding constructor. + // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + + template + BOOST_DEDUCED_TYPENAME boost::enable_if, optional&>::type + operator= ( Expr&& expr ) + { + this->assign_expr(boost::forward(expr),boost::addressof(expr)); + return *this ; + } + +#else + template + optional& operator= ( Expr const& expr ) + { + this->assign_expr(expr,boost::addressof(expr)); + return *this ; + } +#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +#endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION) + + // Copy-assigns from another convertible optional (converts && deep-copies the rhs value) + // Requires a valid conversion from U to T. + // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED + template + optional& operator= ( optional const& rhs ) + { + this->assign(rhs); + return *this ; + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Move-assigns from another convertible optional (converts && deep-moves the rhs value) + // Requires a valid conversion from U to T. + // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED + template + optional& operator= ( optional && rhs ) + { + this->assign(boost::move(rhs)); + return *this ; + } +#endif + + // Assigns from another optional (deep-copies the rhs value) + // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED + // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw) +#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS + optional& operator= ( optional const& rhs ) = default; +#else + optional& operator= ( optional const& rhs ) + { + this->assign( static_cast(rhs) ) ; + return *this ; + } +#endif + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Assigns from another optional (deep-moves the rhs value) +#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS + optional& operator= ( optional && ) = default; +#else + optional& operator= ( optional && rhs ) + BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value) + { + this->assign( static_cast(rhs) ) ; + return *this ; + } +#endif + +#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + +#ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX + + // Assigns from a T (deep-moves/copies the rhs value) + template + BOOST_DEDUCED_TYPENAME boost::enable_if::type>, optional&>::type + operator= ( T_&& val ) + { + this->assign( boost::forward(val) ) ; + return *this ; + } + +#else + + // Assigns from a T (deep-copies the rhs value) + // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED + optional& operator= ( argument_type val ) + { + this->assign( val ) ; + return *this ; + } + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + // Assigns from a T (deep-moves the rhs value) + optional& operator= ( rval_reference_type val ) + { + this->assign( boost::move(val) ) ; + return *this ; + } +#endif + +#endif // BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX + + // Assigns from a "none" + // Which destroys the current value, if any, leaving this UNINITIALIZED + // No-throw (assuming T::~T() doesn't) + optional& operator= ( none_t none_ ) BOOST_NOEXCEPT + { + this->assign( none_ ) ; + return *this ; + } + +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) + // Constructs in-place + // upon exception *this is always uninitialized + template + void emplace ( Args&&... args ) + { + this->emplace_assign( boost::forward(args)... ); + } + + template + explicit optional ( in_place_init_t, Args&&... args ) + : base( in_place_init, boost::forward(args)... ) + {} + + template + explicit optional ( in_place_init_if_t, bool cond, Args&&... args ) + : base( in_place_init_if, cond, boost::forward(args)... ) + {} + +#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + template + void emplace ( Arg&& arg ) + { + this->emplace_assign( boost::forward(arg) ); + } + + void emplace () + { + this->emplace_assign(); + } + + template + explicit optional ( in_place_init_t, Args&& args ) + : base( in_place_init, boost::forward(args) ) + {} + + explicit optional ( in_place_init_t ) + : base( in_place_init ) + {} + + template + explicit optional ( in_place_init_if_t, bool cond, Args&& args ) + : base( in_place_init_if, cond, boost::forward(args) ) + {} + + explicit optional ( in_place_init_if_t, bool cond ) + : base( in_place_init_if, cond ) + {} +#else + template + void emplace ( const Arg& arg ) + { + this->emplace_assign( arg ); + } + + template + void emplace ( Arg& arg ) + { + this->emplace_assign( arg ); + } + + void emplace () + { + this->emplace_assign(); + } + + template + explicit optional ( in_place_init_t, const Arg& arg ) + : base( in_place_init, arg ) + {} + + template + explicit optional ( in_place_init_t, Arg& arg ) + : base( in_place_init, arg ) + {} + + explicit optional ( in_place_init_t ) + : base( in_place_init ) + {} + + template + explicit optional ( in_place_init_if_t, bool cond, const Arg& arg ) + : base( in_place_init_if, cond, arg ) + {} + + template + explicit optional ( in_place_init_if_t, bool cond, Arg& arg ) + : base( in_place_init_if, cond, arg ) + {} + + explicit optional ( in_place_init_if_t, bool cond ) + : base( in_place_init_if, cond ) + {} +#endif + + void swap( optional & arg ) + BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible::value && ::boost::is_nothrow_move_assignable::value) + { + // allow for Koenig lookup + boost::core::invoke_swap(*this, arg); + } + + + // Returns a reference to the value if this is initialized, otherwise, + // the behaviour is UNDEFINED + // No-throw + reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); } + reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); } + + // Returns a copy of the value if this is initialized, 'v' otherwise + reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; } + reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; } + + // Returns a pointer to the value if this is initialized, otherwise, + // the behaviour is UNDEFINED + // No-throw + pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; } + pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; } + + // Returns a reference to the value if this is initialized, otherwise, + // the behaviour is UNDEFINED + // No-throw +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + reference_const_type operator *() const& { return this->get() ; } + reference_type operator *() & { return this->get() ; } + reference_type_of_temporary_wrapper operator *() && { return boost::move(this->get()) ; } +#else + reference_const_type operator *() const { return this->get() ; } + reference_type operator *() { return this->get() ; } +#endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS + +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + reference_const_type value() const& + { + if (this->is_initialized()) + return this->get() ; + else + throw_exception(bad_optional_access()); + } + + reference_type value() & + { + if (this->is_initialized()) + return this->get() ; + else + throw_exception(bad_optional_access()); + } + + reference_type_of_temporary_wrapper value() && + { + if (this->is_initialized()) + return boost::move(this->get()) ; + else + throw_exception(bad_optional_access()); + } + +#else + reference_const_type value() const + { + if (this->is_initialized()) + return this->get() ; + else + throw_exception(bad_optional_access()); + } + + reference_type value() + { + if (this->is_initialized()) + return this->get() ; + else + throw_exception(bad_optional_access()); + } +#endif + + +#ifndef BOOST_NO_CXX11_REF_QUALIFIERS + template + value_type value_or ( U&& v ) const& + { + if (this->is_initialized()) + return get(); + else + return boost::forward(v); + } + + template + value_type value_or ( U&& v ) && + { + if (this->is_initialized()) + return boost::move(get()); + else + return boost::forward(v); + } +#elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + template + value_type value_or ( U&& v ) const + { + if (this->is_initialized()) + return get(); + else + return boost::forward(v); + } +#else + template + value_type value_or ( U const& v ) const + { + if (this->is_initialized()) + return get(); + else + return v; + } + + template + value_type value_or ( U& v ) const + { + if (this->is_initialized()) + return get(); + else + return v; + } +#endif + + +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + template + value_type value_or_eval ( F f ) const& + { + if (this->is_initialized()) + return get(); + else + return f(); + } + + template + value_type value_or_eval ( F f ) && + { + if (this->is_initialized()) + return boost::move(get()); + else + return f(); + } + + template + optional::type> map(F f) & + { + if (this->has_value()) + return f(get()); + else + return none; + } + + template + optional::type> map(F f) const& + { + if (this->has_value()) + return f(get()); + else + return none; + } + + template + optional::type> map(F f) && + { + if (this->has_value()) + return f(boost::move(this->get())); + else + return none; + } + + template + optional::type>::type> flat_map(F f) & + { + if (this->has_value()) + return f(get()); + else + return none; + } + + template + optional::type>::type> flat_map(F f) const& + { + if (this->has_value()) + return f(get()); + else + return none; + } + + template + optional::type>::type> flat_map(F f) && + { + if (this->has_value()) + return f(boost::move(get())); + else + return none; + } + +#else + template + value_type value_or_eval ( F f ) const + { + if (this->is_initialized()) + return get(); + else + return f(); + } + + template + optional::type> map(F f) + { + if (this->has_value()) + return f(get()); + else + return none; + } + + template + optional::type> map(F f) const + { + if (this->has_value()) + return f(get()); + else + return none; + } + + template + optional::type>::type> flat_map(F f) + { + if (this->has_value()) + return f(get()); + else + return none; + } + + template + optional::type>::type> flat_map(F f) const + { + if (this->has_value()) + return f(get()); + else + return none; + } + +#endif + + bool has_value() const BOOST_NOEXCEPT { return this->is_initialized() ; } + + bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; } + + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() +} ; + +} // namespace boost + +#endif // BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL + +namespace boost { + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +template +class optional +{ + BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, "Optional rvalue references are illegal."); +} ; +#endif + +} // namespace boost + +#ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS +# include +#endif + +namespace boost { + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + +template +inline +optional::type> make_optional ( T && v ) +{ + return optional::type>(boost::forward(v)); +} + +// Returns optional(cond,v) +template +inline +optional::type> make_optional ( bool cond, T && v ) +{ + return optional::type>(cond,boost::forward(v)); +} + +#else + +// Returns optional(v) +template +inline +optional make_optional ( T const& v ) +{ + return optional(v); +} + +// Returns optional(cond,v) +template +inline +optional make_optional ( bool cond, T const& v ) +{ + return optional(cond,v); +} + +#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + +// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED. +// No-throw +template +inline +BOOST_DEDUCED_TYPENAME optional::reference_const_type +get ( optional const& opt ) +{ + return opt.get() ; +} + +template +inline +BOOST_DEDUCED_TYPENAME optional::reference_type +get ( optional& opt ) +{ + return opt.get() ; +} + +// Returns a pointer to the value if this is initialized, otherwise, returns NULL. +// No-throw +template +inline +BOOST_DEDUCED_TYPENAME optional::pointer_const_type +get ( optional const* opt ) +{ + return opt->get_ptr() ; +} + +template +inline +BOOST_DEDUCED_TYPENAME optional::pointer_type +get ( optional* opt ) +{ + return opt->get_ptr() ; +} + +// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED. +// No-throw +template +inline +BOOST_DEDUCED_TYPENAME optional::reference_const_type +get_optional_value_or ( optional const& opt, BOOST_DEDUCED_TYPENAME optional::reference_const_type v ) +{ + return opt.get_value_or(v) ; +} + +template +inline +BOOST_DEDUCED_TYPENAME optional::reference_type +get_optional_value_or ( optional& opt, BOOST_DEDUCED_TYPENAME optional::reference_type v ) +{ + return opt.get_value_or(v) ; +} + +// Returns a pointer to the value if this is initialized, otherwise, returns NULL. +// No-throw +template +inline +BOOST_DEDUCED_TYPENAME optional::pointer_const_type +get_pointer ( optional const& opt ) +{ + return opt.get_ptr() ; +} + +template +inline +BOOST_DEDUCED_TYPENAME optional::pointer_type +get_pointer ( optional& opt ) +{ + return opt.get_ptr() ; +} + +} // namespace boost + +#ifndef BOOST_NO_IOSTREAM +namespace boost { + +// The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header. +template +std::basic_ostream& +operator<<(std::basic_ostream& os, optional_detail::optional_tag const&) +{ + BOOST_STATIC_ASSERT_MSG(sizeof(CharType) == 0, "If you want to output boost::optional, include header "); + return os; +} + +} // namespace boost +#endif // BOOST_NO_IOSTREAM + +#include +#include + +#endif // header guard diff --git a/libs/optional/include/boost/optional/optional_fwd.hpp b/libs/optional/include/boost/optional/optional_fwd.hpp new file mode 100644 index 00000000..faee253e --- /dev/null +++ b/libs/optional/include/boost/optional/optional_fwd.hpp @@ -0,0 +1,41 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2016 Andrzej Krzemienski +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +// Revisions: +// 10 May 2008 (added swap related forward declaration) Niels Dekker +// +#ifndef BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP +#define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP + +#include + +namespace boost { + +template class optional ; + +// This forward is needed to refer to namespace scope swap from the member swap +template void swap ( optional& , optional& ) ; + +template struct optional_swap_should_use_default_constructor ; + +#ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS + +template class optional ; + +template void swap ( optional& , optional& ) BOOST_NOEXCEPT; + +#endif + +} // namespace boost + +#endif + diff --git a/libs/optional/include/boost/optional/optional_io.hpp b/libs/optional/include/boost/optional/optional_io.hpp new file mode 100644 index 00000000..3db6ddae --- /dev/null +++ b/libs/optional/include/boost/optional/optional_io.hpp @@ -0,0 +1,95 @@ +// Copyright (C) 2005, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#ifndef BOOST_OPTIONAL_OPTIONAL_IO_FLC_19NOV2002_HPP +#define BOOST_OPTIONAL_OPTIONAL_IO_FLC_19NOV2002_HPP + +#ifndef BOOST_NO_IOSTREAM +#include +#include + +#include "boost/none.hpp" +#include "boost/optional/optional.hpp" + + +namespace boost +{ + +template +inline +std::basic_ostream& +operator<<(std::basic_ostream& out, none_t) +{ + if (out.good()) + { + out << "--"; + } + + return out; +} + +template +inline +std::basic_ostream& +operator<<(std::basic_ostream& out, optional const& v) +{ + if (out.good()) + { + if (!v) + out << "--" ; + else out << ' ' << *v ; + } + + return out; +} + +template +inline +std::basic_istream& +operator>>(std::basic_istream& in, optional& v) +{ + if (in.good()) + { + int d = in.get(); + if (d == ' ') + { + T x; + in >> x; +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + v = boost::move(x); +#else + v = x; +#endif + } + else + { + if (d == '-') + { + d = in.get(); + + if (d == '-') + { + v = none; + return in; + } + } + + in.setstate( std::ios::failbit ); + } + } + + return in; +} + +} // namespace boost + +#endif // BOOST_NO_IOSTREAM +#endif diff --git a/libs/optional/index.html b/libs/optional/index.html new file mode 100644 index 00000000..84b7c939 --- /dev/null +++ b/libs/optional/index.html @@ -0,0 +1,13 @@ + + + + + +Automatic redirection failed, please go to +doc/html/index.html
+

� Copyright Beman Dawes, 2001

+

Distributed under the Boost Software License, Version 1.0. (See accompanying +file LICENSE_1_0.txt or copy +at www.boost.org/LICENSE_1_0.txt)

+ + diff --git a/libs/optional/meta/libraries.json b/libs/optional/meta/libraries.json new file mode 100644 index 00000000..a263d7e8 --- /dev/null +++ b/libs/optional/meta/libraries.json @@ -0,0 +1,17 @@ +{ + "key": "optional", + "boost-version": "1.30.0", + "name": "Optional", + "authors": [ + "Fernando Cacciola" + ], + "description": "A value-semantic, type-safe wrapper for representing 'optional' (or 'nullable') objects of a given type. An optional object may or may not contain a value of the underlying type.", + "category": [ + "Data" + ], + "maintainers": [ + "Fernando Cacciola ", + "Andrzej Krzemienski " + ], + "cxxstd": "03" +} diff --git a/libs/optional/test/Jamfile.v2 b/libs/optional/test/Jamfile.v2 new file mode 100644 index 00000000..c9658637 --- /dev/null +++ b/libs/optional/test/Jamfile.v2 @@ -0,0 +1,91 @@ +# Boost.Optional Library test Jamfile +# +# Copyright (C) 2003, Fernando Luis Cacciola Carballal. +# Copyright (C) 2014 - 2017 Andrzej Krzemienski +# +# Use, modification, and distribution is subject to 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) +# +# See http://www.boost.org/libs/optional for documentation. +# +# You are welcome to contact the author at: +# akrzemi1@gmail.com +# + +import testing ; + +{ + test-suite optional : + [ run optional_test.cpp ] + [ run optional_test_assign.cpp ] + [ run optional_test_swap.cpp ] + [ run optional_test_conversions_from_U.cpp ] + [ run optional_test_convert_from_T.cpp ] + [ run optional_test_convert_assign.cpp ] + [ run optional_test_empty_braces.cpp ] + [ run optional_test_make_optional.cpp ] + [ run optional_test_flat_map.cpp ] + [ run optional_test_hash.cpp ] + [ run optional_test_map.cpp ] + [ run optional_test_tie.cpp ] + [ run optional_test_ref_assign_portable_minimum.cpp ] + [ run optional_test_ref_assign_mutable_int.cpp ] + [ run optional_test_ref_assign_const_int.cpp ] + [ run optional_test_ref_converting_ctor.cpp ] + [ run optional_test_ref_convert_assign_non_int.cpp ] + [ run optional_test_ref_convert_assign_mutable_int.cpp ] + [ run optional_test_ref_convert_assign_const_int.cpp ] + [ run optional_test_ref_portable_minimum.cpp ] + [ run optional_test_ref_move.cpp ] + [ run optional_test_ref_to_val.cpp ] + [ run optional_test_inplace_factory.cpp ] + [ run optional_test_io.cpp ] + [ run optional_test_move.cpp ] + [ run optional_test_noexcept_move.cpp ] + [ run optional_test_old_impl.cpp ] + [ run optional_test_equals_none.cpp ] + [ run optional_test_value_access.cpp ] + [ run optional_test_emplace.cpp ] + [ run optional_test_minimum_requirements.cpp ] + [ run optional_test_msvc_bug_workaround.cpp ] + [ run optional_test_member_T.cpp ] + [ run optional_test_tc_base.cpp ] + [ compile optional_test_sfinae_friendly_ctor.cpp ] + [ compile optional_test_path_assignment.cpp ] + [ compile-fail optional_test_fail_const_swap.cpp ] + [ compile-fail optional_test_ref_convert_assign_const_int_prevented.cpp ] + [ compile-fail optional_test_fail1.cpp ] + [ compile-fail optional_test_fail3a.cpp ] + [ compile-fail optional_test_fail3b.cpp ] + [ compile-fail optional_test_ref_fail1.cpp ] + [ compile-fail optional_test_ref_fail3.cpp ] + [ compile-fail optional_test_ref_fail4.cpp ] + [ compile-fail optional_test_inplace_fail.cpp ] + [ compile-fail optional_test_inplace_fail2.cpp ] + [ compile-fail optional_test_fail_implicit_bool_convert.cpp ] + [ compile-fail optional_test_fail_copying_a_moveable_type.cpp ] + [ compile-fail optional_test_fail_optional_rvalue_ref.cpp ] + [ compile-fail optional_test_ref_fail_init_from_Trefref.cpp ] + [ compile-fail optional_test_ref_fail_init_from_Urefref.cpp ] + [ compile-fail optional_test_ref_fail_assign_from_Trefref.cpp ] + [ compile-fail optional_test_ref_fail_assign_from_Urefref.cpp ] + [ compile-fail optional_test_fail_convert_from_null.cpp ] + [ compile-fail optional_test_fail_explicit_convert_in_value_or.cpp ] + [ compile-fail optional_test_fail_explicit_convert_in_value_or_call.cpp ] + [ compile-fail optional_test_fail_io_without_io.cpp ] + [ compile-fail optional_test_fail_none_io_without_io.cpp ] + [ compile-fail optional_test_fail_convert_assign_of_enums.cpp ] + [ run optional_test_static_properties.cpp ] + [ compile optional_test_maybe_uninitialized_warning.cpp ] + [ compile optional_test_deleted_default_ctor.cpp ] + [ compile optional_test_constructible_from_other.cpp ] + #[ run optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp ] + [ run optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp ] + [ run-fail optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp ] + [ run optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp ] + [ run-fail optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp ] + [ run optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp ] + [ compile-fail optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp ] + ; +} diff --git a/libs/optional/test/optional_ref_assign_test_defs.hpp b/libs/optional/test/optional_ref_assign_test_defs.hpp new file mode 100644 index 00000000..7185ff4a --- /dev/null +++ b/libs/optional/test/optional_ref_assign_test_defs.hpp @@ -0,0 +1,181 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_TEST_OPTIONAL_REF_ASSIGN_TEST_DEFS_AK_07JAN2015_HPP +#define BOOST_OPTIONAL_TEST_OPTIONAL_REF_ASSIGN_TEST_DEFS_AK_07JAN2015_HPP + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/addressof.hpp" +#include "testable_classes.hpp" + +using boost::optional; +using boost::none; +using boost::addressof; + +template +void test_copy_assignment_for_const() +{ + const typename concrete_type_of::type v(2); + optional o; + o = optional(v); + + BOOST_TEST(o); + BOOST_TEST(o != none); + BOOST_TEST(addressof(*o) == addressof(v)); + BOOST_TEST(val(*o) == val(v)); + BOOST_TEST(val(*o) == 2); +} + +template +void test_copy_assignment_for_noconst_const() +{ + typename concrete_type_of::type v(2); + optional o; + o = optional(v); + + BOOST_TEST(o); + BOOST_TEST(o != none); + BOOST_TEST(addressof(*o) == addressof(v)); + BOOST_TEST(val(*o) == val(v)); + BOOST_TEST(val(*o) == 2); + + val(v) = 9; + BOOST_TEST(addressof(*o) == addressof(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 9); + BOOST_TEST_EQ(val(v), 9); +} + +template +void test_copy_assignment_for() +{ + typename concrete_type_of::type v(2); + optional o; + o = optional(v); + + BOOST_TEST(o); + BOOST_TEST(o != none); + BOOST_TEST(addressof(*o) == addressof(v)); + BOOST_TEST(val(*o) == val(v)); + BOOST_TEST(val(*o) == 2); + + val(v) = 9; + BOOST_TEST(addressof(*o) == addressof(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 9); + BOOST_TEST_EQ(val(v), 9); + + val(*o) = 7; + BOOST_TEST(addressof(*o) == addressof(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 7); + BOOST_TEST_EQ(val(v), 7); +} + +template +void test_rebinding_assignment_semantics_const() +{ + const typename concrete_type_of::type v(2), w(7); + optional o(v); + + BOOST_TEST(o); + BOOST_TEST(addressof(*o) == addressof(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 2); + + o = optional(w); + BOOST_TEST_EQ(val(v), 2); + + BOOST_TEST(o); + BOOST_TEST(addressof(*o) != addressof(v)); + BOOST_TEST_NE(val(*o), val(v)); + BOOST_TEST_NE(val(*o), 2); + + BOOST_TEST(addressof(*o) == addressof(w)); + BOOST_TEST_EQ(val(*o), val(w)); + BOOST_TEST_EQ(val(*o), 7); +} + +template +void test_rebinding_assignment_semantics_noconst_const() +{ + typename concrete_type_of::type v(2), w(7); + optional o(v); + + BOOST_TEST(o); + BOOST_TEST(addressof(*o) == addressof(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 2); + + o = optional(w); + BOOST_TEST_EQ(val(v), 2); + + BOOST_TEST(o); + BOOST_TEST(addressof(*o) != addressof(v)); + BOOST_TEST_NE(val(*o), val(v)); + BOOST_TEST_NE(val(*o), 2); + + BOOST_TEST(addressof(*o) == addressof(w)); + BOOST_TEST_EQ(val(*o), val(w)); + BOOST_TEST_EQ(val(*o), 7); +} + +template +void test_rebinding_assignment_semantics() +{ + typename concrete_type_of::type v(2), w(7); + optional o(v); + + BOOST_TEST(o); + BOOST_TEST(addressof(*o) == addressof(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 2); + + o = optional(w); + BOOST_TEST_EQ(val(v), 2); + + BOOST_TEST(o); + BOOST_TEST(addressof(*o) != addressof(v)); + BOOST_TEST_NE(val(*o), val(v)); + BOOST_TEST_NE(val(*o), 2); + + BOOST_TEST(addressof(*o) == addressof(w)); + BOOST_TEST_EQ(val(*o), val(w)); + BOOST_TEST_EQ(val(*o), 7); + + val(*o) = 8; + BOOST_TEST(addressof(*o) == addressof(w)); + BOOST_TEST_EQ(val(*o), val(w)); + BOOST_TEST_EQ(val(*o), 8); + BOOST_TEST_EQ(val(w), 8); + BOOST_TEST_EQ(val(v), 2); +} + +template +void test_converting_assignment() +{ + typename concrete_type_of::type v1(1), v2(2), v3(3); + optional oA(v1), oB(none); + + oA = v2; + BOOST_TEST(oA); + BOOST_TEST(addressof(*oA) == addressof(v2)); + + oB = v3; + BOOST_TEST(oB); + BOOST_TEST(addressof(*oB) == addressof(v3)); +} + +#endif //BOOST_OPTIONAL_TEST_OPTIONAL_REF_ASSIGN_TEST_DEFS_AK_07JAN2015_HPP diff --git a/libs/optional/test/optional_test.cpp b/libs/optional/test/optional_test.cpp new file mode 100644 index 00000000..5ec00162 --- /dev/null +++ b/libs/optional/test/optional_test.cpp @@ -0,0 +1,954 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +// Revisions: +// 12 May 2008 (added more swap tests) +// +#ifndef BOOST_NO_IOSTREAM +#include +#endif // BOOST_NO_IOSTREAM +#include +#include + +#define BOOST_ENABLE_ASSERT_HANDLER + +#include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin +#include "boost/mpl/bool.hpp" +#include "boost/mpl/bool_fwd.hpp" // For mpl::true_ and mpl::false_ + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/none.hpp" + +#include "boost/core/lightweight_test.hpp" + +#include "optional_test_common.hpp" + +void test_implicit_construction ( optional opt, double v, double z ) +{ + check_value(opt,v,z); +} + +void test_implicit_construction ( optional opt, X const& v, X const& z ) +{ + check_value(opt,v,z); +} + +void test_default_implicit_construction ( double, optional opt ) +{ + BOOST_TEST(!opt); +} + +void test_default_implicit_construction ( X const&, optional opt ) +{ + BOOST_TEST(!opt); +} + +// +// Basic test. +// Check ordinary functionality: +// Initialization, assignment, comparison and value-accessing. +// +template +void test_basics( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T z(0); + + T a(1); + + // Default construction. + // 'def' state is Uninitialized. + // T::T() is not called (and it is not even defined) + optional def ; + check_uninitialized(def); + + // Implicit construction + // The first parameter is implicitly converted to optional(a); + test_implicit_construction(a,a,z); + + // Direct initialization. + // 'oa' state is Initialized with 'a' + // T::T( T const& x ) is used. + set_pending_copy( ARG(T) ) ; + optional oa ( a ) ; + check_is_not_pending_copy( ARG(T) ); + check_initialized(oa); + check_value(oa,a,z); + + T b(2); + + optional ob ; + + // Value-Assignment upon Uninitialized optional. + // T::T( T const& x ) is used. + set_pending_copy( ARG(T) ) ; + ob = a ; + check_is_not_pending_copy( ARG(T) ) ; + check_initialized(ob); + check_value(ob,a,z); + + // Value-Assignment upon Initialized optional. + // T::operator=( T const& x ) is used + set_pending_assign( ARG(T) ) ; + set_pending_copy ( ARG(T) ) ; + set_pending_dtor ( ARG(T) ) ; + ob = b ; + check_is_not_pending_assign( ARG(T) ) ; + check_is_pending_copy ( ARG(T) ) ; + check_is_pending_dtor ( ARG(T) ) ; + check_initialized(ob); + check_value(ob,b,z); + + // Assignment initialization. + // T::T ( T const& x ) is used to copy new value. + set_pending_copy( ARG(T) ) ; + optional const oa2 ( oa ) ; + check_is_not_pending_copy( ARG(T) ) ; + check_initialized_const(oa2); + check_value_const(oa2,a,z); + + // Assignment + // T::operator= ( T const& x ) is used to copy new value. + set_pending_assign( ARG(T) ) ; + oa = ob ; + check_is_not_pending_assign( ARG(T) ) ; + check_initialized(oa); + check_value(oa,b,z); + + // Uninitializing Assignment upon Initialized Optional + // T::~T() is used to destroy previous value in oa. + set_pending_dtor( ARG(T) ) ; + set_pending_copy( ARG(T) ) ; + oa = def ; + check_is_not_pending_dtor( ARG(T) ) ; + check_is_pending_copy ( ARG(T) ) ; + check_uninitialized(oa); + + // Uninitializing Assignment upon Uninitialized Optional + // (Dtor is not called this time) + set_pending_dtor( ARG(T) ) ; + set_pending_copy( ARG(T) ) ; + oa = def ; + check_is_pending_dtor( ARG(T) ) ; + check_is_pending_copy( ARG(T) ) ; + check_uninitialized(oa); + + // Deinitialization of Initialized Optional + // T::~T() is used to destroy previous value in ob. + set_pending_dtor( ARG(T) ) ; + ob.reset(); + check_is_not_pending_dtor( ARG(T) ) ; + check_uninitialized(ob); + + // Deinitialization of Uninitialized Optional + // (Dtor is not called this time) + set_pending_dtor( ARG(T) ) ; + ob.reset(); + check_is_pending_dtor( ARG(T) ) ; + check_uninitialized(ob); + +} + +template +void test_conditional_ctor_and_get_value_or ( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T a(321); + + T z(123); + + optional const cdef0(false,a); + + optional def0(false,a); + optional def1 = boost::make_optional(false,a); // T is not within boost so ADL won't find make_optional unqualified + check_uninitialized(def0); + check_uninitialized(def1); + + optional const co0(true,a); + + optional o0(true,a); + optional o1 = boost::make_optional(true,a); // T is not within boost so ADL won't find make_optional unqualified + + check_initialized(o0); + check_initialized(o1); + check_value(o0,a,z); + check_value(o1,a,z); + + T b = def0.get_value_or(z); + BOOST_TEST( b == z ) ; + + b = get_optional_value_or(def0,z); + BOOST_TEST( b == z ) ; + + b = o0.get_value_or(z); + BOOST_TEST( b == a ) ; + + b = get_optional_value_or(o0,z); + BOOST_TEST( b == a ) ; + + + T const& crz = z ; + T& rz = z ; + + T const& crzz = def0.get_value_or(crz); + BOOST_TEST( crzz == crz ) ; + + T& rzz = def0.get_value_or(rz); + BOOST_TEST( rzz == rz ) ; + + T const& crzzz = get_optional_value_or(cdef0,crz); + BOOST_TEST( crzzz == crz ) ; + + T& rzzz = get_optional_value_or(def0,rz); + BOOST_TEST( rzzz == rz ) ; + + T const& crb = o0.get_value_or(crz); + BOOST_TEST( crb == a ) ; + + T& rb = o0.get_value_or(rz); + BOOST_TEST( rb == b ) ; + + T const& crbb = get_optional_value_or(co0,crz); + BOOST_TEST( crbb == b ) ; + + T const& crbbb = get_optional_value_or(o0,crz); + BOOST_TEST( crbbb == b ) ; + + T& rbb = get_optional_value_or(o0,rz); + BOOST_TEST( rbb == b ) ; + + T& ra = a ; + + optional defref(false,ra); + BOOST_TEST(!defref); + + optional ref(true,ra); + BOOST_TEST(!!ref); + + a = T(432); + + BOOST_TEST( *ref == a ) ; + + T& r1 = defref.get_value_or(z); + BOOST_TEST( r1 == z ) ; + + T& r2 = ref.get_value_or(z); + BOOST_TEST( r2 == a ) ; +} + +// +// Test Direct Value Manipulation +// +template +void test_direct_value_manip( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T x(3); + + optional const c_opt0(x) ; + optional opt0(x); + + BOOST_TEST( c_opt0.get().V() == x.V() ) ; + BOOST_TEST( opt0.get().V() == x.V() ) ; + + BOOST_TEST( c_opt0->V() == x.V() ) ; + BOOST_TEST( opt0->V() == x.V() ) ; + + BOOST_TEST( (*c_opt0).V() == x.V() ) ; + BOOST_TEST( (* opt0).V() == x.V() ) ; + + T y(4); + opt0 = y ; + BOOST_TEST( get(opt0).V() == y.V() ) ; +} + +// +// Test Uninitialized access assert +// +template +void test_uninitialized_access( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + optional def ; + + bool passed = false ; + try + { + // This should throw because 'def' is uninitialized + T const& n = def.get() ; + boost::ignore_unused(n); + passed = true ; + } + catch (...) {} + BOOST_TEST(!passed); + + passed = false ; + try + { + // This should throw because 'def' is uninitialized + T const& n = *def ; + boost::ignore_unused(n); + passed = true ; + } + catch (...) {} + BOOST_TEST(!passed); + + passed = false ; + try + { + T v(5) ; + boost::ignore_unused(v); + // This should throw because 'def' is uninitialized + *def = v ; + passed = true ; + } + catch (...) {} + BOOST_TEST(!passed); + + passed = false ; + try + { + // This should throw because 'def' is uninitialized + T v = *(def.operator->()) ; + boost::ignore_unused(v); + passed = true ; + } + catch (...) {} + BOOST_TEST(!passed); +} + +#if BOOST_WORKAROUND( BOOST_INTEL_CXX_VERSION, <= 700) // Intel C++ 7.0 +void prevent_buggy_optimization( bool v ) {} +#endif + +// +// Test Direct Initialization of optional for a T with throwing copy-ctor. +// +template +void test_throwing_direct_init( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T a(6); + + int count = get_instance_count( ARG(T) ) ; + + set_throw_on_copy( ARG(T) ) ; + + bool passed = false ; + try + { + // This should: + // Attempt to copy construct 'a' and throw. + // 'opt' won't be constructed. + set_pending_copy( ARG(T) ) ; + +#if BOOST_WORKAROUND( BOOST_INTEL_CXX_VERSION, <= 700) // Intel C++ 7.0 + // Intel C++ 7.0 specific: + // For some reason, when "check_is_not_pending_copy", + // after the exception block is reached, + // X::pending_copy==true even though X's copy ctor set it to false. + // I guessed there is some sort of optimization bug, + // and it seems to be the since the following additional line just + // solves the problem (!?) + prevent_buggy_optimization(X::pending_copy); +#endif + + optional opt(a) ; + passed = true ; + } + catch ( ... ){} + + BOOST_TEST(!passed); + check_is_not_pending_copy( ARG(T) ); + check_instance_count(count, ARG(T) ); + + reset_throw_on_copy( ARG(T) ) ; + +} + +// +// Test Value Assignment to an Uninitialized optional for a T with a throwing copy-ctor +// +template +void test_throwing_val_assign_on_uninitialized( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T a(7); + + int count = get_instance_count( ARG(T) ) ; + + set_throw_on_copy( ARG(T) ) ; + + optional opt ; + + bool passed = false ; + try + { + // This should: + // Attempt to copy construct 'a' and throw. + // opt should be left uninitialized. + set_pending_copy( ARG(T) ) ; + opt.reset( a ); + passed = true ; + } + catch ( ... ) {} + + BOOST_TEST(!passed); + + check_is_not_pending_copy( ARG(T) ); + check_instance_count(count, ARG(T) ); + check_uninitialized(opt); + + reset_throw_on_copy( ARG(T) ) ; +} + +// +// Test Value Reset on an Initialized optional for a T with a throwing copy-ctor +// +template +void test_throwing_val_assign_on_initialized( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T z(0); + T a(8); + T b(9); + T x(-1); + + int count = get_instance_count( ARG(T) ) ; + + optional opt ( b ) ; + ++ count ; + + check_instance_count(count, ARG(T) ); + + check_value(opt,b,z); + + set_throw_on_assign( ARG(T) ) ; + + bool passed = false ; + try + { + // This should: + // Attempt to assign 'a' and throw. + // opt is kept initialized but its value not necessarily fully assigned + // (in this test, incompletely assigned is flagged with the value -1 being set) + set_pending_assign( ARG(T) ) ; + opt.reset ( a ) ; + passed = true ; + } + catch ( ... ) {} + + BOOST_TEST(!passed); + + check_is_not_pending_assign( ARG(T) ); + check_instance_count(count, ARG(T) ); + check_initialized(opt); + check_value(opt,x,z); + + reset_throw_on_assign ( ARG(T) ) ; +} + +// +// Test Copy Initialization from an Initialized optional for a T with a throwing copy-ctor +// +template +void test_throwing_copy_initialization( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T z(0); + T a(10); + + optional opt (a); + + int count = get_instance_count( ARG(T) ) ; + + set_throw_on_copy( ARG(T) ) ; + + bool passed = false ; + try + { + // This should: + // Attempt to copy construct 'opt' and throw. + // opt1 won't be constructed. + set_pending_copy( ARG(T) ) ; + optional opt1 = opt ; + passed = true ; + } + catch ( ... ) {} + + BOOST_TEST(!passed); + + check_is_not_pending_copy( ARG(T) ); + check_instance_count(count, ARG(T) ); + + // Nothing should have happened to the source optional. + check_initialized(opt); + check_value(opt,a,z); + + reset_throw_on_copy( ARG(T) ) ; +} + +// +// Test Assignment to an Uninitialized optional from an Initialized optional +// for a T with a throwing copy-ctor +// +template +void test_throwing_assign_to_uninitialized( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T z(0); + T a(11); + + optional opt0 ; + optional opt1(a) ; + + int count = get_instance_count( ARG(T) ) ; + + set_throw_on_copy( ARG(T) ) ; + + bool passed = false ; + try + { + // This should: + // Attempt to copy construct 'opt1.value()' into opt0 and throw. + // opt0 should be left uninitialized. + set_pending_copy( ARG(T) ) ; + opt0 = opt1 ; + passed = true ; + } + catch ( ... ) {} + + BOOST_TEST(!passed); + + check_is_not_pending_copy( ARG(T) ); + check_instance_count(count, ARG(T) ); + check_uninitialized(opt0); + + reset_throw_on_copy( ARG(T) ) ; +} + +// +// Test Assignment to an Initialized optional from an Initialized optional +// for a T with a throwing copy-ctor +// +template +void test_throwing_assign_to_initialized( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T z(0); + T a(12); + T b(13); + T x(-1); + + optional opt0(a) ; + optional opt1(b) ; + + int count = get_instance_count( ARG(T) ) ; + + set_throw_on_assign( ARG(T) ) ; + + bool passed = false ; + try + { + // This should: + // Attempt to copy construct 'opt1.value()' into opt0 and throw. + // opt0 is kept initialized but its value not necessarily fully assigned + // (in this test, incompletely assigned is flagged with the value -1 being set) + set_pending_assign( ARG(T) ) ; + opt0 = opt1 ; + passed = true ; + } + catch ( ... ) {} + + BOOST_TEST(!passed); + + // opt0 was left uninitialized + check_is_not_pending_assign( ARG(T) ); + check_instance_count(count, ARG(T) ); + check_initialized(opt0); + check_value(opt0,x,z); + + reset_throw_on_assign( ARG(T) ) ; +} + +// +// Test swap in a no-throwing case +// +template +void test_no_throwing_swap( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T z(0); + T a(14); + T b(15); + + optional def0 ; + optional def1 ; + optional opt0(a) ; + optional opt1(b) ; + + int count = get_instance_count( ARG(T) ) ; + + swap(def0,def1); + check_uninitialized(def0); + check_uninitialized(def1); + + swap(def0,opt0); + check_uninitialized(opt0); + check_initialized(def0); + check_value(def0,a,z); + + // restore def0 and opt0 + swap(def0,opt0); + + swap(opt0,opt1); + check_instance_count(count, ARG(T) ); + check_initialized(opt0); + check_initialized(opt1); + check_value(opt0,b,z); + check_value(opt1,a,z); +} + +// +// Test swap in a throwing case +// +template +void test_throwing_swap( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T a(16); + T b(17); + T x(-1); + + optional opt0(a) ; + optional opt1(b) ; + + set_throw_on_assign( ARG(T) ) ; + + // + // Case 1: Both Initialized. + // + bool passed = false ; + try + { + // This should attempt to swap optionals and fail at swap(X&,X&). + swap(opt0,opt1); + + passed = true ; + } + catch ( ... ) {} + + BOOST_TEST(!passed); + + // optional's swap doesn't affect the initialized states of the arguments. Therefore, + // the following must hold: + check_initialized(opt0); + check_initialized(opt1); + check_value(opt0,x,a); + check_value(opt1,b,x); + + + // + // Case 2: Only one Initialized. + // + reset_throw_on_assign( ARG(T) ) ; + + opt0.reset(); + opt1.reset(a); + + set_throw_on_copy( ARG(T) ) ; + + passed = false ; + try + { + // This should attempt to swap optionals and fail at opt0.reset(*opt1) + // Both opt0 and op1 are left unchanged (unswapped) + swap(opt0,opt1); + + passed = true ; + } + catch ( ... ) {} + + BOOST_TEST(!passed); + + check_uninitialized(opt0); + check_initialized(opt1); + check_value(opt1,a,x); + + reset_throw_on_copy( ARG(T) ) ; +} + +// +// This verifies relational operators. +// +template +void test_relops( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T v0(0); + T v1(1); + T v2(1); + + optional def0 ; + optional def1 ; + optional opt0(v0); + optional opt1(v1); + optional opt2(v2); + + // Check identity + BOOST_TEST ( def0 == def0 ) ; + BOOST_TEST ( opt0 == opt0 ) ; + BOOST_TEST ( !(def0 != def0) ) ; + BOOST_TEST ( !(opt0 != opt0) ) ; + + // Check when both are uninitialized. + BOOST_TEST ( def0 == def1 ) ; // both uninitialized compare equal + BOOST_TEST ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized + BOOST_TEST ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized + BOOST_TEST ( !(def0 != def1) ) ; + BOOST_TEST ( def0 <= def1 ) ; + BOOST_TEST ( def0 >= def1 ) ; + + // Check when only lhs is uninitialized. + BOOST_TEST ( def0 != opt0 ) ; // uninitialized is never equal to initialized + BOOST_TEST ( !(def0 == opt0) ) ; + BOOST_TEST ( def0 < opt0 ) ; // uninitialized is always less than initialized + BOOST_TEST ( !(def0 > opt0) ) ; + BOOST_TEST ( def0 <= opt0 ) ; + BOOST_TEST ( !(def0 >= opt0) ) ; + + // Check when only rhs is uninitialized. + BOOST_TEST ( opt0 != def0 ) ; // initialized is never equal to uninitialized + BOOST_TEST ( !(opt0 == def0) ) ; + BOOST_TEST ( !(opt0 < def0) ) ; // initialized is never less than uninitialized + BOOST_TEST ( opt0 > def0 ) ; + BOOST_TEST ( !(opt0 <= def0) ) ; + BOOST_TEST ( opt0 >= opt0 ) ; + + // If both are initialized, values are compared + BOOST_TEST ( opt0 != opt1 ) ; + BOOST_TEST ( opt1 == opt2 ) ; + BOOST_TEST ( opt0 < opt1 ) ; + BOOST_TEST ( opt1 > opt0 ) ; + BOOST_TEST ( opt1 <= opt2 ) ; + BOOST_TEST ( opt1 >= opt0 ) ; + + // Compare against a value directly + BOOST_TEST ( opt0 == v0 ) ; + BOOST_TEST ( opt0 != v1 ) ; + BOOST_TEST ( opt1 == v2 ) ; + BOOST_TEST ( opt0 < v1 ) ; + BOOST_TEST ( opt1 > v0 ) ; + BOOST_TEST ( opt1 <= v2 ) ; + BOOST_TEST ( opt1 >= v0 ) ; + BOOST_TEST ( v0 != opt1 ) ; + BOOST_TEST ( v1 == opt2 ) ; + BOOST_TEST ( v0 < opt1 ) ; + BOOST_TEST ( v1 > opt0 ) ; + BOOST_TEST ( v1 <= opt2 ) ; + BOOST_TEST ( v1 >= opt0 ) ; + BOOST_TEST ( def0 != v0 ) ; + BOOST_TEST ( !(def0 == v0) ) ; + BOOST_TEST ( def0 < v0 ) ; + BOOST_TEST ( !(def0 > v0) ) ; + BOOST_TEST ( def0 <= v0 ) ; + BOOST_TEST ( !(def0 >= v0) ) ; + BOOST_TEST ( v0 != def0 ) ; + BOOST_TEST ( !(v0 == def0) ) ; + BOOST_TEST ( !(v0 < def0) ) ; + BOOST_TEST ( v0 > def0 ) ; + BOOST_TEST ( !(v0 <= def0) ) ; + BOOST_TEST ( v0 >= opt0 ) ; +} + +template +void test_none( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + using boost::none ; + + optional def0 ; + optional def1(none) ; + optional non_def( T(1234) ) ; + + BOOST_TEST ( def0 == none ) ; + BOOST_TEST ( non_def != none ) ; + BOOST_TEST ( !def1 ) ; + BOOST_TEST ( !(non_def < none) ) ; + BOOST_TEST ( non_def > none ) ; + BOOST_TEST ( !(non_def <= none) ) ; + BOOST_TEST ( non_def >= none ) ; + + non_def = none ; + BOOST_TEST ( !non_def ) ; + + test_default_implicit_construction(T(1),none); +} + +template +void test_arrow( T const* ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + T a(1234); + + optional oa(a) ; + optional const coa(a) ; + + BOOST_TEST ( coa->V() == 1234 ) ; + + oa->V() = 4321 ; + + BOOST_TEST ( a.V() = 1234 ) ; + BOOST_TEST ( (*oa).V() = 4321 ) ; +} + +void test_with_builtin_types() +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + test_basics( ARG(double) ); + test_conditional_ctor_and_get_value_or( ARG(double) ); + test_uninitialized_access( ARG(double) ); + test_no_throwing_swap( ARG(double) ); + test_relops( ARG(double) ) ; + test_none( ARG(double) ) ; +} + +// MSVC < 11.0 doesn't destroy X when we call ptr->VBase::VBase. +// Make sure that we work around this bug. +struct VBase : virtual X +{ + VBase(int v) : X(v) {} + // MSVC 8.0 doesn't generate this correctly... + VBase(const VBase& other) : X(static_cast(other)) {} +}; + +void test_with_class_type() +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + test_basics( ARG(X) ); + test_basics( ARG(VBase) ); + test_conditional_ctor_and_get_value_or( ARG(X) ); + test_direct_value_manip( ARG(X) ); + test_uninitialized_access( ARG(X) ); + test_throwing_direct_init( ARG(X) ); + test_throwing_val_assign_on_uninitialized( ARG(X) ); + test_throwing_val_assign_on_initialized( ARG(X) ); + test_throwing_copy_initialization( ARG(X) ); + test_throwing_assign_to_uninitialized( ARG(X) ); + test_throwing_assign_to_initialized( ARG(X) ); + test_no_throwing_swap( ARG(X) ); + test_throwing_swap( ARG(X) ); + test_relops( ARG(X) ) ; + test_none( ARG(X) ) ; + test_arrow( ARG(X) ) ; + BOOST_TEST ( X::count == 0 ) ; +} + +int eat ( bool ) { return 1 ; } +int eat ( char ) { return 1 ; } +int eat ( int ) { return 1 ; } +int eat ( void const* ) { return 1 ; } + +template int eat ( T ) { return 0 ; } + +// +// This verifies that operator safe_bool() behaves properly. +// +template +void test_no_implicit_conversions_impl( T const& ) +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + optional def ; + BOOST_TEST ( eat(def) == 0 ) ; +} + +void test_no_implicit_conversions() +{ + TRACE( std::endl << BOOST_CURRENT_FUNCTION ); + + bool b = false ; + char c = 0 ; + int i = 0 ; + void const* p = 0 ; + + test_no_implicit_conversions_impl(b); + test_no_implicit_conversions_impl(c); + test_no_implicit_conversions_impl(i); + test_no_implicit_conversions_impl(p); +} + + +// Test for support for classes with overridden operator& +class CustomAddressOfClass +{ + int n; + +public: + CustomAddressOfClass() : n(0) {} + CustomAddressOfClass(CustomAddressOfClass const& that) : n(that.n) {} + explicit CustomAddressOfClass(int m) : n(m) {} + int* operator& () { return &n; } + bool operator== (CustomAddressOfClass const& that) const { return n == that.n; } +}; + +void test_custom_addressof_operator() +{ + boost::optional< CustomAddressOfClass > o1(CustomAddressOfClass(10)); + BOOST_TEST(!!o1); + BOOST_TEST(o1.get() == CustomAddressOfClass(10)); + + o1 = CustomAddressOfClass(20); + BOOST_TEST(!!o1); + BOOST_TEST(o1.get() == CustomAddressOfClass(20)); + + o1 = boost::none; + BOOST_TEST(!o1); +} + +int main() +{ + try + { + test_with_class_type(); + test_with_builtin_types(); + test_no_implicit_conversions(); + test_custom_addressof_operator(); + } + catch ( ... ) + { + BOOST_ERROR("Unexpected Exception caught!"); + } + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_assign.cpp b/libs/optional/test/optional_test_assign.cpp new file mode 100644 index 00000000..07dfcdcd --- /dev/null +++ b/libs/optional/test/optional_test_assign.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2018 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/core/lightweight_test.hpp" +#include "boost/optional/optional.hpp" + +void test_assignment_to_empty() +{ + // this test used to fail on GCC 8.1.0/8.2.0/9.0.0 with -std=c++98 + boost::optional oa, ob(1); + BOOST_TEST(!oa); + BOOST_TEST(ob); + + oa = ob; + BOOST_TEST(oa); +} + +int main() +{ + test_assignment_to_empty(); + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_common.hpp b/libs/optional/test/optional_test_common.hpp new file mode 100644 index 00000000..389ad67c --- /dev/null +++ b/libs/optional/test/optional_test_common.hpp @@ -0,0 +1,283 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2014, Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#include + +#ifdef ENABLE_TRACE +#define TRACE(msg) std::cout << msg << std::endl ; +#else +#define TRACE(msg) +#endif + +namespace boost { + +void assertion_failed (char const * expr, char const * func, char const * file, long ) +{ + using std::string ; + string msg = string("Boost assertion failure for \"") + + string(expr) + + string("\" at file \"") + + string(file) + + string("\" function \"") + + string(func) + + string("\"") ; + + TRACE(msg); + + throw std::logic_error(msg); +} + +} + +using boost::optional ; + + +#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP +using boost::swap ; +using boost::get ; +using boost::get_pointer ; +#endif + +// MSVC6.0 does not support comparisons of optional against a literal null pointer value (0) +// via the safe_bool operator. +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1300) ) // 1300 == VC++ 7.1 +#define BOOST_OPTIONAL_NO_NULL_COMPARE +#else +#define BOOST_OPTIONAL_NO_NULL_COMPARE // Andrzej: I also disable 0 comparison everywhere +#endif + +#define ARG(T) (static_cast< T const* >(0)) + +// +// Helper class used to verify the lifetime management of the values held by optional +// +class X +{ + public : + + X ( int av ) : v(av) + { + ++ count ; + + TRACE ( "X::X(" << av << "). this=" << this ) ; + } + + X ( X const& rhs ) : v(rhs.v) + { + pending_copy = false ; + + TRACE ( "X::X( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ; + + if ( throw_on_copy ) + { + TRACE ( "throwing exception in X's copy ctor" ) ; + throw 0 ; + } + + ++ count ; + } + + ~X() + { + pending_dtor = false ; + + -- count ; + + TRACE ( "X::~X(). v=" << v << " this=" << this ); + } + + X& operator= ( X const& rhs ) + { + pending_assign = false ; + + if ( throw_on_assign ) + { + TRACE ( "throwing exception in X's assignment" ) ; + + v = -1 ; + + throw 0 ; + } + else + { + v = rhs.v ; + + TRACE ( "X::operator =( X const& rhs). this=" << this << " rhs.v=" << rhs.v ) ; + } + return *this ; + } + + friend bool operator == ( X const& a, X const& b ) + { return a.v == b.v ; } + + friend bool operator != ( X const& a, X const& b ) + { return a.v != b.v ; } + + friend bool operator < ( X const& a, X const& b ) + { return a.v < b.v ; } + + int V() const { return v ; } + int& V() { return v ; } + + static int count ; + static bool pending_copy ; + static bool pending_dtor ; + static bool pending_assign ; + static bool throw_on_copy ; + static bool throw_on_assign ; + + private : + + int v ; + + private : + + X() ; +} ; + + +int X::count = 0 ; +bool X::pending_copy = false ; +bool X::pending_dtor = false ; +bool X::pending_assign = false ; +bool X::throw_on_copy = false ; +bool X::throw_on_assign = false ; + +inline void set_pending_copy ( X const* ) { X::pending_copy = true ; } +inline void set_pending_dtor ( X const* ) { X::pending_dtor = true ; } +inline void set_pending_assign ( X const* ) { X::pending_assign = true ; } +inline void set_throw_on_copy ( X const* ) { X::throw_on_copy = true ; } +inline void set_throw_on_assign ( X const* ) { X::throw_on_assign = true ; } +inline void reset_throw_on_copy ( X const* ) { X::throw_on_copy = false ; } +inline void reset_throw_on_assign ( X const* ) { X::throw_on_assign = false ; } +inline void check_is_pending_copy ( X const* ) { BOOST_TEST( X::pending_copy ) ; } +inline void check_is_pending_dtor ( X const* ) { BOOST_TEST( X::pending_dtor ) ; } +inline void check_is_pending_assign ( X const* ) { BOOST_TEST( X::pending_assign ) ; } +inline void check_is_not_pending_copy ( X const* ) { BOOST_TEST( !X::pending_copy ) ; } +inline void check_is_not_pending_dtor ( X const* ) { BOOST_TEST( !X::pending_dtor ) ; } +inline void check_is_not_pending_assign( X const* ) { BOOST_TEST( !X::pending_assign ) ; } +inline void check_instance_count ( int c, X const* ) { BOOST_TEST( X::count == c ) ; } +inline int get_instance_count ( X const* ) { return X::count ; } + +inline void set_pending_copy (...) {} +inline void set_pending_dtor (...) {} +inline void set_pending_assign (...) {} +inline void set_throw_on_copy (...) {} +inline void set_throw_on_assign (...) {} +inline void reset_throw_on_copy (...) {} +inline void reset_throw_on_assign (...) {} +inline void check_is_pending_copy (...) {} +inline void check_is_pending_dtor (...) {} +inline void check_is_pending_assign (...) {} +inline void check_is_not_pending_copy (...) {} +inline void check_is_not_pending_dtor (...) {} +inline void check_is_not_pending_assign(...) {} +inline void check_instance_count (...) {} +inline int get_instance_count (...) { return 0 ; } + + +template +inline void check_uninitialized_const ( optional const& opt ) +{ +#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE + BOOST_TEST( opt == 0 ) ; +#endif + BOOST_TEST( !opt ) ; + BOOST_TEST( !get_pointer(opt) ) ; + BOOST_TEST( !opt.get_ptr() ) ; + BOOST_TEST( !opt.has_value() ) ; + BOOST_TEST( !opt.is_initialized() ) ; + BOOST_TEST( opt == boost::none ) ; +} +template +inline void check_uninitialized ( optional& opt ) +{ +#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE + BOOST_TEST( opt == 0 ) ; +#endif + BOOST_TEST( !opt ) ; + BOOST_TEST( !get_pointer(opt) ) ; + BOOST_TEST( !opt.get_ptr() ) ; + BOOST_TEST( !opt.has_value() ) ; + BOOST_TEST( !opt.is_initialized() ) ; + BOOST_TEST( opt == boost::none ) ; + + check_uninitialized_const(opt); +} + +template +inline void check_initialized_const ( optional const& opt ) +{ + BOOST_TEST( opt ) ; + +#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE + BOOST_TEST( opt != 0 ) ; +#endif + + BOOST_TEST ( !!opt ) ; + BOOST_TEST ( get_pointer(opt) ) ; + BOOST_TEST ( opt.get_ptr() ) ; + BOOST_TEST ( opt.has_value() ) ; + BOOST_TEST ( opt.is_initialized() ) ; + BOOST_TEST ( opt != boost::none ) ; +} + +template +inline void check_initialized ( optional& opt ) +{ + BOOST_TEST( opt ) ; + +#ifndef BOOST_OPTIONAL_NO_NULL_COMPARE + BOOST_TEST( opt != 0 ) ; +#endif + + BOOST_TEST ( !!opt ) ; + BOOST_TEST ( get_pointer(opt) ) ; + BOOST_TEST ( opt.get_ptr() ) ; + BOOST_TEST ( opt.has_value() ) ; + BOOST_TEST ( opt.is_initialized() ) ; + BOOST_TEST ( opt != boost::none ) ; + + check_initialized_const(opt); +} + +template +inline void check_value_const ( optional const& opt, T const& v, T const& z ) +{ + BOOST_TEST( *opt == v ) ; + BOOST_TEST( *opt != z ) ; + BOOST_TEST( opt.get() == v ) ; + BOOST_TEST( opt.get() != z ) ; + BOOST_TEST( (*(opt.operator->()) == v) ) ; + BOOST_TEST( *get_pointer(opt) == v ) ; +} + +template +inline void check_value ( optional& opt, T const& v, T const& z ) +{ +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) // 1200 == VC++ 6.0 + // For some reason, VC6.0 is creating a temporary while evaluating (*opt == v), + // so we need to turn throw on copy off first. + reset_throw_on_copy( ARG(T) ) ; +#endif + + BOOST_TEST( *opt == v ) ; + BOOST_TEST( *opt != z ) ; + BOOST_TEST( opt.get() == v ) ; + BOOST_TEST( opt.get() != z ) ; + BOOST_TEST( (*(opt.operator->()) == v) ) ; + BOOST_TEST( *get_pointer(opt) == v ) ; + + check_value_const(opt,v,z); +} + + diff --git a/libs/optional/test/optional_test_constructible_from_other.cpp b/libs/optional/test/optional_test_constructible_from_other.cpp new file mode 100644 index 00000000..af856862 --- /dev/null +++ b/libs/optional/test/optional_test_constructible_from_other.cpp @@ -0,0 +1,59 @@ +// Copyright (c) 2018 Andrey Semashev +// +// Use, modification, and distribution is subject to 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 test verifies that Boost.Optional copy constructors do not attempt to invoke +// the element type initializing constructors from templated arguments + +#include +#include + +struct no_type +{ + char data; +}; + +struct yes_type +{ + char data[2]; +}; + +template< unsigned int Size > +struct size_tag {}; + +template< typename T, typename U > +struct is_constructible +{ + static U& get(); + + template< typename T1 > + static yes_type check_helper(size_tag< sizeof(static_cast< T1 >(get())) >*); + template< typename T1 > + static no_type check_helper(...); + + static const bool value = sizeof(check_helper< T >(0)) == sizeof(yes_type); +}; + +template< typename T > +class wrapper +{ +public: + wrapper() {} + wrapper(wrapper const&) {} + template< typename U > + wrapper(U const&, typename boost::enable_if_c< is_constructible< T, U >::value, int >::type = 0) {} +}; + +inline boost::optional< wrapper< int > > foo() +{ + return boost::optional< wrapper< int > >(); +} + +int main() +{ + // Invokes boost::optional copy constructor. Should not invoke wrapper constructor from U. + boost::optional< wrapper< int > > res = foo(); + return 0; +} diff --git a/libs/optional/test/optional_test_conversions_from_U.cpp b/libs/optional/test/optional_test_conversions_from_U.cpp new file mode 100644 index 00000000..309cb869 --- /dev/null +++ b/libs/optional/test/optional_test_conversions_from_U.cpp @@ -0,0 +1,111 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: akrzemi1@gmail.com + + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" + +using boost::optional; + + +// testing types: +// X is convertible to Y +// ADeriv is convertible to ABase +struct X +{ + int val; + explicit X(int v) : val(v) {} +}; + +struct Y +{ + int yval; + Y(X const& x) : yval(x.val) {} + friend bool operator==(Y const& l, Y const& r) { return l.yval == r.yval; } +}; + +struct ABase +{ + int val; + explicit ABase(int v) : val(v) {} + friend bool operator==(ABase const& l, ABase const& r) { return l.val == r.val; } +}; + +struct ADeriv : ABase +{ + explicit ADeriv(int v) : ABase(v) {} +}; + + +template +void test_convert_optional_U_to_optional_T_for() +{ +#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR + { + optional ou(U(8)); + optional ot1(ou); + BOOST_TEST(ot1); + BOOST_TEST(*ot1 == T(*ou)); + } +#endif + +#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT + { + optional ou(U(8)); + optional ot2; + ot2 = ou; + BOOST_TEST(ot2); + BOOST_TEST(*ot2 == T(*ou)); + } +#endif +} + +void test_convert_optional_U_to_optional_T() +{ + test_convert_optional_U_to_optional_T_for(); + test_convert_optional_U_to_optional_T_for(); + test_convert_optional_U_to_optional_T_for(); + test_convert_optional_U_to_optional_T_for(); +} + +template +void test_convert_U_to_optional_T_for() +{ + U u(8); + optional ot1(u); + BOOST_TEST(ot1); + BOOST_TEST(*ot1 == T(u)); + + optional ot2; + ot2 = u; + BOOST_TEST(ot2); + BOOST_TEST(*ot2 == T(u)); +} + +void test_convert_U_to_optional_T() +{ + test_convert_U_to_optional_T_for(); + test_convert_U_to_optional_T_for(); + test_convert_U_to_optional_T_for(); + test_convert_U_to_optional_T_for(); +} + +int main() +{ + test_convert_optional_U_to_optional_T(); + test_convert_U_to_optional_T(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_convert_assign.cpp b/libs/optional/test/optional_test_convert_assign.cpp new file mode 100644 index 00000000..f0366dcf --- /dev/null +++ b/libs/optional/test/optional_test_convert_assign.cpp @@ -0,0 +1,57 @@ +// Copyright (C) 2021 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#include "boost/core/lightweight_test.hpp" +#include "boost/none.hpp" + +//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR + +using boost::optional; + +struct implicit_bool_conv +{ + operator bool() const { return false; } +}; + +struct explicit_bool_conv +{ + bool operator!() const BOOST_NOEXCEPT { return false; } + BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() +}; + +template +void test_convert_assign() +{ + optional oi; + oi = From(); + BOOST_TEST(oi); +} + +void test_no_bad_assignment() +{ +#if !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) + // this means that type trait `boost::is_assignable` works. + BOOST_STATIC_ASSERT((boost::is_assignable&, bool>::value)); + BOOST_STATIC_ASSERT((boost::is_assignable&, implicit_bool_conv>::value)); + BOOST_STATIC_ASSERT((! boost::is_assignable&, explicit_bool_conv>::value)); +#endif +} + +int main() +{ + test_convert_assign(); + test_convert_assign(); + test_no_bad_assignment(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_convert_from_T.cpp b/libs/optional/test/optional_test_convert_from_T.cpp new file mode 100644 index 00000000..bfa1a0aa --- /dev/null +++ b/libs/optional/test/optional_test_convert_from_T.cpp @@ -0,0 +1,70 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/none.hpp" + +//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR + +using boost::optional; +using boost::none; + +template +struct superconv +{ + #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + template + superconv(T&&) { BOOST_STATIC_ASSERT(sizeof(T) == 0); } + #else + template + superconv(const T&) { BOOST_STATIC_ASSERT(sizeof(T) == 0); } + template + superconv( T&) { BOOST_STATIC_ASSERT(sizeof(T) == 0); } + #endif + + superconv() {} +}; + +void test_optional_of_superconverting_T() // compile-time test +{ +#ifndef BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT + superconv > s; + superconv > & rs = s; + optional > > os = rs; +#endif +} + +void test_optional_optional_T() +{ + optional oi1 (1), oiN; + optional< optional > ooi1 (oi1), ooiN(oiN); + + BOOST_TEST(ooi1); + BOOST_TEST(*ooi1); + BOOST_TEST_EQ(**ooi1, 1); + + BOOST_TEST(ooiN); + BOOST_TEST(!*ooiN); +} + +int main() +{ + test_optional_optional_T(); + test_optional_of_superconverting_T(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_deleted_default_ctor.cpp b/libs/optional/test/optional_test_deleted_default_ctor.cpp new file mode 100644 index 00000000..ec38b913 --- /dev/null +++ b/libs/optional/test/optional_test_deleted_default_ctor.cpp @@ -0,0 +1,66 @@ +// Copyright 2017 Peter Dimov +// Copyright 2017 Vinnie Falco +// Copyright 2018 Andrzej Krzemienski +// +// Distributed under the Boost Software License, Version 1.0. +// +// http://www.boost.org/LICENSE_1_0.txt + +#include + +#if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + +int main() +{ +} + +#else + +#include +#include + +class basic_multi_buffer; + +class const_buffers_type // a similar declaration in boost.beast had problem +{ // with boost optional + basic_multi_buffer const* b_; + + friend class basic_multi_buffer; + + explicit + const_buffers_type(basic_multi_buffer const& b); + +public: + const_buffers_type() = delete; + const_buffers_type(const_buffers_type const&) = default; + const_buffers_type& operator=(const_buffers_type const&) = default; +}; + +void test_beast_example() +{ + // test if it even compiles + boost::optional< std::pair > opt, opt2; + opt = opt2; + (void)opt; +} + +struct NotDefaultConstructible // minimal class exposing the problem +{ + NotDefaultConstructible() = delete; +}; + +void test_assign_for_non_default_constructible() +{ + // test if it even compiles + boost::optional opt, opt2; + opt = opt2; + (void)opt; +} + +int main() +{ + test_beast_example(); + test_assign_for_non_default_constructible(); +} + +#endif diff --git a/libs/optional/test/optional_test_emplace.cpp b/libs/optional/test/optional_test_emplace.cpp new file mode 100644 index 00000000..5182d97f --- /dev/null +++ b/libs/optional/test/optional_test_emplace.cpp @@ -0,0 +1,390 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include +#include "boost/core/lightweight_test.hpp" +#include "boost/none.hpp" + +//#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT +//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR + +using boost::optional; +using boost::none; +using boost::in_place_init; +using boost::in_place_init_if; + +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +class Guard +{ +public: + int which_ctor; + Guard () : which_ctor(0) { } + Guard (int&, double&&) : which_ctor(1) { } + Guard (int&&, double&) : which_ctor(2) { } + Guard (int&&, double&&) : which_ctor(3) { } + Guard (int&, double&) : which_ctor(4) { } + Guard (std::string const&) : which_ctor(5) { } + Guard (std::string &) : which_ctor(6) { } + Guard (std::string &&) : which_ctor(7) { } +private: + Guard(Guard&&); + Guard(Guard const&); + void operator=(Guard &&); + void operator=(Guard const&); +}; + + +void test_emplace() +{ + int i = 0; + double d = 0.0; + const std::string cs; + std::string ms; + optional o; + + o.emplace(); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + + o.emplace(i, 2.0); + BOOST_TEST(o); + BOOST_TEST(1 == o->which_ctor); + + o.emplace(1, d); + BOOST_TEST(o); + BOOST_TEST(2 == o->which_ctor); + + o.emplace(1, 2.0); + BOOST_TEST(o); + BOOST_TEST(3 == o->which_ctor); + + o.emplace(i, d); + BOOST_TEST(o); + BOOST_TEST(4 == o->which_ctor); + + o.emplace(cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + + o.emplace(ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); + + o.emplace(std::string()); + BOOST_TEST(o); + BOOST_TEST(7 == o->which_ctor); +} + +void test_in_place_ctor() +{ + int i = 0; + double d = 0.0; + const std::string cs; + std::string ms; + + { + optional o (in_place_init); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + } + { + optional o (in_place_init, i, 2.0); + BOOST_TEST(o); + BOOST_TEST(1 == o->which_ctor); + } + { + optional o (in_place_init, 1, d); + BOOST_TEST(o); + BOOST_TEST(2 == o->which_ctor); + } + { + optional o (in_place_init, 1, 2.0); + BOOST_TEST(o); + BOOST_TEST(3 == o->which_ctor); + } + { + optional o (in_place_init, i, d); + BOOST_TEST(o); + BOOST_TEST(4 == o->which_ctor); + } + { + optional o (in_place_init, cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + } + { + optional o (in_place_init, ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); + } + { + optional o (in_place_init, std::string()); + BOOST_TEST(o); + BOOST_TEST(7 == o->which_ctor); + } +} + +void test_in_place_if_ctor() +{ + int i = 0; + double d = 0.0; + const std::string cs; + std::string ms; + + { + optional o (in_place_init_if, true); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + } + { + optional o (in_place_init_if, true, i, 2.0); + BOOST_TEST(o); + BOOST_TEST(1 == o->which_ctor); + } + { + optional o (in_place_init_if, true, 1, d); + BOOST_TEST(o); + BOOST_TEST(2 == o->which_ctor); + } + { + optional o (in_place_init_if, true, 1, 2.0); + BOOST_TEST(o); + BOOST_TEST(3 == o->which_ctor); + } + { + optional o (in_place_init_if, true, i, d); + BOOST_TEST(o); + BOOST_TEST(4 == o->which_ctor); + } + { + optional o (in_place_init_if, true, cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + } + { + optional o (in_place_init_if, true, ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); + } + { + optional o (in_place_init_if, true, std::string()); + BOOST_TEST(o); + BOOST_TEST(7 == o->which_ctor); + } + + { + optional o (in_place_init_if, false, 1, 2.0); + BOOST_TEST(!o); + } +} + + +#endif + +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + + +struct ThrowOnMove +{ + ThrowOnMove(ThrowOnMove&&) { throw int(); } + ThrowOnMove(ThrowOnMove const&) { throw int(); } + ThrowOnMove(int){} +}; + + +void test_no_moves_on_emplacement() +{ + try { + optional o; + o.emplace(1); + BOOST_TEST(o); + } + catch (...) { + BOOST_TEST(false); + } +} + +void test_no_moves_on_in_place_ctor() +{ + try { + optional o (in_place_init, 1); + BOOST_TEST(o); + + optional p (in_place_init_if, true, 1); + BOOST_TEST(p); + + optional q (in_place_init_if, false, 1); + BOOST_TEST(!q); + } + catch (...) { + BOOST_TEST(false); + } +} + +#endif + +struct Thrower +{ + Thrower(bool throw_) { if (throw_) throw int(); } + +private: + Thrower(Thrower const&); +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + Thrower(Thrower&&); +#endif +}; + +void test_clear_on_throw() +{ + optional ot; + try { + ot.emplace(false); + BOOST_TEST(ot); + } catch(...) { + BOOST_TEST(false); + } + + try { + ot.emplace(true); + BOOST_TEST(false); + } catch(...) { + BOOST_TEST(!ot); + } +} + +void test_no_assignment_on_emplacement() +{ + optional os, ot; + BOOST_TEST(!os); + os.emplace("wow"); + BOOST_TEST(os); + BOOST_TEST_EQ(*os, "wow"); + + BOOST_TEST(!ot); + ot.emplace(); + BOOST_TEST(ot); + BOOST_TEST_EQ(*ot, ""); +} + +namespace no_rvalue_refs { + +class Guard +{ +public: + int which_ctor; + Guard () : which_ctor(0) { } + Guard (std::string const&) : which_ctor(5) { } + Guard (std::string &) : which_ctor(6) { } +private: + Guard(Guard const&); + void operator=(Guard const&); +}; + +void test_emplace() +{ + const std::string cs; + std::string ms; + optional o; + + o.emplace(); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + + o.emplace(cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + + o.emplace(ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); +} + +void test_in_place_ctor() +{ + const std::string cs; + std::string ms; + + { + optional o (in_place_init); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + } + { + optional o (in_place_init, cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + } + { + optional o (in_place_init, ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); + } +} + +void test_in_place_if_ctor() +{ + const std::string cs; + std::string ms; + + { + optional n (in_place_init_if, false); + BOOST_TEST(!n); + + optional o (in_place_init_if, true); + BOOST_TEST(o); + BOOST_TEST(0 == o->which_ctor); + } + { + optional n (in_place_init_if, false, cs); + BOOST_TEST(!n); + + optional o (in_place_init_if, true, cs); + BOOST_TEST(o); + BOOST_TEST(5 == o->which_ctor); + } + { + optional n (in_place_init_if, false, ms); + BOOST_TEST(!n); + + optional o (in_place_init_if, true, ms); + BOOST_TEST(o); + BOOST_TEST(6 == o->which_ctor); + } +} + +} // namespace no_rvalue_ref + +int main() +{ +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES) + test_emplace(); + test_in_place_ctor(); + test_in_place_if_ctor(); +#endif +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + test_no_moves_on_emplacement(); + test_no_moves_on_in_place_ctor(); +#endif + test_clear_on_throw(); + test_no_assignment_on_emplacement(); + no_rvalue_refs::test_emplace(); + no_rvalue_refs::test_in_place_ctor(); + no_rvalue_refs::test_in_place_if_ctor(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_empty_braces.cpp b/libs/optional/test/optional_test_empty_braces.cpp new file mode 100644 index 00000000..273d81d1 --- /dev/null +++ b/libs/optional/test/optional_test_empty_braces.cpp @@ -0,0 +1,57 @@ +// Copyright (C) 2016 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" + +//#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT +//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR + +using boost::optional; + +struct Value +{ + explicit Value(int) {} +}; + +#ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX +template +void test_brace_init() +{ + optional o = {}; + BOOST_TEST(!o); +} + +template +void test_brace_assign() +{ + optional o; + o = {}; + BOOST_TEST(!o); +} +#endif + +int main() +{ +#ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX + test_brace_init(); + test_brace_init(); + test_brace_assign(); + test_brace_assign(); +#endif + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_equals_none.cpp b/libs/optional/test/optional_test_equals_none.cpp new file mode 100644 index 00000000..1e3157b1 --- /dev/null +++ b/libs/optional/test/optional_test_equals_none.cpp @@ -0,0 +1,43 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/none.hpp" + + +struct SemiRegular // no operator== +{ +private: void operator==(SemiRegular const&) const {} +private: void operator!=(SemiRegular const&) const {} +}; + +void test_equal_to_none_of_noncomparable_T() +{ + boost::optional i = SemiRegular(); + boost::optional o; + + BOOST_TEST(i != boost::none); + BOOST_TEST(boost::none != i); + BOOST_TEST(o == boost::none); + BOOST_TEST(boost::none == o); +} + +int main() +{ + test_equal_to_none_of_noncomparable_T(); + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_experimental_traits.cpp b/libs/optional/test/optional_test_experimental_traits.cpp new file mode 100644 index 00000000..5088b4a2 --- /dev/null +++ b/libs/optional/test/optional_test_experimental_traits.cpp @@ -0,0 +1,152 @@ +// Copyright (C) 2017 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/core/lightweight_test_trait.hpp" +#include "boost/type_traits/is_base_of.hpp" +#include "boost/optional/detail/experimental_traits.hpp" + +#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS + +struct PrivDefault +{ + private: PrivDefault() {} +}; + +struct CustDefault +{ + CustDefault() {} +}; + +struct CustomizedTrivial +{ + CustomizedTrivial() {} +}; + +struct DeletedDefault +{ + BOOST_DELETED_FUNCTION(DeletedDefault()) +}; + +namespace boost { namespace optional_config { + +template <> struct optional_uses_direct_storage_for : boost::true_type {}; + +}} + +struct CustDtor +{ + ~CustDtor() {} +}; + +struct NoDefault +{ + explicit NoDefault(int) {} +}; + +struct Empty {}; + +template +struct Aggregate { T t; U u; }; + +struct CustAssign +{ + CustAssign& operator=(CustAssign const&) { return *this; } +}; + +struct CustMove +{ + CustMove(CustMove &&) {} +}; + +void test_type_traits() +{ + // this only tests if type traits are implemented correctly + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); + + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); + + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); + + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); + + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); + + +#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for, double> > )); + + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable, double> > )); + + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); +#endif + + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); + + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable > )); +} + +void test_trivial_copyability() +{ + BOOST_TEST_TRAIT_TRUE((boost::is_base_of, boost::optional > )); + BOOST_TEST_TRAIT_TRUE((boost::is_base_of, boost::optional > )); + BOOST_TEST_TRAIT_TRUE((boost::is_base_of, boost::optional > )); + BOOST_TEST_TRAIT_FALSE((boost::is_base_of, boost::optional > )); + +#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable, double> > > )); + + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable > )); +#endif +} + +#endif + +int main() +{ +#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS + test_type_traits(); + test_trivial_copyability(); +#endif + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_fail1.cpp b/libs/optional/test/optional_test_fail1.cpp new file mode 100644 index 00000000..6073466d --- /dev/null +++ b/libs/optional/test/optional_test_fail1.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#include "boost/optional.hpp" + +// +// THIS TEST SHOULD FAIL TO COMPILE +// +void test_deep_constantness() +{ + boost::optional opt ; + boost::optional const copt ; + + *copt = opt ; // Cannot assign to "int const&" +} + + diff --git a/libs/optional/test/optional_test_fail2.cpp b/libs/optional/test/optional_test_fail2.cpp new file mode 100644 index 00000000..36b42bfc --- /dev/null +++ b/libs/optional/test/optional_test_fail2.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#include "boost/optional.hpp" + +// +// THIS TEST SHOULD FAIL TO COMPILE +// +void test_no_implicit_conversion() +{ + boost::optional opt(1) ; + + // You can compare against 0 or against another optional<>, + // but not against another value + if ( opt == 1 ) ; +} + + diff --git a/libs/optional/test/optional_test_fail3.cpp b/libs/optional/test/optional_test_fail3.cpp new file mode 100644 index 00000000..12c3ff8c --- /dev/null +++ b/libs/optional/test/optional_test_fail3.cpp @@ -0,0 +1,33 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#include "boost/optional.hpp" + +// +// THIS TEST SHOULD FAIL TO COMPILE +// +#if BOOST_WORKAROUND( BOOST_INTEL_CXX_VERSION, <= 700) // Intel C++ 7.0 +// Intel C++ 7.0 incorrectly accepts the initialization "boost::optional opt = 3" +// even though the ctor is explicit (c.f. 12.3.1.2), so the test uses another form of +// copy-initialization: argument-passing (8.5.12) +void helper ( boost::optional ) ; +void test_explicit_constructor() +{ + helper(3) ; // ERROR: Ctor is explicit. +} +#else +void test_explicit_constructor() +{ + boost::optional opt = 3 ; // ERROR: Ctor is explicit. +} +#endif + + diff --git a/libs/optional/test/optional_test_fail3a.cpp b/libs/optional/test/optional_test_fail3a.cpp new file mode 100644 index 00000000..6204853a --- /dev/null +++ b/libs/optional/test/optional_test_fail3a.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#include + +#include "boost/optional.hpp" + +// +// THIS TEST SHOULD FAIL TO COMPILE +// +void test_no_unsupported_conversion() +{ + boost::optional opt1(1) ; + boost::optional< std::string > opt2( opt1 ) ; // Cannot convert from "int" to "std::string" +} + + diff --git a/libs/optional/test/optional_test_fail3b.cpp b/libs/optional/test/optional_test_fail3b.cpp new file mode 100644 index 00000000..8058b8b1 --- /dev/null +++ b/libs/optional/test/optional_test_fail3b.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#include + +#include "boost/optional.hpp" + +struct A {} ; +struct B {} ; +// +// THIS TEST SHOULD FAIL TO COMPILE +// +void test_no_unsupported_conversion() +{ + boost::optional opt1; + boost::optional opt2; + opt2 = opt1 ; // Cannot convert from "A" to "B" +} + + diff --git a/libs/optional/test/optional_test_fail_const_swap.cpp b/libs/optional/test/optional_test_fail_const_swap.cpp new file mode 100644 index 00000000..b91582cf --- /dev/null +++ b/libs/optional/test/optional_test_fail_const_swap.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2018, Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional.hpp" + +// THIS TEST SHOULD FAIL TO COMPILE + +void test_converting_assignment_of_different_enums() +{ + const boost::optional o1(1); + const boost::optional o2(2); + swap(o1, o2); // no swap on const objects should compile +} + +int main() +{ + test_converting_assignment_of_different_enums(); +} diff --git a/libs/optional/test/optional_test_fail_convert_assign_of_enums.cpp b/libs/optional/test/optional_test_fail_convert_assign_of_enums.cpp new file mode 100644 index 00000000..149df034 --- /dev/null +++ b/libs/optional/test/optional_test_fail_convert_assign_of_enums.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2015, Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional.hpp" + +// THIS TEST SHOULD FAIL TO COMPILE + +enum E1 {e1}; +enum E2 {e2}; + +void test_converting_assignment_of_different_enums() +{ + boost::optional o2(e2); + boost::optional o1; + o1 = o2; +} + +int main() {} diff --git a/libs/optional/test/optional_test_fail_convert_from_null.cpp b/libs/optional/test/optional_test_fail_convert_from_null.cpp new file mode 100644 index 00000000..a454615d --- /dev/null +++ b/libs/optional/test/optional_test_fail_convert_from_null.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2014, Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com +// +#include "boost/optional.hpp" + +// +// THIS TEST SHOULD FAIL TO COMPILE +// + +struct NoInitFromNull{}; + +void test_conversion_from_null() +{ + boost::optional opt = 0; +} + + diff --git a/libs/optional/test/optional_test_fail_copying_a_moveable_type.cpp b/libs/optional/test/optional_test_fail_copying_a_moveable_type.cpp new file mode 100644 index 00000000..c1194cda --- /dev/null +++ b/libs/optional/test/optional_test_fail_copying_a_moveable_type.cpp @@ -0,0 +1,36 @@ +// Copyright (C) 2014, Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com +// +#include "boost/optional.hpp" + +class MoveOnly +{ +public: + int val; + MoveOnly(int v) : val(v) {} + MoveOnly(MoveOnly&& rhs) : val(rhs.val) { rhs.val = 0; } + void operator=(MoveOnly&& rhs) {val = rhs.val; rhs.val = 0; } + +private: + MoveOnly(MoveOnly const&); + void operator=(MoveOnly const&); +}; + +// +// THIS TEST SHOULD FAIL TO COMPILE +// +void test_copying_optional_with_noncopyable_T() +{ + boost::optional opt1 ; + boost::optional opt2(opt1) ; +} + + diff --git a/libs/optional/test/optional_test_fail_explicit_convert_in_value_or.cpp b/libs/optional/test/optional_test_fail_explicit_convert_in_value_or.cpp new file mode 100644 index 00000000..7b6f29c5 --- /dev/null +++ b/libs/optional/test/optional_test_fail_explicit_convert_in_value_or.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2014, Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com +// +#include "boost/optional.hpp" + +// +// THIS TEST SHOULD FAIL TO COMPILE +// + +struct U +{}; + +struct T +{ + explicit T(U const&) {} +}; + + +void test_implicit_conversion_to_bool() +{ + boost::optional opt; + opt.value_or(U()); +} + diff --git a/libs/optional/test/optional_test_fail_explicit_convert_in_value_or_call.cpp b/libs/optional/test/optional_test_fail_explicit_convert_in_value_or_call.cpp new file mode 100644 index 00000000..e37d2351 --- /dev/null +++ b/libs/optional/test/optional_test_fail_explicit_convert_in_value_or_call.cpp @@ -0,0 +1,34 @@ +// Copyright (C) 2014, Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com +// +#include "boost/optional.hpp" + +// +// THIS TEST SHOULD FAIL TO COMPILE +// + +struct U +{}; + +struct T +{ + explicit T(U const&) {} +}; + +U get_U() { return U(); } + + +void test_verifying_the_implicit_conversion_to_bool() +{ + boost::optional opt; + opt.value_or_eval(get_U); +} + diff --git a/libs/optional/test/optional_test_fail_implicit_bool_convert.cpp b/libs/optional/test/optional_test_fail_implicit_bool_convert.cpp new file mode 100644 index 00000000..5009373c --- /dev/null +++ b/libs/optional/test/optional_test_fail_implicit_bool_convert.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2014, Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com +// +#include "boost/optional.hpp" + +// +// THIS TEST SHOULD FAIL TO COMPILE +// + +#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + +bool test_implicit_conversion_to_bool() +{ + boost::optional opt; + return opt; +} + +#else +# error "Test skipped: this compiler does not support explicit conversion operators." +#endif diff --git a/libs/optional/test/optional_test_fail_io_without_io.cpp b/libs/optional/test/optional_test_fail_io_without_io.cpp new file mode 100644 index 00000000..e986d372 --- /dev/null +++ b/libs/optional/test/optional_test_fail_io_without_io.cpp @@ -0,0 +1,24 @@ +// Copyright (C) 2015, Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include +#include "boost/optional.hpp" +// but no boost/optional/optional_io.hpp + +// THIS TEST SHOULD FAIL TO COMPILE +// Unless one includes header boost/optional/optional_io.hpp, it should not be possible +// to stream out an optional object. + +void test_streaming_out_optional() +{ + boost::optional opt; + std::cout << opt; +} \ No newline at end of file diff --git a/libs/optional/test/optional_test_fail_none_io_without_io.cpp b/libs/optional/test/optional_test_fail_none_io_without_io.cpp new file mode 100644 index 00000000..7fa19a9f --- /dev/null +++ b/libs/optional/test/optional_test_fail_none_io_without_io.cpp @@ -0,0 +1,23 @@ +// Copyright (C) 2015, Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include +#include "boost/none.hpp" +// but no boost/optional/optional_io.hpp + +// THIS TEST SHOULD FAIL TO COMPILE +// Unless one includes header boost/optional/optional_io.hpp, it should not be possible +// to stream out boost::none. + +void test_streaming_out_none() +{ + std::cout << boost::none; +} \ No newline at end of file diff --git a/libs/optional/test/optional_test_fail_optional_rvalue_ref.cpp b/libs/optional/test/optional_test_fail_optional_rvalue_ref.cpp new file mode 100644 index 00000000..5a1e039d --- /dev/null +++ b/libs/optional/test/optional_test_fail_optional_rvalue_ref.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2014, Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com +// +#include "boost/optional.hpp" +// +// THIS TEST SHOULD FAIL TO COMPILE +// + +boost::optional oi; + + diff --git a/libs/optional/test/optional_test_flat_map.cpp b/libs/optional/test/optional_test_flat_map.cpp new file mode 100644 index 00000000..05ed63aa --- /dev/null +++ b/libs/optional/test/optional_test_flat_map.cpp @@ -0,0 +1,275 @@ +// Copyright (C) 2018 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/ignore_unused.hpp" +#include "boost/core/lightweight_test.hpp" +#include "boost/core/lightweight_test_trait.hpp" +#include "boost/type_traits/is_same.hpp" + + +using boost::optional; +using boost::make_optional; +using boost::is_same; + +template +void verify_type(Deduced) +{ + BOOST_TEST_TRAIT_TRUE(( is_same )); +} + +struct Int +{ + int i; + explicit Int(int i_) : i(i_) {} +}; + +struct convert_t +{ + typedef optional result_type; + optional operator()(int i) { if (i != 0) return Int(i); else return boost::none; } +}; + +void test_flat_map_on_mutable_optional_with_function_object() +{ + { + optional oi (1); + verify_type< optional >(oi.flat_map(convert_t())); + optional oI = oi.flat_map(convert_t()); + BOOST_TEST(bool(oI)); + BOOST_TEST_EQ(1, oI->i); + } + { + optional oi (0); + optional oI = oi.flat_map(convert_t()); + BOOST_TEST(!oI); + } + { + optional oi; + optional oI = oi.flat_map(convert_t()); + BOOST_TEST(!oI); + } +} + +void test_flat_map_on_const_optional_with_function_object() +{ + { + const optional oi (1); + verify_type< optional >(oi.flat_map(convert_t())); + optional oI = oi.flat_map(convert_t()); + BOOST_TEST(bool(oI)); + BOOST_TEST_EQ(1, oI->i); + } + { + const optional oi (0); + optional oI = oi.flat_map(convert_t()); + BOOST_TEST(!oI); + } + { + const optional oi; + optional oI = oi.flat_map(convert_t()); + BOOST_TEST(!oI); + } +} + +void test_flat_map_with_lambda() +{ +#if !defined BOOST_NO_CXX11_LAMBDAS && !defined BOOST_NO_CXX11_DECLTYPE_N3276 + { + optional oi (1); + verify_type< optional >(oi.flat_map([](int i){ return optional(i == 0, Int(i)); })); + optional oI = oi.flat_map([](int i){ return optional(i != 0, Int(i)); }); + BOOST_TEST(bool(oI)); + BOOST_TEST_EQ(1, oI->i); + } + { + optional oi (0); + optional oI = oi.flat_map([](int i){ return optional(i != 0, Int(i)); }); + BOOST_TEST(!oI); + } + { + optional oi; + optional oI = oi.flat_map([](int i){ return optional(i != 0, Int(i)); }); + BOOST_TEST(!oI); + } +#endif // lambdas +} + +struct get_opt_ref +{ + typedef optional result_type; + optional operator()(int& i) { return i != 0 ? optional(i) : optional(); } +}; + +void test_flat_map_obj_to_ref() +{ + { + optional oi (2); + verify_type< optional >(oi.flat_map(get_opt_ref())); + optional ori = oi.flat_map(get_opt_ref()); + BOOST_TEST(bool(ori)); + BOOST_TEST_EQ(2, *ori); + *ori = 3; + BOOST_TEST(bool(oi)); + BOOST_TEST_EQ(3, *oi); + BOOST_TEST_EQ(3, *ori); + } + { + optional oi (0); + optional ori = oi.flat_map(get_opt_ref()); + BOOST_TEST(!ori); + } + { + optional oi; + optional ori = oi.flat_map(get_opt_ref()); + BOOST_TEST(!ori); + } +} + +optional get_opt_int_ref(Int& i) +{ + return i.i ? optional(i.i) : optional(); +} + +void test_flat_map_ref_to_ref() +{ + { + Int I (5); + optional orI (I); + verify_type< optional >(orI.flat_map(get_opt_int_ref)); + optional ori = orI.flat_map(get_opt_int_ref); + BOOST_TEST(bool(ori)); + BOOST_TEST_EQ(5, *ori); + *ori = 6; + BOOST_TEST_EQ(6, *ori); + BOOST_TEST_EQ(6, I.i); + } + { + Int I (0); + optional orI (I); + optional ori = orI.flat_map(get_opt_int_ref); + BOOST_TEST(!ori); + } + { + optional orI; + optional ori = orI.flat_map(get_opt_int_ref); + BOOST_TEST(!ori); + } +} + +optional< optional > make_opt_int(int i) +{ + if (i == 0) + return boost::none; + else if (i == 1) + return boost::make_optional(optional()); + else + return boost::make_optional(boost::make_optional(Int(i))); +} + +void test_flat_map_opt_opt() +{ + { + optional oi (9); + verify_type > >(oi.flat_map(make_opt_int)); + optional > ooI = oi.flat_map(make_opt_int); + BOOST_TEST(bool(ooI)); + BOOST_TEST(bool(*ooI)); + BOOST_TEST_EQ(9, (**ooI).i); + } + { + optional oi (1); + optional > ooI = oi.flat_map(make_opt_int); + BOOST_TEST(bool(ooI)); + BOOST_TEST(!*ooI); + } + { + optional oi (0); + optional > ooI = oi.flat_map(make_opt_int); + BOOST_TEST(!ooI); + } + { + optional oi; + optional > ooI = oi.flat_map(make_opt_int); + BOOST_TEST(!ooI); + } +} + +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) +struct MoveOnly +{ + int value; + explicit MoveOnly(int i) : value(i) {} + MoveOnly(MoveOnly && r) : value(r.value) { r.value = 0; } + MoveOnly& operator=(MoveOnly && r) { value = r.value; r.value = 0; return *this; } + +private: + MoveOnly(MoveOnly const&); + void operator=(MoveOnly const&); +}; + +MoveOnly makeMoveOnly(int i) +{ + return MoveOnly(i); +} + +optional makeOptMoveOnly(int i) +{ + return optional(MoveOnly(i)); +} + +optional get_val(MoveOnly m) +{ + return optional(m.value != 0, m.value); +} + +void test_flat_map_move_only() +{ + { + optional om (makeMoveOnly(1)), om2 (makeMoveOnly(2)); + verify_type >(boost::move(om).flat_map(get_val)); + optional oi = boost::move(om2).flat_map(get_val); + BOOST_TEST(bool(oi)); + BOOST_TEST_EQ(2, *oi); + } + { + optional oj = makeOptMoveOnly(4).flat_map(get_val); + BOOST_TEST(bool(oj)); + BOOST_TEST_EQ(4, *oj); + } + { + optional oj = optional().flat_map(get_val); + BOOST_TEST(!oj); + } +} + +#endif // no rvalue refs + +int main() +{ + test_flat_map_on_mutable_optional_with_function_object(); + test_flat_map_on_const_optional_with_function_object(); + test_flat_map_with_lambda(); + test_flat_map_obj_to_ref(); + test_flat_map_ref_to_ref(); + test_flat_map_opt_opt(); + +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + test_flat_map_move_only(); +#endif + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_hash.cpp b/libs/optional/test/optional_test_hash.cpp new file mode 100644 index 00000000..8a631a25 --- /dev/null +++ b/libs/optional/test/optional_test_hash.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" +#include "boost/config.hpp" +#include "boost/core/lightweight_test.hpp" + +#if !defined(BOOST_NO_CXX11_HDR_UNORDERED_SET) && !defined(BOOST_OPTIONAL_CONFIG_DO_NOT_SPECIALIZE_STD_HASH) + +#include + +void test_unordered_map() +{ + std::unordered_set > set; + set.insert(boost::optional(1)); + set.insert(boost::optional(1)); + + + BOOST_TEST(set.size() == 1u); + BOOST_TEST(set.find(boost::optional(1)) != set.end()); +} + +#else + +void test_unordered_map() +{} + +#endif + + +#if !defined(BOOST_OPTIONAL_CONFIG_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) + +void tets_hash() +{ + std::hash > hash_int; + boost::optional oN; + boost::optional o1(1); + + BOOST_TEST(hash_int(oN) == hash_int(oN)); + BOOST_TEST(hash_int(o1) == hash_int(o1)); +} + +#else + +void tets_hash() +{} + +#endif + + +int main() +{ + test_unordered_map(); + tets_hash(); + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_inplace_factory.cpp b/libs/optional/test/optional_test_inplace_factory.cpp new file mode 100644 index 00000000..9960c624 --- /dev/null +++ b/libs/optional/test/optional_test_inplace_factory.cpp @@ -0,0 +1,113 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com + +#include +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT +#include "boost/utility/in_place_factory.hpp" +#include "boost/utility/typed_in_place_factory.hpp" +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/none.hpp" + +struct Guard +{ + double num; + std::string str; + Guard() : num() {} + Guard(double num_, std::string str_) : num(num_), str(str_) {} + + friend bool operator==(const Guard& lhs, const Guard& rhs) { return lhs.num == rhs.num && lhs.str == rhs.str; } + friend bool operator!=(const Guard& lhs, const Guard& rhs) { return !(lhs == rhs); } + +private: + Guard(const Guard&); + Guard& operator=(const Guard&); +}; + +void test_ctor() +{ +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + Guard g0, g1(1.0, "one"), g2(2.0, "two"); + + boost::optional og0 ( boost::in_place() ); + boost::optional og1 ( boost::in_place(1.0, "one") ); + boost::optional og1_( boost::in_place(1.0, "one") ); + boost::optional og2 ( boost::in_place(2.0, "two") ); + + BOOST_TEST(og0); + BOOST_TEST(og1); + BOOST_TEST(og1_); + BOOST_TEST(og2); + + BOOST_TEST(*og0 == g0); + BOOST_TEST(*og1 == g1); + BOOST_TEST(*og1_ == g1); + BOOST_TEST(*og2 == g2); + + BOOST_TEST(og1_ == og1); + BOOST_TEST(og1_ != og2); + BOOST_TEST(og1_ != og0); + + boost::optional o( boost::in_place(5) ); + BOOST_TEST(o); + BOOST_TEST(*o == 5); +#endif +} + +void test_assign() +{ +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT +#ifndef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION + Guard g0, g1(1.0, "one"), g2(2.0, "two"); + + boost::optional og0, og1, og1_, og2; + + og0 = boost::in_place(); + og1 = boost::in_place(1.0, "one"); + og1_ = boost::in_place(1.0, "one"); + og2 = boost::in_place(2.0, "two"); + + BOOST_TEST(og0); + BOOST_TEST(og1); + BOOST_TEST(og1_); + BOOST_TEST(og2); + + BOOST_TEST(*og0 == g0); + BOOST_TEST(*og1 == g1); + BOOST_TEST(*og1_ == g1); + BOOST_TEST(*og2 == g2); + + BOOST_TEST(og1_ == og1); + BOOST_TEST(og1_ != og2); + BOOST_TEST(og1_ != og0); + + boost::optional o; + o = boost::in_place(5); + BOOST_TEST(o); + BOOST_TEST(*o == 5); +#endif +#endif +} + +int main() +{ + test_ctor(); + test_assign(); + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_inplace_fail.cpp b/libs/optional/test/optional_test_inplace_fail.cpp new file mode 100644 index 00000000..38722baf --- /dev/null +++ b/libs/optional/test/optional_test_inplace_fail.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com + +#include +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT +#include "boost/utility/in_place_factory.hpp" +#include "boost/utility/typed_in_place_factory.hpp" +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/none.hpp" + +struct Guard +{ + double num; + std::string str; + Guard() : num() {} + Guard(double num_, std::string str_) : num(num_), str(str_) {} + + friend bool operator==(const Guard& lhs, const Guard& rhs) { return lhs.num == rhs.num && lhs.str == rhs.str; } + friend bool operator!=(const Guard& lhs, const Guard& rhs) { return !(lhs == rhs); } + +private: + Guard(const Guard&); + Guard& operator=(const Guard&); +}; + + +int main() +{ +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + int excessive_param = 2; + boost::optional og1 ( boost::in_place(1.0, "one", excessive_param) ); +#else + NOTHING_TO_TEST_SO_JUST_FAIL +#endif + return 0; +} \ No newline at end of file diff --git a/libs/optional/test/optional_test_inplace_fail2.cpp b/libs/optional/test/optional_test_inplace_fail2.cpp new file mode 100644 index 00000000..ad4cedd3 --- /dev/null +++ b/libs/optional/test/optional_test_inplace_fail2.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com + +#include +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT +#include "boost/utility/in_place_factory.hpp" +#include "boost/utility/typed_in_place_factory.hpp" +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/none.hpp" + +struct Guard +{ + double num; + std::string str; + Guard() : num() {} + Guard(double num_, std::string str_) : num(num_), str(str_) {} + + friend bool operator==(const Guard& lhs, const Guard& rhs) { return lhs.num == rhs.num && lhs.str == rhs.str; } + friend bool operator!=(const Guard& lhs, const Guard& rhs) { return !(lhs == rhs); } + +private: + Guard(const Guard&); + Guard& operator=(const Guard&); +}; + + +int main() +{ +#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT + typedef int BAD_TARGET_TYPE; + boost::optional og1 ( boost::in_place(1.0, "one") ); +#else + NOTHING_TO_TEST_SO_JUST_FAIL +#endif + return 0; +} \ No newline at end of file diff --git a/libs/optional/test/optional_test_io.cpp b/libs/optional/test/optional_test_io.cpp new file mode 100644 index 00000000..8086c11c --- /dev/null +++ b/libs/optional/test/optional_test_io.cpp @@ -0,0 +1,100 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com + +#include "boost/optional/optional.hpp" +#include "boost/optional/optional_io.hpp" +#include "boost/core/lightweight_test.hpp" + +#ifndef BOOST_NO_IOSTREAM + +#include + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + + + +using boost::optional; + +template +void test2( Opt o, Opt buff ) +{ + std::stringstream s ; + + const int markv = 123 ; + int mark = 0 ; + + s << o << " " << markv ; + s >> buff >> mark ; + + BOOST_TEST( buff == o ) ; + BOOST_TEST( mark == markv ) ; +} + + +template +void test( T v, T w ) +{ + test2( boost::make_optional(v), optional ()); + test2( boost::make_optional(v), boost::make_optional(w)); + test2( optional () , optional ()); + test2( optional () , boost::make_optional(w)); +} + + +template +void subtest_tag_none_reversibility_with_optional(optional ov) +{ + std::stringstream s; + s << boost::none; + s >> ov; + BOOST_TEST(!ov); +} + +template +void subtest_tag_none_equivalence_with_optional() +{ + std::stringstream s, r; + optional ov; + s << boost::none; + r << ov; + BOOST_TEST_EQ(s.str(), r.str()); +} + +template +void test_tag_none(T v) +{ + subtest_tag_none_reversibility_with_optional(optional(v)); + subtest_tag_none_reversibility_with_optional(optional()); + subtest_tag_none_equivalence_with_optional(); +} + + +int main() +{ + test(1,2); + test(std::string("hello"), std::string("buffer")); + test_tag_none(10); + test_tag_none(std::string("text")); + + return boost::report_errors(); +} + +#else // BOOST_NO_IOSTREAM + +int main() +{ + return boost::report_errors(); +} + +#endif // BOOST_NO_IOSTREAM diff --git a/libs/optional/test/optional_test_make_optional.cpp b/libs/optional/test/optional_test_make_optional.cpp new file mode 100644 index 00000000..f5ef23b0 --- /dev/null +++ b/libs/optional/test/optional_test_make_optional.cpp @@ -0,0 +1,121 @@ +// Copyright (C) 2017 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/ignore_unused.hpp" +#include "boost/core/lightweight_test.hpp" +#include "boost/core/lightweight_test_trait.hpp" +#include "boost/type_traits/is_same.hpp" + + +using boost::optional; +using boost::make_optional; +using boost::is_same; + +template +void verify_type(Deduced) +{ + BOOST_TEST_TRAIT_TRUE(( is_same )); +} + +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) +struct MoveOnly +{ + int value; + explicit MoveOnly(int i) : value(i) {} + MoveOnly(MoveOnly && r) : value(r.value) { r.value = 0; } + MoveOnly& operator=(MoveOnly && r) { value = r.value; r.value = 0; return *this; } + +private: + MoveOnly(MoveOnly const&); + void operator=(MoveOnly const&); +}; + +MoveOnly makeMoveOnly(int i) +{ + return MoveOnly(i); +} + +void test_make_optional_for_move_only_type() +{ + verify_type< optional >(make_optional(makeMoveOnly(2))); + verify_type< optional >(make_optional(true, makeMoveOnly(2))); + + optional o1 = make_optional(makeMoveOnly(1)); + BOOST_TEST (o1); + BOOST_TEST_EQ (1, o1->value); + + optional o2 = make_optional(true, makeMoveOnly(2)); + BOOST_TEST (o2); + BOOST_TEST_EQ (2, o2->value); + + optional oN = make_optional(false, makeMoveOnly(2)); + BOOST_TEST (!oN); +} + +#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + +void test_make_optional_for_optional() +{ + optional oi; + verify_type< optional< optional > >(make_optional(oi)); + verify_type< optional< optional > >(make_optional(true, oi)); + + optional< optional > ooi = make_optional(oi); + BOOST_TEST (ooi); + BOOST_TEST (!*ooi); + + optional< optional > ooT = make_optional(true, oi); + BOOST_TEST (ooT); + BOOST_TEST (!*ooT); + + optional< optional > ooF = make_optional(false, oi); + BOOST_TEST (!ooF); +} + +void test_nested_make_optional() +{ + verify_type< optional< optional > >(make_optional(make_optional(1))); + verify_type< optional< optional > >(make_optional(true, make_optional(true, 2))); + + optional< optional > oo1 = make_optional(make_optional(1)); + BOOST_TEST (oo1); + BOOST_TEST (*oo1); + BOOST_TEST_EQ (1, **oo1); + + optional< optional > oo2 = make_optional(true, make_optional(true, 2)); + BOOST_TEST (oo2); + BOOST_TEST (*oo2); + BOOST_TEST_EQ (2, **oo2); + + optional< optional > oo3 = make_optional(true, make_optional(false, 3)); + BOOST_TEST (oo3); + BOOST_TEST (!*oo3); + + optional< optional > oo4 = make_optional(false, make_optional(true, 4)); + BOOST_TEST (!oo4); +} + +int main() +{ +#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + test_make_optional_for_move_only_type(); +#endif + test_make_optional_for_optional(); + test_nested_make_optional(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_map.cpp b/libs/optional/test/optional_test_map.cpp new file mode 100644 index 00000000..f0b7f0e2 --- /dev/null +++ b/libs/optional/test/optional_test_map.cpp @@ -0,0 +1,192 @@ +// Copyright (C) 2018 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/ignore_unused.hpp" +#include "boost/core/lightweight_test.hpp" +#include "boost/core/lightweight_test_trait.hpp" +#include "boost/type_traits/is_same.hpp" + + +using boost::optional; +using boost::make_optional; +using boost::is_same; + +template +void verify_type(Deduced) +{ + BOOST_TEST_TRAIT_TRUE(( is_same )); +} + +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) +struct MoveOnly +{ + int value; + explicit MoveOnly(int i) : value(i) {} + MoveOnly(MoveOnly && r) : value(r.value) { r.value = 0; } + MoveOnly& operator=(MoveOnly && r) { value = r.value; r.value = 0; return *this; } + +private: + MoveOnly(MoveOnly const&); + void operator=(MoveOnly const&); +}; + +MoveOnly makeMoveOnly(int i) +{ + return MoveOnly(i); +} + +optional makeOptMoveOnly(int i) +{ + return optional(MoveOnly(i)); +} + +int get_val(MoveOnly m) +{ + return m.value; +} + +void test_map_move_only() +{ + optional om (makeMoveOnly(7)), om2 (makeMoveOnly(8)); + verify_type >(boost::move(om).map(get_val)); + optional oi = boost::move(om2).map(get_val); + BOOST_TEST(bool(oi)); + BOOST_TEST_EQ(8, *oi); + + optional oj = makeOptMoveOnly(4).map(get_val); + BOOST_TEST(bool(oj)); + BOOST_TEST_EQ(4, *oj); + + optional o_; + optional oi_ = boost::move(o_).map(get_val); + BOOST_TEST(!oi_); +} + +#endif // no rvalue refs + +struct Int +{ + int i; + explicit Int(int i_) : i(i_) {} +}; + +struct convert_t +{ + typedef Int result_type; + Int operator()(int i) { return Int(i); } +}; + +int& get_int_ref(Int& i) +{ + return i.i; +} + +struct get_ref +{ + typedef int& result_type; + int& operator()(int& i) { return i; } +}; + +void test_map() +{ + optional oi (1); + verify_type >(oi.map(convert_t())); + optional oI = oi.map(convert_t()); + BOOST_TEST(bool(oI)); + BOOST_TEST_EQ(1, oI->i); + + optional o_ = optional().map(convert_t()); + BOOST_TEST(!o_); +} + +optional make_opt_int(int i) +{ + if (i != 0) + return Int(i); + else + return boost::none; +} + +void test_map_optional() +{ + optional o9 (9), o0 (0), o_; + verify_type > >(o9.map(make_opt_int)); + optional > oo9 = o9.map(make_opt_int); + BOOST_TEST(bool(oo9)); + BOOST_TEST(bool(*oo9)); + BOOST_TEST_EQ(9, (**oo9).i); + + optional > oo0 = o0.map(make_opt_int); + BOOST_TEST(bool(oo0)); + BOOST_TEST(!*oo0); + + optional > oo_ = o_.map(make_opt_int); + BOOST_TEST(!oo_); +} + +void test_map_with_lambda() +{ +#if !defined BOOST_NO_CXX11_LAMBDAS && !defined BOOST_NO_CXX11_DECLTYPE_N3276 + optional oi (1), oj(2); + verify_type >(oi.map([](int i){ return i == 1; })); + optional ob = oi.map([](int i){ return i == 1; }); + optional oc = oj.map([](int i){ return i == 1; }); + BOOST_TEST(bool(ob)); + BOOST_TEST_EQ(true, *ob); + BOOST_TEST(bool(oc)); + BOOST_TEST_EQ(false, *oc); +#endif // lambdas +} + +void test_map_to_ref() +{ + optional oi (2); + verify_type >(oi.map(get_ref())); + optional ori = oi.map(get_ref()); + BOOST_TEST(bool(ori)); + *ori = 3; + BOOST_TEST(bool(oi)); + BOOST_TEST_EQ(3, *oi); + BOOST_TEST_EQ(3, *ori); +} + +void test_map_optional_ref() +{ + Int I (5); + optional ori (I); + verify_type >(ori.map(get_int_ref)); + optional orii = ori.map(get_int_ref); + BOOST_TEST(bool(orii)); + BOOST_TEST_EQ(5, *orii); + *orii = 6; + BOOST_TEST_EQ(6, I.i); +} + +int main() +{ +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) + test_map_move_only(); +#endif + test_map_with_lambda(); + test_map(); + test_map_optional(); + test_map_to_ref(); + test_map_optional(); + test_map_optional_ref(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_maybe_uninitialized_warning.cpp b/libs/optional/test/optional_test_maybe_uninitialized_warning.cpp new file mode 100644 index 00000000..7660ece6 --- /dev/null +++ b/libs/optional/test/optional_test_maybe_uninitialized_warning.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2017 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +boost::optional getitem(); + +int main(int argc, const char *[]) +{ + boost::optional a = getitem(); + boost::optional b; + + if (argc > 0) + b = argc; + + if (a == b) + return 1; + + return 0; +} \ No newline at end of file diff --git a/libs/optional/test/optional_test_member_T.cpp b/libs/optional/test/optional_test_member_T.cpp new file mode 100644 index 00000000..c31fedb5 --- /dev/null +++ b/libs/optional/test/optional_test_member_T.cpp @@ -0,0 +1,44 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" + +struct Status +{ + enum T + { + DISCONNECTED, + CONNECTING, + CONNECTED, + }; + + T mValue; +}; + +void test_member_T() +{ + boost::optional x = Status(); + x->mValue = Status::CONNECTED; + + BOOST_TEST(x->mValue == Status::CONNECTED); +} + +int main() +{ + test_member_T(); + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_minimum_requirements.cpp b/libs/optional/test/optional_test_minimum_requirements.cpp new file mode 100644 index 00000000..11ff247e --- /dev/null +++ b/libs/optional/test/optional_test_minimum_requirements.cpp @@ -0,0 +1,76 @@ +// Copyright (C) 2014-2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include +#include "boost/core/lightweight_test.hpp" +#include "boost/none.hpp" + +class NonConstructible +{ +private: + NonConstructible(); + NonConstructible(NonConstructible const&); +#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) + NonConstructible(NonConstructible &&); +#endif +}; + +void test_non_constructible() +{ + boost::optional o; + BOOST_TEST(!o); + BOOST_TEST(o == boost::none); + BOOST_TEST_THROWS(o.value(), boost::bad_optional_access); +} + +class Guard +{ +public: + explicit Guard(int) {} +private: + Guard(); + Guard(Guard const&); +#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) + Guard(Guard &&); +#endif +}; + +void test_guard() +{ + boost::optional o; + o.emplace(1); + BOOST_TEST(o); + BOOST_TEST(o != boost::none); +} + +void test_non_assignable() +{ + boost::optional o; + o.emplace("cat"); + BOOST_TEST(o); + BOOST_TEST(o != boost::none); + BOOST_TEST_EQ(*o, std::string("cat")); +} + +int main() +{ + test_non_constructible(); + test_guard(); + test_non_assignable(); + + return boost::report_errors(); +} \ No newline at end of file diff --git a/libs/optional/test/optional_test_move.cpp b/libs/optional/test/optional_test_move.cpp new file mode 100644 index 00000000..f27cd998 --- /dev/null +++ b/libs/optional/test/optional_test_move.cpp @@ -0,0 +1,352 @@ +// Copyright (C) 2014 - 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" + +using boost::optional; +using boost::none; + +//#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT +//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + +enum State +{ + sDefaultConstructed, + sValueCopyConstructed, + sValueMoveConstructed, + sCopyConstructed, + sMoveConstructed, + sMoveAssigned, + sCopyAssigned, + sValueCopyAssigned, + sValueMoveAssigned, + sMovedFrom, + sIntConstructed +}; + +struct OracleVal +{ + State s; + int i; + OracleVal(int i = 0) : s(sIntConstructed), i(i) {} +}; + + +struct Oracle +{ + State s; + OracleVal val; + + Oracle() : s(sDefaultConstructed) {} + Oracle(const OracleVal& v) : s(sValueCopyConstructed), val(v) {} + Oracle(OracleVal&& v) : s(sValueMoveConstructed), val(std::move(v)) {v.s = sMovedFrom;} + Oracle(const Oracle& o) : s(sCopyConstructed), val(o.val) {} + Oracle(Oracle&& o) : s(sMoveConstructed), val(std::move(o.val)) {o.s = sMovedFrom;} + + Oracle& operator=(const OracleVal& v) { s = sValueCopyAssigned; val = v; return *this; } + Oracle& operator=(OracleVal&& v) { s = sValueMoveAssigned; val = std::move(v); v.s = sMovedFrom; return *this; } + Oracle& operator=(const Oracle& o) { s = sCopyAssigned; val = o.val; return *this; } + Oracle& operator=(Oracle&& o) { s = sMoveAssigned; val = std::move(o.val); o.s = sMovedFrom; return *this; } +}; + +bool operator==( Oracle const& a, Oracle const& b ) { return a.val.i == b.val.i; } +bool operator!=( Oracle const& a, Oracle const& b ) { return a.val.i != b.val.i; } + + +void test_move_ctor_from_U() +{ + optional o1 ((OracleVal())); + BOOST_TEST(o1); + BOOST_TEST(o1->s == sValueMoveConstructed || o1->s == sMoveConstructed); + + OracleVal v1; + optional o2 (v1); + BOOST_TEST(o2); + BOOST_TEST(o2->s == sValueCopyConstructed || o2->s == sCopyConstructed || o2->s == sMoveConstructed ); + BOOST_TEST(v1.s == sIntConstructed); + + optional o3 (boost::move(v1)); + BOOST_TEST(o3); + BOOST_TEST(o3->s == sValueMoveConstructed || o3->s == sMoveConstructed); + BOOST_TEST(v1.s == sMovedFrom); +} + +void test_move_ctor_form_T() +{ + optional o1 ((Oracle())); + BOOST_TEST(o1); + BOOST_TEST(o1->s == sMoveConstructed); + + Oracle v1; + optional o2 (v1); + BOOST_TEST(o2); + BOOST_TEST(o2->s == sCopyConstructed); + BOOST_TEST(v1.s == sDefaultConstructed); + + optional o3 (boost::move(v1)); + BOOST_TEST(o3); + BOOST_TEST(o3->s == sMoveConstructed); + BOOST_TEST(v1.s == sMovedFrom); +} + +void test_move_ctor_from_optional_T() +{ + optional o1; + optional o2(boost::move(o1)); + + BOOST_TEST(!o1); + BOOST_TEST(!o2); + + optional o3((Oracle())); + optional o4(boost::move(o3)); + BOOST_TEST(o3); + BOOST_TEST(o4); + BOOST_TEST(o3->s == sMovedFrom); + BOOST_TEST(o4->s == sMoveConstructed); + + optional o5((optional())); + BOOST_TEST(!o5); + + optional o6((optional(Oracle()))); + BOOST_TEST(o6); + BOOST_TEST(o6->s == sMoveConstructed); + + optional o7(o6); // does copy ctor from non-const lvalue compile? +} + +void test_move_assign_from_U() +{ + optional o1 = boost::none; // test if additional ctors didn't break it + o1 = boost::none; // test if additional assignments didn't break it + o1 = OracleVal(); + BOOST_TEST(o1); + + BOOST_TEST(o1->s == sValueMoveConstructed); + + o1 = OracleVal(); + BOOST_TEST(o1); + BOOST_TEST(o1->s == sMoveAssigned); + + OracleVal v1; + optional o2; + o2 = v1; + BOOST_TEST(o2); + BOOST_TEST(o2->s == sValueCopyConstructed); + BOOST_TEST(v1.s == sIntConstructed); + o2 = v1; + BOOST_TEST(o2); + BOOST_TEST(o2->s == sCopyAssigned || o2->s == sMoveAssigned); + BOOST_TEST(v1.s == sIntConstructed); + + optional o3; + o3 = boost::move(v1); + BOOST_TEST(o3); + BOOST_TEST(o3->s == sValueMoveConstructed); + BOOST_TEST(v1.s == sMovedFrom); +} + +void test_move_assign_from_T() +{ + optional o1; + o1 = Oracle(); + BOOST_TEST(o1); + BOOST_TEST(o1->s == sMoveConstructed); + + o1 = Oracle(); + BOOST_TEST(o1); + BOOST_TEST(o1->s == sMoveAssigned); + + Oracle v1; + optional o2; + o2 = v1; + BOOST_TEST(o2); + BOOST_TEST(o2->s == sCopyConstructed); + BOOST_TEST(v1.s == sDefaultConstructed); + o2 = v1; + BOOST_TEST(o2); + BOOST_TEST(o2->s == sCopyAssigned); + BOOST_TEST(v1.s == sDefaultConstructed); + + optional o3; + o3 = boost::move(v1); + BOOST_TEST(o3); + BOOST_TEST(o3->s == sMoveConstructed); + BOOST_TEST(v1.s == sMovedFrom); +} + +void test_move_assign_from_optional_T() +{ + optional o1; + optional o2; + o1 = optional(); + BOOST_TEST(!o1); + optional o3((Oracle())); + o1 = o3; + BOOST_TEST(o3); + BOOST_TEST(o3->s == sMoveConstructed); + BOOST_TEST(o1); + BOOST_TEST(o1->s == sCopyConstructed); + + o2 = boost::move(o3); + BOOST_TEST(o3); + BOOST_TEST(o3->s == sMovedFrom); + BOOST_TEST(o2); + BOOST_TEST(o2->s == sMoveConstructed); + + o2 = optional((Oracle())); + BOOST_TEST(o2); + BOOST_TEST(o2->s == sMoveAssigned); +} + +class MoveOnly +{ +public: + int val; + MoveOnly(int v) : val(v) {} + MoveOnly(MoveOnly&& rhs) : val(rhs.val) { rhs.val = 0; } + void operator=(MoveOnly&& rhs) {val = rhs.val; rhs.val = 0; } + +private: + MoveOnly(MoveOnly const&); + void operator=(MoveOnly const&); + + friend class MoveOnlyB; +}; + +void test_with_move_only() +{ + optional o1; + optional o2((MoveOnly(1))); + BOOST_TEST(o2); + BOOST_TEST(o2->val == 1); + optional o3 (boost::move(o1)); + BOOST_TEST(!o3); + optional o4 (boost::move(o2)); + BOOST_TEST(o4); + BOOST_TEST(o4->val == 1); + BOOST_TEST(o2); + BOOST_TEST(o2->val == 0); + + o3 = boost::move(o4); + BOOST_TEST(o3); + BOOST_TEST(o3->val == 1); + BOOST_TEST(o4); + BOOST_TEST(o4->val == 0); +} + +class MoveOnlyB +{ +public: + int val; + MoveOnlyB(int v) : val(v) {} + MoveOnlyB(MoveOnlyB&& rhs) : val(rhs.val) { rhs.val = 0; } + void operator=(MoveOnlyB&& rhs) {val = rhs.val; rhs.val = 0; } + MoveOnlyB(MoveOnly&& rhs) : val(rhs.val) { rhs.val = 0; } + void operator=(MoveOnly&& rhs) {val = rhs.val; rhs.val = 0; } + +private: + MoveOnlyB(MoveOnlyB const&); + void operator=(MoveOnlyB const&); + MoveOnlyB(MoveOnly const&); + void operator=(MoveOnly const&); +}; + +void test_move_assign_from_optional_U() +{ + optional a((MoveOnly(2))); + optional b1; + b1 = boost::move(a); + + BOOST_TEST(b1); + BOOST_TEST(b1->val == 2); + BOOST_TEST(a); + BOOST_TEST(a->val == 0); + + b1 = MoveOnly(4); + + BOOST_TEST(b1); + BOOST_TEST(b1->val == 4); +} + +void test_move_ctor_from_optional_U() +{ + optional a((MoveOnly(2))); + optional b1(boost::move(a)); + + BOOST_TEST(b1); + BOOST_TEST(b1->val == 2); + BOOST_TEST(a); + BOOST_TEST(a->val == 0); + + optional b2(( optional(( MoveOnly(4) )) )); + + BOOST_TEST(b2); + BOOST_TEST(b2->val == 4); +} + +void test_swap() +{ + optional a((MoveOnly(2))); + optional b((MoveOnly(3))); + swap(a, b); + + BOOST_TEST(a->val == 3); + BOOST_TEST(b->val == 2); +} + +void test_optional_ref_to_movables() +{ + MoveOnly m(3); + optional orm = m; + orm->val = 2; + BOOST_TEST(m.val == 2); + + optional orm2 = orm; + orm2->val = 1; + BOOST_TEST(m.val == 1); + BOOST_TEST(orm->val == 1); + + optional orm3 = boost::move(orm); + orm3->val = 4; + BOOST_TEST(m.val == 4); + BOOST_TEST(orm->val == 4); + BOOST_TEST(orm2->val == 4); +} + +#endif + +int main() +{ +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + test_move_ctor_from_U(); + test_move_ctor_form_T(); + test_move_ctor_from_optional_T(); + test_move_ctor_from_optional_U(); + test_move_assign_from_U(); + test_move_assign_from_T(); + test_move_assign_from_optional_T(); + test_move_assign_from_optional_U(); + test_with_move_only(); + test_optional_ref_to_movables(); + test_swap(); +#endif + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_msvc_bug_workaround.cpp b/libs/optional/test/optional_test_msvc_bug_workaround.cpp new file mode 100644 index 00000000..126e8850 --- /dev/null +++ b/libs/optional/test/optional_test_msvc_bug_workaround.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#define BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" + + +struct Wrapper +{ + operator int () { return 9; } + operator boost::optional () { return 7; } +}; + +void test() +{ +#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) + boost::optional v = Wrapper(); + BOOST_TEST(v); + BOOST_TEST_EQ(*v, 7); +#endif +} + +int main() +{ + test(); + return boost::report_errors(); +} \ No newline at end of file diff --git a/libs/optional/test/optional_test_noexcept_move.cpp b/libs/optional/test/optional_test_noexcept_move.cpp new file mode 100644 index 00000000..258bacd2 --- /dev/null +++ b/libs/optional/test/optional_test_noexcept_move.cpp @@ -0,0 +1,116 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/static_assert.hpp" +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + + +using boost::optional; + + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_NOEXCEPT + +// these 4 classes have different noexcept signatures in move operations +struct NothrowBoth { + NothrowBoth(NothrowBoth&&) BOOST_NOEXCEPT_IF(true) {}; + void operator=(NothrowBoth&&) BOOST_NOEXCEPT_IF(true) {}; +}; +struct NothrowCtor { + NothrowCtor(NothrowCtor&&) BOOST_NOEXCEPT_IF(true) {}; + void operator=(NothrowCtor&&) BOOST_NOEXCEPT_IF(false) {}; +}; +struct NothrowAssign { + NothrowAssign(NothrowAssign&&) BOOST_NOEXCEPT_IF(false) {}; + void operator=(NothrowAssign&&) BOOST_NOEXCEPT_IF(true) {}; +}; +struct NothrowNone { + NothrowNone(NothrowNone&&) BOOST_NOEXCEPT_IF(false) {}; + void operator=(NothrowNone&&) BOOST_NOEXCEPT_IF(false) {}; +}; + +#if 0 // these also test type_traits, which are wrong +void test_noexcept_as_defined() // this is a compile-time test +{ + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_constructible::value); + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_assignable::value); + + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_constructible::value); + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable::value); + + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_constructible::value); + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_assignable::value); + + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_constructible::value); + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable::value); +} + +void test_noexcept_on_optional_with_type_traits() // this is a compile-time test +{ + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_constructible >::value); + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_assignable >::value); + BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional())); + + BOOST_STATIC_ASSERT(::boost::is_nothrow_move_constructible >::value); + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable >::value); + BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional())); + + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_constructible >::value); + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable >::value); + BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional())); + + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_constructible >::value); + BOOST_STATIC_ASSERT(!::boost::is_nothrow_move_assignable >::value); + BOOST_STATIC_ASSERT(BOOST_NOEXCEPT_EXPR(optional())); +} +#endif + +void test_noexcept_optional_with_operator() // compile-time test +{ + typedef optional ONx2; + typedef optional ONxC; + typedef optional ONxA; + typedef optional ONx0; + ONx2 onx2; + ONxC onxC; + ONxA onxA; + ONx0 onx0; + + BOOST_STATIC_ASSERT( BOOST_NOEXCEPT_EXPR( ONx2() )); + BOOST_STATIC_ASSERT( BOOST_NOEXCEPT_EXPR( ONx2(boost::move(onx2)) )); + BOOST_STATIC_ASSERT( BOOST_NOEXCEPT_EXPR( onx2 = ONx2() )); + + BOOST_STATIC_ASSERT( BOOST_NOEXCEPT_EXPR( ONxC() )); + BOOST_STATIC_ASSERT( BOOST_NOEXCEPT_EXPR( ONxC(boost::move(onxC)) )); + BOOST_STATIC_ASSERT(!BOOST_NOEXCEPT_EXPR( onxC = ONxC() )); + + BOOST_STATIC_ASSERT( BOOST_NOEXCEPT_EXPR( ONxA() )); + BOOST_STATIC_ASSERT(!BOOST_NOEXCEPT_EXPR( ONxA(boost::move(onxA)) )); + BOOST_STATIC_ASSERT(!BOOST_NOEXCEPT_EXPR( onxA = ONxA() )); + + BOOST_STATIC_ASSERT( BOOST_NOEXCEPT_EXPR( ONx0() )); + BOOST_STATIC_ASSERT(!BOOST_NOEXCEPT_EXPR( ONx0(boost::move(onx0)) )); + BOOST_STATIC_ASSERT(!BOOST_NOEXCEPT_EXPR( onx0 = ONx0() )); +} + +#endif // !defined BOOST_NO_CXX11_NOEXCEPT +#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + +int main() +{ + return 0; +} + + diff --git a/libs/optional/test/optional_test_old_impl.cpp b/libs/optional/test/optional_test_old_impl.cpp new file mode 100644 index 00000000..f3da56e1 --- /dev/null +++ b/libs/optional/test/optional_test_old_impl.cpp @@ -0,0 +1,223 @@ +// Copyright (C) 2014 - 2018 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#define BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL // does old implementation still work for basic usage? +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/ignore_unused.hpp" +#include "boost/core/lightweight_test.hpp" + +using boost::optional; + +struct IntWrapper +{ + int _i; + IntWrapper(int i) : _i(i) {} + bool operator==(IntWrapper const& rhs) const { return _i == rhs._i; } +}; + +template +void test_function_value_or_for() +{ + optional oM0; + const optional oC0; + optional oM1(1); + const optional oC2(2); + + BOOST_TEST(oM0.value_or(5) == 5); + BOOST_TEST(oC0.value_or(5) == 5); + BOOST_TEST(oM1.value_or(5) == 1); + BOOST_TEST(oC2.value_or(5) == 2); +} + +template +void test_function_value_for() +{ + optional o0; + optional o1(1); + const optional oC(2); + + try + { + T& v = o1.value(); + BOOST_TEST(v == 1); + } + catch(...) + { + BOOST_TEST(false); + } + + try + { + T const& v = oC.value(); + BOOST_TEST(v == 2); + } + catch(...) + { + BOOST_TEST(false); + } + + BOOST_TEST_THROWS(o0.value(), boost::bad_optional_access); +} + +void test_function_value() +{ + test_function_value_for(); + test_function_value_for(); + test_function_value_for(); +} + +struct FatToIntConverter +{ + static int conversions; + int _val; + FatToIntConverter(int val) : _val(val) {} + operator int() const { conversions += 1; return _val; } +}; + +int FatToIntConverter::conversions = 0; + +void test_function_value_or() +{ + test_function_value_or_for(); + test_function_value_or_for(); + test_function_value_or_for(); + + optional oi(1); + BOOST_TEST(oi.value_or(FatToIntConverter(2)) == 1); + BOOST_TEST(FatToIntConverter::conversions == 0); + + oi = boost::none; + BOOST_TEST(oi.value_or(FatToIntConverter(2)) == 2); + BOOST_TEST(FatToIntConverter::conversions == 1); +} + + +struct FunM +{ + int operator()() { return 5; } +}; + +struct FunC +{ + int operator()() const { return 6; } +}; + +int funP () +{ + return 7; +} + +int throw_() +{ + throw int(); +} + +void test_function_value_or_eval() +{ + optional o1 = 1; + optional oN; + FunM funM; + FunC funC; + + BOOST_TEST_EQ(o1.value_or_eval(funM), 1); + BOOST_TEST_EQ(oN.value_or_eval(funM), 5); + BOOST_TEST_EQ(o1.value_or_eval(FunM()), 1); + BOOST_TEST_EQ(oN.value_or_eval(FunM()), 5); + + BOOST_TEST_EQ(o1.value_or_eval(funC), 1); + BOOST_TEST_EQ(oN.value_or_eval(funC), 6); + BOOST_TEST_EQ(o1.value_or_eval(FunC()), 1); + BOOST_TEST_EQ(oN.value_or_eval(FunC()), 6); + + BOOST_TEST_EQ(o1.value_or_eval(funP), 1); + BOOST_TEST_EQ(oN.value_or_eval(funP), 7); + +#ifndef BOOST_NO_CXX11_LAMBDAS + BOOST_TEST_EQ(o1.value_or_eval([](){return 8;}), 1); + BOOST_TEST_EQ(oN.value_or_eval([](){return 8;}), 8); +#endif + + try + { + BOOST_TEST_EQ(o1.value_or_eval(throw_), 1); + } + catch(...) + { + BOOST_TEST(false); + } + + BOOST_TEST_THROWS(oN.value_or_eval(throw_), int); +} + +const optional makeConstOptVal() +{ + return std::string("something"); +} + +void test_const_move() +{ + std::string s5 = *makeConstOptVal(); + std::string s6 = makeConstOptVal().value(); + boost::ignore_unused(s5); + boost::ignore_unused(s6); +} + + +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) +struct MoveOnly +{ + explicit MoveOnly(int){} + MoveOnly(MoveOnly &&){} + void operator=(MoveOnly &&); +private: + MoveOnly(MoveOnly const&); + void operator=(MoveOnly const&); +}; + +optional makeMoveOnly() +{ + return MoveOnly(1); +} + +MoveOnly moveOnlyDefault() +{ + return MoveOnly(1); +} + +// compile-time test +void test_move_only_getters() +{ + MoveOnly m1 = *makeMoveOnly(); + MoveOnly m2 = makeMoveOnly().value(); + MoveOnly m3 = makeMoveOnly().value_or(MoveOnly(1)); + MoveOnly m4 = makeMoveOnly().value_or_eval(moveOnlyDefault); + boost::ignore_unused(m1); + boost::ignore_unused(m2); + boost::ignore_unused(m3); + boost::ignore_unused(m4); +} + +#endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS + +int main() +{ + test_function_value(); + test_function_value_or(); + test_function_value_or_eval(); + test_const_move(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_path_assignment.cpp b/libs/optional/test/optional_test_path_assignment.cpp new file mode 100644 index 00000000..485e741d --- /dev/null +++ b/libs/optional/test/optional_test_path_assignment.cpp @@ -0,0 +1,73 @@ +// Copyright (C) 2019 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#ifndef BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT +#ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS +template +struct void_t +{ + typedef void type; +}; + + +template +struct trait +{ +}; + +// the following trait emulates properties std::iterator_traits +template +struct trait >::type + >::type> +{ + typedef BOOST_DEDUCED_TYPENAME T::value_type value_type; +}; + +// This class emulates the properties of std::filesystem::path +struct Path +{ + +#if __cplusplus >= 201103 + template ::value_type> + Path(T const&); +#else + template + Path(T const&, BOOST_DEDUCED_TYPENAME trait::value_type* = 0); +#endif + +}; +#endif +#endif + + +int main() +{ +#ifndef BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT +#ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS + + boost::optional optFs1; + boost::optional optFs2; + + optFs1 = optFs2; + + // the following still fails although it shouldn't + //BOOST_STATIC_ASSERT((std::is_copy_constructible>::value)); + +#endif +#endif +} diff --git a/libs/optional/test/optional_test_ref_assign_const_int.cpp b/libs/optional/test/optional_test_ref_assign_const_int.cpp new file mode 100644 index 00000000..6dddf9ec --- /dev/null +++ b/libs/optional/test/optional_test_ref_assign_const_int.cpp @@ -0,0 +1,34 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: akrzemi1@gmail.com + + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" +#include "testable_classes.hpp" +#include "optional_ref_assign_test_defs.hpp" + +using boost::optional; +using boost::none; + + +int main() +{ + test_copy_assignment_for_const(); + test_copy_assignment_for_noconst_const(); + test_rebinding_assignment_semantics_const(); + test_rebinding_assignment_semantics_noconst_const(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_ref_assign_mutable_int.cpp b/libs/optional/test/optional_test_ref_assign_mutable_int.cpp new file mode 100644 index 00000000..5aa717e7 --- /dev/null +++ b/libs/optional/test/optional_test_ref_assign_mutable_int.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: akrzemi1@gmail.com + + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" +#include "testable_classes.hpp" +#include "optional_ref_assign_test_defs.hpp" + +using boost::optional; +using boost::none; + +int main() +{ + test_copy_assignment_for(); + test_rebinding_assignment_semantics(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_ref_assign_portable_minimum.cpp b/libs/optional/test/optional_test_ref_assign_portable_minimum.cpp new file mode 100644 index 00000000..31599f30 --- /dev/null +++ b/libs/optional/test/optional_test_ref_assign_portable_minimum.cpp @@ -0,0 +1,45 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: akrzemi1@gmail.com + + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" +#include "testable_classes.hpp" +#include "optional_ref_assign_test_defs.hpp" + +using boost::optional; +using boost::none; + + +template +void test_optional_ref_assignment() +{ + test_copy_assignment_for(); + test_rebinding_assignment_semantics(); + + test_copy_assignment_for_const(); + test_copy_assignment_for_noconst_const(); + test_rebinding_assignment_semantics_const(); + test_rebinding_assignment_semantics_noconst_const(); +} + +int main() +{ + test_optional_ref_assignment(); + test_optional_ref_assignment(); + test_optional_ref_assignment< optional >(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_ref_convert_assign_const_int.cpp b/libs/optional/test/optional_test_ref_convert_assign_const_int.cpp new file mode 100644 index 00000000..0d6585ff --- /dev/null +++ b/libs/optional/test/optional_test_ref_convert_assign_const_int.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: akrzemi1@gmail.com + + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/addressof.hpp" +#include "boost/core/enable_if.hpp" +#include "boost/core/lightweight_test.hpp" +#include "testable_classes.hpp" +#include "optional_ref_assign_test_defs.hpp" + +int main() +{ +#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT + test_converting_assignment(); +#endif + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_ref_convert_assign_const_int_prevented.cpp b/libs/optional/test/optional_test_ref_convert_assign_const_int_prevented.cpp new file mode 100644 index 00000000..e692475f --- /dev/null +++ b/libs/optional/test/optional_test_ref_convert_assign_const_int_prevented.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: akrzemi1@gmail.com + + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/addressof.hpp" +#include "boost/core/enable_if.hpp" +#include "boost/core/lightweight_test.hpp" +#include "testable_classes.hpp" +#include "optional_ref_assign_test_defs.hpp" + +int main() +{ +#ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT + test_converting_assignment(); +#else + BOOST_STATIC_ASSERT_MSG(false, "EXPECTED TEST COMPILE-TIME FAILURE"); +#endif + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_ref_convert_assign_mutable_int.cpp b/libs/optional/test/optional_test_ref_convert_assign_mutable_int.cpp new file mode 100644 index 00000000..6003c433 --- /dev/null +++ b/libs/optional/test/optional_test_ref_convert_assign_mutable_int.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: akrzemi1@gmail.com + + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/addressof.hpp" +#include "boost/core/enable_if.hpp" +#include "boost/core/lightweight_test.hpp" +#include "testable_classes.hpp" +#include "optional_ref_assign_test_defs.hpp" + +int main() +{ + test_converting_assignment(); + test_converting_assignment(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_ref_convert_assign_non_int.cpp b/libs/optional/test/optional_test_ref_convert_assign_non_int.cpp new file mode 100644 index 00000000..93d3c3f2 --- /dev/null +++ b/libs/optional/test/optional_test_ref_convert_assign_non_int.cpp @@ -0,0 +1,39 @@ +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: akrzemi1@gmail.com + + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/addressof.hpp" +#include "boost/core/enable_if.hpp" +#include "boost/core/lightweight_test.hpp" +#include "testable_classes.hpp" +#include "optional_ref_assign_test_defs.hpp" + + +template +void test_all_const_cases() +{ + test_converting_assignment(); + test_converting_assignment(); + test_converting_assignment(); +} + +int main() +{ + test_all_const_cases(); + test_all_const_cases(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_ref_converting_ctor.cpp b/libs/optional/test/optional_test_ref_converting_ctor.cpp new file mode 100644 index 00000000..b8335cd0 --- /dev/null +++ b/libs/optional/test/optional_test_ref_converting_ctor.cpp @@ -0,0 +1,110 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: akrzemi1@gmail.com + + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/addressof.hpp" +#include "boost/core/enable_if.hpp" +#include "boost/core/lightweight_test.hpp" +#include "testable_classes.hpp" + +using boost::optional; +using boost::none; + +template +void test_converting_ctor() +{ + typename concrete_type_of::type v1(1), v2(2); + + { + optional o1 = v1, o1_ = v1, o2 = v2; + + BOOST_TEST(o1); + BOOST_TEST(boost::addressof(*o1) == boost::addressof(v1)); + BOOST_TEST(o1_); + BOOST_TEST(boost::addressof(*o1_) == boost::addressof(v1)); + BOOST_TEST(boost::addressof(*o1_) == boost::addressof(*o1)); + + BOOST_TEST(o2); + BOOST_TEST(boost::addressof(*o2) == boost::addressof(v2)); + BOOST_TEST(boost::addressof(*o2) != boost::addressof(*o1)); + } + { + const optional o1 = v1, o1_ = v1, o2 = v2; + + BOOST_TEST(o1); + BOOST_TEST(boost::addressof(*o1) == boost::addressof(v1)); + BOOST_TEST(o1_); + BOOST_TEST(boost::addressof(*o1_) == boost::addressof(v1)); + BOOST_TEST(boost::addressof(*o1_) == boost::addressof(*o1)); + + BOOST_TEST(o2); + BOOST_TEST(boost::addressof(*o2) == boost::addressof(v2)); + BOOST_TEST(boost::addressof(*o2) != boost::addressof(*o1)); + } +} + +template +void test_converting_ctor_for_noconst_const() +{ + typename concrete_type_of::type v1(1), v2(2); + + { + optional o1 = v1, o1_ = v1, o2 = v2; + + BOOST_TEST(o1); + BOOST_TEST(boost::addressof(*o1) == boost::addressof(v1)); + BOOST_TEST(o1_); + BOOST_TEST(boost::addressof(*o1_) == boost::addressof(v1)); + BOOST_TEST(boost::addressof(*o1_) == boost::addressof(*o1)); + + BOOST_TEST(o2); + BOOST_TEST(boost::addressof(*o2) == boost::addressof(v2)); + BOOST_TEST(boost::addressof(*o2) != boost::addressof(*o1)); + } + { + const optional o1 = v1, o1_ = v1, o2 = v2; + + BOOST_TEST(o1); + BOOST_TEST(boost::addressof(*o1) == boost::addressof(v1)); + BOOST_TEST(o1_); + BOOST_TEST(boost::addressof(*o1_) == boost::addressof(v1)); + BOOST_TEST(boost::addressof(*o1_) == boost::addressof(*o1)); + + BOOST_TEST(o2); + BOOST_TEST(boost::addressof(*o2) == boost::addressof(v2)); + BOOST_TEST(boost::addressof(*o2) != boost::addressof(*o1)); + } +} + +template +void test_all_const_cases() +{ + test_converting_ctor(); +#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT + test_converting_ctor(); +#endif + test_converting_ctor_for_noconst_const(); +} + +int main() +{ + test_all_const_cases(); + test_all_const_cases(); + test_all_const_cases(); + test_all_const_cases< optional >(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_ref_fail1.cpp b/libs/optional/test/optional_test_ref_fail1.cpp new file mode 100644 index 00000000..b2f9061d --- /dev/null +++ b/libs/optional/test/optional_test_ref_fail1.cpp @@ -0,0 +1,25 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#include "boost/optional.hpp" + +// +// THIS TEST SHOULD FAIL TO COMPILE +// +void optional_reference__test_no_converting_assignment() +{ + boost::optional opt ; + double v = 1 ; + double& r = v ; + opt = r ; +} + + diff --git a/libs/optional/test/optional_test_ref_fail3.cpp b/libs/optional/test/optional_test_ref_fail3.cpp new file mode 100644 index 00000000..e630d077 --- /dev/null +++ b/libs/optional/test/optional_test_ref_fail3.cpp @@ -0,0 +1,23 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#include "boost/optional.hpp" + +// +// THIS TEST SHOULD FAIL TO COMPILE +// +void optional_reference__test_no_converting_ctor() +{ + boost::optional opt1 ; + boost::optional opt2 = opt1 ; +} + + diff --git a/libs/optional/test/optional_test_ref_fail4.cpp b/libs/optional/test/optional_test_ref_fail4.cpp new file mode 100644 index 00000000..0425243f --- /dev/null +++ b/libs/optional/test/optional_test_ref_fail4.cpp @@ -0,0 +1,24 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#include "boost/optional.hpp" + +// +// THIS TEST SHOULD FAIL TO COMPILE +// +void optional_reference__test_no_converting_initialization() +{ + short v = 1 ; + short& r = v; + boost::optional opt(r) ; +} + + diff --git a/libs/optional/test/optional_test_ref_fail_assign_from_Trefref.cpp b/libs/optional/test/optional_test_ref_fail_assign_from_Trefref.cpp new file mode 100644 index 00000000..4eb748a5 --- /dev/null +++ b/libs/optional/test/optional_test_ref_fail_assign_from_Trefref.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2014, andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com +// +#include "boost/optional.hpp" + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +// +// THIS TEST SHOULD FAIL TO COMPILE +// +void optional_reference__test_no_assign_from_Trefref() +{ + boost::optional opt; + opt = int(3); +} + +#else +# error "Test skipped. This cannot be implemented w/o rvalue references." +#endif diff --git a/libs/optional/test/optional_test_ref_fail_assign_from_Urefref.cpp b/libs/optional/test/optional_test_ref_fail_assign_from_Urefref.cpp new file mode 100644 index 00000000..b06185f6 --- /dev/null +++ b/libs/optional/test/optional_test_ref_fail_assign_from_Urefref.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2014, andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com +// +#include "boost/optional.hpp" + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +// +// THIS TEST SHOULD FAIL TO COMPILE +// +void optional_reference__test_no_assign_from_Urefref() +{ + boost::optional opt; + opt = long(3); +} + +#else +# error "Test skipped. This cannot be implemented w/o rvalue references." +#endif diff --git a/libs/optional/test/optional_test_ref_fail_init_from_Trefref.cpp b/libs/optional/test/optional_test_ref_fail_init_from_Trefref.cpp new file mode 100644 index 00000000..a08c08af --- /dev/null +++ b/libs/optional/test/optional_test_ref_fail_init_from_Trefref.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2014, andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com +// +#include "boost/optional.hpp" +#include "boost/core/ignore_unused.hpp" + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +// +// THIS TEST SHOULD FAIL TO COMPILE +// +void optional_reference__test_no_init_from_Trefref() +{ + boost::optional opt = int(3); + boost::ignore_unused(opt); +} + +#else +# error "Test skipped. This cannot be implemented w/o rvalue references." +#endif diff --git a/libs/optional/test/optional_test_ref_fail_init_from_Urefref.cpp b/libs/optional/test/optional_test_ref_fail_init_from_Urefref.cpp new file mode 100644 index 00000000..af7ca279 --- /dev/null +++ b/libs/optional/test/optional_test_ref_fail_init_from_Urefref.cpp @@ -0,0 +1,27 @@ +// Copyright (C) 2014, 2016 andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com +// +#include "boost/optional.hpp" +#include "boost/core/ignore_unused.hpp" + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +// +// THIS TEST SHOULD FAIL TO COMPILE +// +void optional_reference__test_no_init_from_Urefref() +{ + boost::optional opt = long(3); + boost::ignore_unused(opt); +} + +#else +# error "Test skipped. This cannot be implemented w/o rvalue references." +#endif diff --git a/libs/optional/test/optional_test_ref_move.cpp b/libs/optional/test/optional_test_ref_move.cpp new file mode 100644 index 00000000..bf0bcb84 --- /dev/null +++ b/libs/optional/test/optional_test_ref_move.cpp @@ -0,0 +1,69 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: akrzemi1@gmail.com + + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include +#include "boost/core/addressof.hpp" +#include "boost/core/lightweight_test.hpp" + +using boost::optional; + +std::string global("text"); + +optional make_optional_string_ref() +{ + return optional(global); +} + +std::string& return_global() +{ + return global; +} + +int main() +{ + optional opt; + opt = make_optional_string_ref(); + BOOST_TEST(bool(opt)); + BOOST_TEST(*opt == global); + BOOST_TEST(boost::addressof(*opt) == boost::addressof(global)); + + { + std::string& str = *make_optional_string_ref(); + BOOST_TEST(str == global); + BOOST_TEST(boost::addressof(str) == boost::addressof(global)); + } + + { + std::string& str = make_optional_string_ref().value(); + BOOST_TEST(str == global); + BOOST_TEST(boost::addressof(str) == boost::addressof(global)); + } + + { + std::string& str = make_optional_string_ref().value_or(global); + BOOST_TEST(str == global); + BOOST_TEST(boost::addressof(str) == boost::addressof(global)); + } + + { + std::string& str = make_optional_string_ref().value_or_eval(&return_global); + BOOST_TEST(str == global); + BOOST_TEST(boost::addressof(str) == boost::addressof(global)); + } + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_ref_portable_minimum.cpp b/libs/optional/test/optional_test_ref_portable_minimum.cpp new file mode 100644 index 00000000..bf7af323 --- /dev/null +++ b/libs/optional/test/optional_test_ref_portable_minimum.cpp @@ -0,0 +1,499 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: akrzemi1@gmail.com + + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/addressof.hpp" +#include "boost/core/enable_if.hpp" +#include "boost/core/lightweight_test.hpp" +#include "testable_classes.hpp" + +using boost::optional; +using boost::none; + +struct CountingClass +{ + static int count; + static int assign_count; + CountingClass() { ++count; } + CountingClass(const CountingClass&) { ++count; } + CountingClass& operator=(const CountingClass&) { ++assign_count; return *this; } + ~CountingClass() { ++count; } +}; + +int CountingClass::count = 0; +int CountingClass::assign_count = 0; + +void test_no_object_creation() +{ + BOOST_TEST_EQ(0, CountingClass::count); + BOOST_TEST_EQ(0, CountingClass::assign_count); + { + CountingClass v1, v2; + optional oA(v1); + optional oB; + optional oC = oA; + oB = oA; + *oB = v2; + oC = none; + oC = optional(v2); + oB = none; + oA = oB; + } + BOOST_TEST_EQ(4, CountingClass::count); + BOOST_TEST_EQ(1, CountingClass::assign_count); +} + +template +typename boost::enable_if< has_arrow >::type +test_arrow_const() +{ + const typename concrete_type_of::type v(2); + optional o(v); + BOOST_TEST(o); + BOOST_TEST_EQ(o->val(), 2); + BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val())); +} + +template +typename boost::disable_if< has_arrow >::type +test_arrow_const() +{ +} + +template +typename boost::enable_if< has_arrow >::type +test_arrow_noconst_const() +{ + typename concrete_type_of::type v(2); + optional o(v); + BOOST_TEST(o); + BOOST_TEST_EQ(o->val(), 2); + BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val())); + + v.val() = 1; + BOOST_TEST(o); + BOOST_TEST_EQ(o->val(), 1); + BOOST_TEST_EQ(v.val(), 1); + BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val())); +} + +template +typename boost::disable_if< has_arrow >::type +test_arrow_noconst_const() +{ +} + +template +typename boost::enable_if< has_arrow >::type +test_arrow() +{ + typename concrete_type_of::type v(2); + optional o(v); + BOOST_TEST(o); + BOOST_TEST_EQ(o->val(), 2); + BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val())); + + v.val() = 1; + BOOST_TEST(o); + BOOST_TEST_EQ(o->val(), 1); + BOOST_TEST_EQ(v.val(), 1); + BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val())); + + o->val() = 3; + BOOST_TEST(o); + BOOST_TEST_EQ(o->val(), 3); + BOOST_TEST_EQ(v.val(), 3); + BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val())); + +} + +template +typename boost::disable_if< has_arrow >::type +test_arrow() +{ +} + +template +void test_not_containing_value_for() +{ + optional o1; + optional o2 = none; + optional o3 = o1; + + BOOST_TEST(!o1); + BOOST_TEST(!o2); + BOOST_TEST(!o3); + + BOOST_TEST(o1 == none); + BOOST_TEST(o2 == none); + BOOST_TEST(o3 == none); +} + +template +void test_direct_init_for_const() +{ + const typename concrete_type_of::type v(2); + optional o(v); + + BOOST_TEST(o); + BOOST_TEST(o != none); + BOOST_TEST(boost::addressof(*o) == boost::addressof(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 2); +} + +template +void test_direct_init_for_noconst_const() +{ + typename concrete_type_of::type v(2); + optional o(v); + + BOOST_TEST(o); + BOOST_TEST(o != none); + BOOST_TEST(boost::addressof(*o) == boost::addressof(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 2); + + val(v) = 9; + BOOST_TEST(boost::addressof(*o) == boost::addressof(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 9); + BOOST_TEST_EQ(val(v), 9); +} + +template +void test_direct_init_for() +{ + typename concrete_type_of::type v(2); + optional o(v); + + BOOST_TEST(o); + BOOST_TEST(o != none); + BOOST_TEST(boost::addressof(*o) == boost::addressof(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 2); + + val(v) = 9; + BOOST_TEST(boost::addressof(*o) == boost::addressof(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 9); + BOOST_TEST_EQ(val(v), 9); + + val(*o) = 7; + BOOST_TEST(boost::addressof(*o) == boost::addressof(v)); + BOOST_TEST_EQ(val(*o), val(v)); + BOOST_TEST_EQ(val(*o), 7); + BOOST_TEST_EQ(val(v), 7); +} + +template +void test_clearing_the_value() +{ + typename concrete_type_of::type v(2); + optional o1(v), o2(v); + + BOOST_TEST(o1); + BOOST_TEST(o1 != none); + BOOST_TEST(o2); + BOOST_TEST(o2 != none); + + o1 = none; + BOOST_TEST(!o1); + BOOST_TEST(o1 == none); + BOOST_TEST(o2); + BOOST_TEST(o2 != none); + BOOST_TEST_EQ(val(*o2), 2); + BOOST_TEST(boost::addressof(*o2) == boost::addressof(v)); + BOOST_TEST_EQ(val(v), 2); +} + +template +void test_equality() +{ + typename concrete_type_of::type v1(1), v2(2), v2_(2), v3(3); + optional o1(v1), o2(v2), o2_(v2_), o3(v3), o3_(v3), oN, oN_; + // o2 and o2_ point to different objects; o3 and o3_ point to the same object + + BOOST_TEST(oN == oN); + BOOST_TEST(oN == oN_); + BOOST_TEST(oN_ == oN); + BOOST_TEST(o1 == o1); + BOOST_TEST(o2 == o2); + BOOST_TEST(o2 == o2_); + BOOST_TEST(o2_ == o2); + BOOST_TEST(o3 == o3); + BOOST_TEST(o3 == o3_); + BOOST_TEST(!(oN == o1)); + BOOST_TEST(!(o1 == oN)); + BOOST_TEST(!(o2 == o1)); + BOOST_TEST(!(o2 == oN)); + + BOOST_TEST(!(oN != oN)); + BOOST_TEST(!(oN != oN_)); + BOOST_TEST(!(oN_ != oN)); + BOOST_TEST(!(o1 != o1)); + BOOST_TEST(!(o2 != o2)); + BOOST_TEST(!(o2 != o2_)); + BOOST_TEST(!(o2_ != o2)); + BOOST_TEST(!(o3 != o3)); + BOOST_TEST(!(o3 != o3_)); + BOOST_TEST( (oN != o1)); + BOOST_TEST( (o1 != oN)); + BOOST_TEST( (o2 != o1)); + BOOST_TEST( (o2 != oN)); +} + +template +void test_order() +{ + typename concrete_type_of::type v1(1), v2(2), v2_(2), v3(3); + optional o1(v1), o2(v2), o2_(v2_), o3(v3), o3_(v3), oN, oN_; + // o2 and o2_ point to different objects; o3 and o3_ point to the same object + + BOOST_TEST(!(oN < oN)); + BOOST_TEST(!(oN < oN_)); + BOOST_TEST(!(oN_ < oN)); + BOOST_TEST(!(o1 < o1)); + BOOST_TEST(!(o2 < o2)); + BOOST_TEST(!(o2 < o2_)); + BOOST_TEST(!(o2_ < o2)); + BOOST_TEST(!(o3 < o3)); + BOOST_TEST(!(o3 < o3_)); + + BOOST_TEST( (oN <= oN)); + BOOST_TEST( (oN <= oN_)); + BOOST_TEST( (oN_ <= oN)); + BOOST_TEST( (o1 <= o1)); + BOOST_TEST( (o2 <= o2)); + BOOST_TEST( (o2 <= o2_)); + BOOST_TEST( (o2_ <= o2)); + BOOST_TEST( (o3 <= o3)); + BOOST_TEST( (o3 <= o3_)); + + BOOST_TEST(!(oN > oN)); + BOOST_TEST(!(oN > oN_)); + BOOST_TEST(!(oN_ > oN)); + BOOST_TEST(!(o1 > o1)); + BOOST_TEST(!(o2 > o2)); + BOOST_TEST(!(o2 > o2_)); + BOOST_TEST(!(o2_ > o2)); + BOOST_TEST(!(o3 > o3)); + BOOST_TEST(!(o3 > o3_)); + + BOOST_TEST( (oN >= oN)); + BOOST_TEST( (oN >= oN_)); + BOOST_TEST( (oN_ >= oN)); + BOOST_TEST( (o1 >= o1)); + BOOST_TEST( (o2 >= o2)); + BOOST_TEST( (o2 >= o2_)); + BOOST_TEST( (o2_ >= o2)); + BOOST_TEST( (o3 >= o3)); + BOOST_TEST( (o3 >= o3_)); + + BOOST_TEST( (oN < o1)); + BOOST_TEST( (oN_ < o1)); + BOOST_TEST( (oN < o2)); + BOOST_TEST( (oN_ < o2)); + BOOST_TEST( (oN < o2_)); + BOOST_TEST( (oN_ < o2_)); + BOOST_TEST( (oN < o3)); + BOOST_TEST( (oN_ < o3)); + BOOST_TEST( (oN < o3_)); + BOOST_TEST( (oN_ < o3_)); + BOOST_TEST( (o1 < o2)); + BOOST_TEST( (o1 < o2_)); + BOOST_TEST( (o1 < o3)); + BOOST_TEST( (o1 < o3_)); + BOOST_TEST( (o2 < o3)); + BOOST_TEST( (o2_ < o3)); + BOOST_TEST( (o2 < o3_)); + BOOST_TEST( (o2_ < o3_)); + + BOOST_TEST( (oN <= o1)); + BOOST_TEST( (oN_ <= o1)); + BOOST_TEST( (oN <= o2)); + BOOST_TEST( (oN_ <= o2)); + BOOST_TEST( (oN <= o2_)); + BOOST_TEST( (oN_ <= o2_)); + BOOST_TEST( (oN <= o3)); + BOOST_TEST( (oN_ <= o3)); + BOOST_TEST( (oN <= o3_)); + BOOST_TEST( (oN_ <= o3_)); + BOOST_TEST( (o1 <= o2)); + BOOST_TEST( (o1 <= o2_)); + BOOST_TEST( (o1 <= o3)); + BOOST_TEST( (o1 <= o3_)); + BOOST_TEST( (o2 <= o3)); + BOOST_TEST( (o2_ <= o3)); + BOOST_TEST( (o2 <= o3_)); + BOOST_TEST( (o2_ <= o3_)); + + BOOST_TEST(!(oN > o1)); + BOOST_TEST(!(oN_ > o1)); + BOOST_TEST(!(oN > o2)); + BOOST_TEST(!(oN_ > o2)); + BOOST_TEST(!(oN > o2_)); + BOOST_TEST(!(oN_ > o2_)); + BOOST_TEST(!(oN > o3)); + BOOST_TEST(!(oN_ > o3)); + BOOST_TEST(!(oN > o3_)); + BOOST_TEST(!(oN_ > o3_)); + BOOST_TEST(!(o1 > o2)); + BOOST_TEST(!(o1 > o2_)); + BOOST_TEST(!(o1 > o3)); + BOOST_TEST(!(o1 > o3_)); + BOOST_TEST(!(o2 > o3)); + BOOST_TEST(!(o2_ > o3)); + BOOST_TEST(!(o2 > o3_)); + BOOST_TEST(!(o2_ > o3_)); + + BOOST_TEST(!(oN >= o1)); + BOOST_TEST(!(oN_ >= o1)); + BOOST_TEST(!(oN >= o2)); + BOOST_TEST(!(oN_ >= o2)); + BOOST_TEST(!(oN >= o2_)); + BOOST_TEST(!(oN_ >= o2_)); + BOOST_TEST(!(oN >= o3)); + BOOST_TEST(!(oN_ >= o3)); + BOOST_TEST(!(oN >= o3_)); + BOOST_TEST(!(oN_ >= o3_)); + BOOST_TEST(!(o1 >= o2)); + BOOST_TEST(!(o1 >= o2_)); + BOOST_TEST(!(o1 >= o3)); + BOOST_TEST(!(o1 >= o3_)); + BOOST_TEST(!(o2 >= o3)); + BOOST_TEST(!(o2_ >= o3)); + BOOST_TEST(!(o2 >= o3_)); + BOOST_TEST(!(o2_ >= o3_)); + + BOOST_TEST(!(o1 < oN)); + BOOST_TEST(!(o1 < oN_)); + BOOST_TEST(!(o2 < oN)); + BOOST_TEST(!(o2 < oN_)); + BOOST_TEST(!(o2_ < oN)); + BOOST_TEST(!(o2_ < oN_)); + BOOST_TEST(!(o3 < oN)); + BOOST_TEST(!(o3 < oN_)); + BOOST_TEST(!(o3_ < oN)); + BOOST_TEST(!(o3_ < oN_)); + BOOST_TEST(!(o2 < oN)); + BOOST_TEST(!(o2_ < oN_)); + BOOST_TEST(!(o3 < oN)); + BOOST_TEST(!(o3_ < oN_)); + BOOST_TEST(!(o3 < oN)); + BOOST_TEST(!(o3 < oN_)); + BOOST_TEST(!(o3_ < oN)); + BOOST_TEST(!(o3_ < oN_)); +} + +template +void test_swap() +{ + typename concrete_type_of::type v1(1), v2(2); + optional o1(v1), o1_(v1), o2(v2), o2_(v2), oN, oN_; + + swap(o1, o1); + BOOST_TEST(o1); + BOOST_TEST(boost::addressof(*o1) == boost::addressof(v1)); + + swap(oN, oN_); + BOOST_TEST(!oN); + BOOST_TEST(!oN_); + + swap(o1, oN); + BOOST_TEST(!o1); + BOOST_TEST(oN); + BOOST_TEST(boost::addressof(*oN) == boost::addressof(v1)); + + swap(oN, o1); + BOOST_TEST(!oN); + BOOST_TEST(o1); + BOOST_TEST(boost::addressof(*o1) == boost::addressof(v1)); + + swap(o1_, o2_); + BOOST_TEST(o1_); + BOOST_TEST(o2_); + BOOST_TEST(boost::addressof(*o1_) == boost::addressof(v2)); + BOOST_TEST(boost::addressof(*o2_) == boost::addressof(v1)); +} + +template +void test_convertibility_of_compatible_reference_types() +{ + typename concrete_type_of::type v1(1); + optional oN, o1(v1); + optional uN(oN), u1(o1); + BOOST_TEST(!uN); + BOOST_TEST(u1); + BOOST_TEST(boost::addressof(*u1) == boost::addressof(*o1)); + + uN = o1; + u1 = oN; + BOOST_TEST(!u1); + BOOST_TEST(uN); + BOOST_TEST(boost::addressof(*uN) == boost::addressof(*o1)); +} + +template +void test_optional_ref() +{ + test_not_containing_value_for(); + test_direct_init_for(); + test_clearing_the_value(); + test_arrow(); + test_equality(); + test_order(); + test_swap(); +} + +template +void test_optional_const_ref() +{ + test_not_containing_value_for(); + test_direct_init_for_const(); + test_direct_init_for_noconst_const(); + test_clearing_the_value(); + test_clearing_the_value(); + test_arrow_const(); + test_arrow_noconst_const(); + test_equality(); + test_equality(); + test_order(); + test_order(); + test_swap(); + test_swap(); +} + +int main() +{ + test_optional_ref(); + test_optional_ref(); + test_optional_ref(); + test_optional_ref< optional >(); + + test_optional_const_ref(); + test_optional_const_ref(); + test_optional_const_ref(); + test_optional_const_ref< optional >(); + + test_convertibility_of_compatible_reference_types(); + test_convertibility_of_compatible_reference_types(); + test_convertibility_of_compatible_reference_types(); + test_convertibility_of_compatible_reference_types(); + test_convertibility_of_compatible_reference_types, const optional >(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_ref_to_val.cpp b/libs/optional/test/optional_test_ref_to_val.cpp new file mode 100644 index 00000000..e93469f1 --- /dev/null +++ b/libs/optional/test/optional_test_ref_to_val.cpp @@ -0,0 +1,116 @@ +// Copyright (C) 2016 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" + +using boost::optional; +using boost::none; + +struct Value +{ + int val; + explicit Value(int v) : val(v) {} +}; + +int val(int const& i) +{ + return i; +} + +int val(Value const& v) +{ + return v.val; +} + +template +optional make_opt_ref(Tref& v) +{ + return optional(v); +} + +template +void test_construct_from_optional_ref() +{ + Tref v1 (1), v2 (2); + + optional opt_ref0; + optional opt_ref1 (v1); + + optional opt_val0 (opt_ref0); + optional opt_val1 (opt_ref1); + optional opt_val2 (make_opt_ref(v2)); + + BOOST_TEST (!opt_val0); + BOOST_TEST (opt_val1); + BOOST_TEST (opt_val2); + + BOOST_TEST_EQ (1, val(*opt_val1)); + BOOST_TEST_EQ (2, val(*opt_val2)); + + BOOST_TEST (boost::addressof(*opt_val1) != boost::addressof(v1)); + BOOST_TEST (boost::addressof(*opt_val2) != boost::addressof(v2)); +} + +template +void test_assign_from_optional_ref() +{ + Tref v1 (1), v2 (2); + + optional opt_ref0; + optional opt_ref1 (v1); + + optional opt_val0; + optional opt_val1; + optional opt_val2; + + opt_val0 = opt_ref0; + opt_val1 = opt_ref1; + opt_val2 = make_opt_ref(v2); + + BOOST_TEST (!opt_val0); + BOOST_TEST (opt_val1); + BOOST_TEST (opt_val2); + + BOOST_TEST_EQ (1, val(*opt_val1)); + BOOST_TEST_EQ (2, val(*opt_val2)); + + BOOST_TEST (boost::addressof(*opt_val1) != boost::addressof(v1)); + BOOST_TEST (boost::addressof(*opt_val2) != boost::addressof(v2)); +} + + +int main() +{ + test_construct_from_optional_ref(); + test_construct_from_optional_ref(); + test_construct_from_optional_ref(); + test_construct_from_optional_ref(); + + test_construct_from_optional_ref(); + test_construct_from_optional_ref(); + test_construct_from_optional_ref(); + test_construct_from_optional_ref(); + + test_assign_from_optional_ref(); + test_assign_from_optional_ref(); + + test_assign_from_optional_ref(); + test_assign_from_optional_ref(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_sfinae_friendly_ctor.cpp b/libs/optional/test/optional_test_sfinae_friendly_ctor.cpp new file mode 100644 index 00000000..c13bb2bb --- /dev/null +++ b/libs/optional/test/optional_test_sfinae_friendly_ctor.cpp @@ -0,0 +1,49 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +using boost::optional; + +#if (!defined BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT) + +struct X {}; +struct Y {}; + +struct Resource +{ + explicit Resource(const X&) {} +}; + +BOOST_STATIC_ASSERT(( boost::is_constructible::value )); +BOOST_STATIC_ASSERT(( !boost::is_constructible::value )); + +BOOST_STATIC_ASSERT(( boost::is_constructible, const X&>::value )); +BOOST_STATIC_ASSERT(( !boost::is_constructible, const Y&>::value )); + +#ifndef BOOST_OPTIONAL_DETAIL_NO_SFINAE_FRIENDLY_CONSTRUCTORS +BOOST_STATIC_ASSERT(( boost::is_constructible< optional< optional >, optional >::value )); +BOOST_STATIC_ASSERT(( !boost::is_constructible< optional, optional< optional > >::value )); + +BOOST_STATIC_ASSERT(( boost::is_constructible< optional< optional >, const optional& >::value )); +BOOST_STATIC_ASSERT(( !boost::is_constructible< optional, const optional< optional >& >::value )); + +BOOST_STATIC_ASSERT(( boost::is_constructible, const optional&>::value )); +BOOST_STATIC_ASSERT(( !boost::is_constructible, const optional&>::value )); +#endif + +#endif + +int main() { } diff --git a/libs/optional/test/optional_test_static_properties.cpp b/libs/optional/test/optional_test_static_properties.cpp new file mode 100644 index 00000000..5dc10537 --- /dev/null +++ b/libs/optional/test/optional_test_static_properties.cpp @@ -0,0 +1,146 @@ +// Copyright (C) 2017 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/core/lightweight_test_trait.hpp" +#include "boost/type_traits/is_base_of.hpp" +#include "boost/optional/detail/experimental_traits.hpp" + +#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS + +struct PrivDefault +{ + private: PrivDefault() {} +}; + +struct CustDefault +{ + CustDefault() {} +}; + +struct CustomizedTrivial +{ + CustomizedTrivial() {} +}; + +struct DeletedDefault +{ + BOOST_DELETED_FUNCTION(DeletedDefault()) +}; + +namespace boost { namespace optional_config { + +template <> struct optional_uses_direct_storage_for : boost::true_type {}; + +}} + +struct CustDtor +{ + ~CustDtor() {} +}; + +struct NoDefault +{ + explicit NoDefault(int) {} +}; + +struct Empty {}; + +template +struct Aggregate { T t; U u; }; + +struct CustAssign +{ + CustAssign& operator=(CustAssign const&) { return *this; } +}; + +struct CustMove +{ + CustMove(CustMove &&) {} +}; + +void test_type_traits() +{ + // this only tests if type traits are implemented correctly + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); + + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); + + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); + + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); + + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); + + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for, double> > )); +#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES + + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable, double> > )); + +#endif + + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); + + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable > )); +} + +void test_trivial_copyability() +{ + BOOST_TEST_TRAIT_TRUE((boost::is_base_of, boost::optional > )); + BOOST_TEST_TRAIT_TRUE((boost::is_base_of, boost::optional > )); + BOOST_TEST_TRAIT_TRUE((boost::is_base_of, boost::optional > )); + BOOST_TEST_TRAIT_FALSE((boost::is_base_of, boost::optional > )); + +#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); + + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable > )); +#endif + + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable > )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable > > )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable, double> > > )); +} + +#endif + +int main() +{ +#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS + test_type_traits(); + test_trivial_copyability(); +#endif + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_swap.cpp b/libs/optional/test/optional_test_swap.cpp new file mode 100644 index 00000000..2294c703 --- /dev/null +++ b/libs/optional/test/optional_test_swap.cpp @@ -0,0 +1,366 @@ +// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +// Revisions: +// 12 May 2008 (added more swap tests) +// + +#include "boost/optional/optional.hpp" +#include "boost/utility/in_place_factory.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" + +#if __cplusplus < 201103L +#include +#else +#include +#endif + +using boost::optional; +using boost::none; + +#define ARG(T) (static_cast< T const* >(0)) + +namespace optional_swap_test +{ + class default_ctor_exception : public std::exception {} ; + class copy_ctor_exception : public std::exception {} ; + class assignment_exception : public std::exception {} ; + + // + // Base class for swap test classes. Its assignment should not be called, when swapping + // optional objects. (The default std::swap would do so.) + // + class base_class_with_forbidden_assignment + { + public: + base_class_with_forbidden_assignment & operator=(const base_class_with_forbidden_assignment &) + { + BOOST_TEST(!"The assignment should not be used while swapping!"); + throw assignment_exception(); + } + + virtual ~base_class_with_forbidden_assignment() {} + }; + + // + // Class without default constructor + // + class class_without_default_ctor : public base_class_with_forbidden_assignment + { + public: + char data; + explicit class_without_default_ctor(char arg) : data(arg) {} + }; + + // + // Class whose default constructor should not be used by optional::swap! + // + class class_whose_default_ctor_should_not_be_used : public base_class_with_forbidden_assignment + { + public: + char data; + explicit class_whose_default_ctor_should_not_be_used(char arg) : data(arg) {} + + class_whose_default_ctor_should_not_be_used() + { + BOOST_TEST(!"This default constructor should not be used while swapping!"); + throw default_ctor_exception(); + } + }; + + // + // Class whose default constructor should be used by optional::swap. + // Its copy constructor should be avoided! + // + class class_whose_default_ctor_should_be_used : public base_class_with_forbidden_assignment + { + public: + char data; + explicit class_whose_default_ctor_should_be_used(char arg) : data(arg) { } + + class_whose_default_ctor_should_be_used() : data('\0') { } + + class_whose_default_ctor_should_be_used(const class_whose_default_ctor_should_be_used &) + { + BOOST_TEST(!"This copy constructor should not be used while swapping!"); + throw copy_ctor_exception(); + } + }; + + // + // Class template whose default constructor should be used by optional::swap. + // Its copy constructor should be avoided! + // + template + class template_whose_default_ctor_should_be_used : public base_class_with_forbidden_assignment + { + public: + T data; + explicit template_whose_default_ctor_should_be_used(T arg) : data(arg) { } + + template_whose_default_ctor_should_be_used() : data('\0') { } + + template_whose_default_ctor_should_be_used(const template_whose_default_ctor_should_be_used &) + { + BOOST_TEST(!"This copy constructor should not be used while swapping!"); + throw copy_ctor_exception(); + } + }; + + // + // Class whose explicit constructor should be used by optional::swap. + // Its other constructors should be avoided! + // + class class_whose_explicit_ctor_should_be_used : public base_class_with_forbidden_assignment + { + public: + char data; + explicit class_whose_explicit_ctor_should_be_used(char arg) : data(arg) { } + + class_whose_explicit_ctor_should_be_used() + { + BOOST_TEST(!"This default constructor should not be used while swapping!"); + throw default_ctor_exception(); + } + + class_whose_explicit_ctor_should_be_used(const class_whose_explicit_ctor_should_be_used &) + { + BOOST_TEST(!"This copy constructor should not be used while swapping!"); + throw copy_ctor_exception(); + } + }; + + void swap(class_whose_default_ctor_should_not_be_used & lhs, class_whose_default_ctor_should_not_be_used & rhs) + { + std::swap(lhs.data, rhs.data); + } + + void swap(class_whose_default_ctor_should_be_used & lhs, class_whose_default_ctor_should_be_used & rhs) + { + std::swap(lhs.data, rhs.data); + } + + void swap(class_without_default_ctor & lhs, class_without_default_ctor & rhs) + { + std::swap(lhs.data, rhs.data); + } + + void swap(class_whose_explicit_ctor_should_be_used & lhs, class_whose_explicit_ctor_should_be_used & rhs) + { + std::swap(lhs.data, rhs.data); + } + + template + void swap(template_whose_default_ctor_should_be_used & lhs, template_whose_default_ctor_should_be_used & rhs) + { + std::swap(lhs.data, rhs.data); + } + + // + // optional::swap should be customized when neither the copy constructor + // nor the default constructor of T are supposed to be used when swapping, e.g., + // for the following type T = class_whose_explicit_ctor_should_be_used. + // + void swap(boost::optional & x, boost::optional & y) + { + bool hasX(x); + bool hasY(y); + + if ( !hasX && !hasY ) + return; + + if( !hasX ) + x = boost::in_place('\0'); + else if ( !hasY ) + y = boost::in_place('\0'); + + optional_swap_test::swap(*x,*y); + + if( !hasX ) + y = boost::none ; + else if( !hasY ) + x = boost::none ; + } + + +} // End of namespace optional_swap_test. + + +namespace boost { + +// +// Compile time tweaking on whether or not swap should use the default constructor: +// + +template <> struct optional_swap_should_use_default_constructor< + optional_swap_test::class_whose_default_ctor_should_be_used> : true_type {} ; + +template <> struct optional_swap_should_use_default_constructor< + optional_swap_test::class_whose_default_ctor_should_not_be_used> : false_type {} ; + +template struct optional_swap_should_use_default_constructor< + optional_swap_test::template_whose_default_ctor_should_be_used > : true_type {} ; + + +// +// Specialization of boost::swap: +// +template <> +void swap(optional & x, optional & y) +{ + optional_swap_test::swap(x, y); +} + +} // namespace boost + + +namespace std { + +// +// Specializations of std::swap: +// + +template <> +void swap(optional_swap_test::class_whose_default_ctor_should_be_used & x, optional_swap_test::class_whose_default_ctor_should_be_used & y) +{ + optional_swap_test::swap(x, y); +} + +template <> +void swap(optional_swap_test::class_whose_default_ctor_should_not_be_used & x, optional_swap_test::class_whose_default_ctor_should_not_be_used & y) +{ + optional_swap_test::swap(x, y); +} + +template <> +void swap(optional_swap_test::class_without_default_ctor & x, optional_swap_test::class_without_default_ctor & y) +{ + optional_swap_test::swap(x, y); +} + +template <> +void swap(optional_swap_test::class_whose_explicit_ctor_should_be_used & x, optional_swap_test::class_whose_explicit_ctor_should_be_used & y) +{ + optional_swap_test::swap(x, y); +} + +} // namespace std + + +// +// Tests whether the swap function works properly for optional. +// Assumes that T has one data member, of type char. +// Returns true iff the test is passed. +// +template +void test_swap_function( T const* ) +{ + try + { + optional obj1; + optional obj2('a'); + + // Self-swap should not have any effect. + swap(obj1, obj1); + swap(obj2, obj2); + BOOST_TEST(!obj1); + BOOST_TEST(!!obj2 && obj2->data == 'a'); + + // Call non-member swap. + swap(obj1, obj2); + + // Test if obj1 and obj2 are really swapped. + BOOST_TEST(!!obj1 && obj1->data == 'a'); + BOOST_TEST(!obj2); + + // Call non-member swap one more time. + swap(obj1, obj2); + + // Test if obj1 and obj2 are swapped back. + BOOST_TEST(!obj1); + BOOST_TEST(!!obj2 && obj2->data == 'a'); + } + catch(const std::exception &) + { + // The swap function should not throw, for our test cases. + BOOST_TEST(!"throw in swap"); + } +} + +// +// Tests whether the optional::swap member function works properly. +// Assumes that T has one data member, of type char. +// Returns true iff the test is passed. +// +template +void test_swap_member_function( T const* ) +{ + try + { + optional obj1; + optional obj2('a'); + + // Self-swap should not have any effect. + obj1.swap(obj1); + obj2.swap(obj2); + BOOST_TEST(!obj1); + BOOST_TEST(!!obj2 && obj2->data == 'a'); + + // Call member swap. + obj1.swap(obj2); + + // Test if obj1 and obj2 are really swapped. + BOOST_TEST(!!obj1 && obj1->data == 'a'); + BOOST_TEST(!obj2); + + // Call member swap one more time. + obj1.swap(obj2); + + // Test if obj1 and obj2 are swapped back. + BOOST_TEST(!obj1); + BOOST_TEST(!!obj2 && obj2->data == 'a'); + } + catch(const std::exception &) + { + BOOST_TEST(!"throw in swap"); + } +} + + +// +// Tests compile time tweaking of swap, by means of +// optional_swap_should_use_default_constructor. +// +void test_swap_tweaking() +{ + ( test_swap_function( ARG(optional_swap_test::class_without_default_ctor) ) ); + ( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) ); + ( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) ); + ( test_swap_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) ); + ( test_swap_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used) ) ); + ( test_swap_member_function( ARG(optional_swap_test::class_without_default_ctor) ) ); + ( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) ); + ( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) ); + ( test_swap_member_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) ); + ( test_swap_member_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used) ) ); +} + +int main() +{ + test_swap_tweaking(); + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_test_tc_base.cpp b/libs/optional/test/optional_test_tc_base.cpp new file mode 100644 index 00000000..60463959 --- /dev/null +++ b/libs/optional/test/optional_test_tc_base.cpp @@ -0,0 +1,87 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" + +#if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) + +int main() +{ +} + +#else + +#include + +struct NotDefaultConstructible +{ + NotDefaultConstructible() = delete; +}; + +void test_tc_base() +{ + boost::optional o; + + BOOST_TEST(boost::none == o); +} + +struct S +{ + +}; + +template +struct W +{ + T& t_; + + template + W(Args&&... args) + : t_(std::forward(args)...) + { + } +}; + +void test_value_init() +{ +#ifndef BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX + { + S s; + W w{s}; + } +#endif + { + S s; + W w(s); + } +} + +void test_optional_reference_wrapper() +{ + boost::optional > o; + BOOST_TEST(boost::none == o); +} + +int main() +{ + test_tc_base(); + test_value_init(); + test_optional_reference_wrapper(); + return boost::report_errors(); +} + +#endif diff --git a/libs/optional/test/optional_test_tie.cpp b/libs/optional/test/optional_test_tie.cpp new file mode 100644 index 00000000..1ea34f44 --- /dev/null +++ b/libs/optional/test/optional_test_tie.cpp @@ -0,0 +1,74 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/none.hpp" +#include "boost/tuple/tuple.hpp" + +struct counting_oracle +{ + int val; + counting_oracle() : val() { ++default_ctor_count; } + counting_oracle(int v) : val(v) { ++val_ctor_count; } + counting_oracle(const counting_oracle& rhs) : val(rhs.val) { ++copy_ctor_count; } + counting_oracle& operator=(const counting_oracle& rhs) { val = rhs.val; ++copy_assign_count; return *this; } + ~counting_oracle() { ++dtor_count; } + + static int dtor_count; + static int default_ctor_count; + static int val_ctor_count; + static int copy_ctor_count; + static int copy_assign_count; + static int equals_count; + + friend bool operator==(const counting_oracle& lhs, const counting_oracle& rhs) { ++equals_count; return lhs.val == rhs.val; } + + static void clear_count() + { + dtor_count = default_ctor_count = val_ctor_count = copy_ctor_count = copy_assign_count = equals_count = 0; + } +}; + +int counting_oracle::dtor_count = 0; +int counting_oracle::default_ctor_count = 0; +int counting_oracle::val_ctor_count = 0; +int counting_oracle::copy_ctor_count = 0; +int counting_oracle::copy_assign_count = 0; +int counting_oracle::equals_count = 0; + +// Test boost::tie() interoperability. +int main() +{ + const std::pair pair(1, 2); + counting_oracle::clear_count(); + + boost::optional o1, o2; + boost::tie(o1, o2) = pair; + + BOOST_TEST(o1); + BOOST_TEST(o2); + BOOST_TEST(*o1 == counting_oracle(1)); + BOOST_TEST(*o2 == counting_oracle(2)); + BOOST_TEST_EQ(2, counting_oracle::copy_ctor_count); + BOOST_TEST_EQ(0, counting_oracle::copy_assign_count); + BOOST_TEST_EQ(0, counting_oracle::default_ctor_count); + + return boost::report_errors(); +} + + diff --git a/libs/optional/test/optional_test_value_access.cpp b/libs/optional/test/optional_test_value_access.cpp new file mode 100644 index 00000000..c11cb423 --- /dev/null +++ b/libs/optional/test/optional_test_value_access.cpp @@ -0,0 +1,222 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/optional/optional.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/ignore_unused.hpp" +#include "boost/core/lightweight_test.hpp" + +using boost::optional; + +struct IntWrapper +{ + int _i; + IntWrapper(int i) : _i(i) {} + bool operator==(IntWrapper const& rhs) const { return _i == rhs._i; } +}; + +template +void test_function_value_or_for() +{ + optional oM0; + const optional oC0; + optional oM1(1); + const optional oC2(2); + + BOOST_TEST(oM0.value_or(5) == 5); + BOOST_TEST(oC0.value_or(5) == 5); + BOOST_TEST(oM1.value_or(5) == 1); + BOOST_TEST(oC2.value_or(5) == 2); +} + +template +void test_function_value_for() +{ + optional o0; + optional o1(1); + const optional oC(2); + + try + { + T& v = o1.value(); + BOOST_TEST(v == 1); + } + catch(...) + { + BOOST_TEST(false); + } + + try + { + T const& v = oC.value(); + BOOST_TEST(v == 2); + } + catch(...) + { + BOOST_TEST(false); + } + + BOOST_TEST_THROWS(o0.value(), boost::bad_optional_access); +} + +void test_function_value() +{ + test_function_value_for(); + test_function_value_for(); + test_function_value_for(); +} + +struct FatToIntConverter +{ + static int conversions; + int _val; + FatToIntConverter(int val) : _val(val) {} + operator int() const { conversions += 1; return _val; } +}; + +int FatToIntConverter::conversions = 0; + +void test_function_value_or() +{ + test_function_value_or_for(); + test_function_value_or_for(); + test_function_value_or_for(); + + optional oi(1); + BOOST_TEST(oi.value_or(FatToIntConverter(2)) == 1); + BOOST_TEST(FatToIntConverter::conversions == 0); + + oi = boost::none; + BOOST_TEST(oi.value_or(FatToIntConverter(2)) == 2); + BOOST_TEST(FatToIntConverter::conversions == 1); +} + + +struct FunM +{ + int operator()() { return 5; } +}; + +struct FunC +{ + int operator()() const { return 6; } +}; + +int funP () +{ + return 7; +} + +int throw_() +{ + throw int(); +} + +void test_function_value_or_eval() +{ + optional o1 = 1; + optional oN; + FunM funM; + FunC funC; + + BOOST_TEST_EQ(o1.value_or_eval(funM), 1); + BOOST_TEST_EQ(oN.value_or_eval(funM), 5); + BOOST_TEST_EQ(o1.value_or_eval(FunM()), 1); + BOOST_TEST_EQ(oN.value_or_eval(FunM()), 5); + + BOOST_TEST_EQ(o1.value_or_eval(funC), 1); + BOOST_TEST_EQ(oN.value_or_eval(funC), 6); + BOOST_TEST_EQ(o1.value_or_eval(FunC()), 1); + BOOST_TEST_EQ(oN.value_or_eval(FunC()), 6); + + BOOST_TEST_EQ(o1.value_or_eval(funP), 1); + BOOST_TEST_EQ(oN.value_or_eval(funP), 7); + +#ifndef BOOST_NO_CXX11_LAMBDAS + BOOST_TEST_EQ(o1.value_or_eval([](){return 8;}), 1); + BOOST_TEST_EQ(oN.value_or_eval([](){return 8;}), 8); +#endif + + try + { + BOOST_TEST_EQ(o1.value_or_eval(throw_), 1); + } + catch(...) + { + BOOST_TEST(false); + } + + BOOST_TEST_THROWS(oN.value_or_eval(throw_), int); +} + +const optional makeConstOptVal() +{ + return std::string("something"); +} + +void test_const_move() +{ + std::string s5 = *makeConstOptVal(); + std::string s6 = makeConstOptVal().value(); + boost::ignore_unused(s5); + boost::ignore_unused(s6); +} + + +#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) +struct MoveOnly +{ + explicit MoveOnly(int){} + MoveOnly(MoveOnly &&){} + void operator=(MoveOnly &&); +private: + MoveOnly(MoveOnly const&); + void operator=(MoveOnly const&); +}; + +optional makeMoveOnly() +{ + return MoveOnly(1); +} + +MoveOnly moveOnlyDefault() +{ + return MoveOnly(1); +} + +// compile-time test +void test_move_only_getters() +{ + MoveOnly m1 = *makeMoveOnly(); + MoveOnly m2 = makeMoveOnly().value(); + MoveOnly m3 = makeMoveOnly().value_or(MoveOnly(1)); + MoveOnly m4 = makeMoveOnly().value_or_eval(moveOnlyDefault); + boost::ignore_unused(m1); + boost::ignore_unused(m2); + boost::ignore_unused(m3); + boost::ignore_unused(m4); +} + +#endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS + +int main() +{ + test_function_value(); + test_function_value_or(); + test_function_value_or_eval(); + test_const_move(); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp b/libs/optional/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp new file mode 100644 index 00000000..202c7ef9 --- /dev/null +++ b/libs/optional/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp @@ -0,0 +1,50 @@ +// Copyright (C) 2015 - 2018 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" +#include "boost/predef.h" +#include + +int main() +{ +#if defined(__GNUC__) + + std::string emptys; + +#ifdef BOOST_INTEL_CXX_VERSION + BOOST_TEST_EQ(emptys, "HAS INTEL INSIDE"); +#else + BOOST_TEST_EQ(emptys, "NO INTEL INSIDE"); +#endif + +#if !defined BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_TEST_EQ(emptys, "HAS RVALUE REFS"); +#else + BOOST_TEST_EQ(emptys, "NO RVALUE REFS"); +#endif + + int empty = -1; + BOOST_TEST_EQ(empty, __GNUC__); + BOOST_TEST_EQ(empty, __GNUC_MINOR__); + BOOST_TEST_EQ(empty, __GNUC_PATCHLEVEL__); + BOOST_TEST_EQ(empty, __cplusplus); +#endif + + BOOST_TEST_EQ(empty, BOOST_COMP_GNUC); + BOOST_TEST_EQ(empty, BOOST_COMP_CLANG); + BOOST_TEST_EQ(empty, BOOST_LANG_STDCPP); + BOOST_TEST_EQ(empty, BOOST_LIB_C_GNU); + BOOST_TEST_EQ(empty, BOOST_LIB_STD_GNU); + BOOST_TEST_EQ(empty, BOOST_LIB_STD_CXX); + + return boost::report_errors(); +} diff --git a/libs/optional/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp b/libs/optional/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp new file mode 100644 index 00000000..030b9ba9 --- /dev/null +++ b/libs/optional/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_fail.cpp @@ -0,0 +1,37 @@ +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/core/ignore_unused.hpp" +#include "boost/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" + +#if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (!defined BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF) + +# error "failed as requested" + +#else + +struct S {}; + +struct Binder +{ + S& ref_; + template Binder (R&&r) : ref_(r) {} +}; + +int main() +{ + S s ; + Binder b = s; + boost::ignore_unused(b); +} + +#endif diff --git a/libs/optional/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp b/libs/optional/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp new file mode 100644 index 00000000..a6edbc6d --- /dev/null +++ b/libs/optional/test/optional_xconfig_NO_LEGAL_CONVERT_FROM_REF_pass.cpp @@ -0,0 +1,38 @@ +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/core/ignore_unused.hpp" +#include "boost/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" + +#if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_LEGAL_CONVERT_FROM_REF) + +int main() { return 0; } + +#else + +struct S {}; + +struct Binder +{ + S& ref_; + template Binder (R&&r) : ref_(r) {} +}; + +int main() +{ + S s ; + Binder b = s; + boost::ignore_unused(b); + return 0; +} + +#endif diff --git a/libs/optional/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp b/libs/optional/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp new file mode 100644 index 00000000..7bf6d928 --- /dev/null +++ b/libs/optional/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_fail.cpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" + +#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT + +int main() +{ + BOOST_ERROR("failed as requested"); + return boost::report_errors(); +} + +#else + +const int global_i = 0; + +struct Binder +{ + void operator=(const int& i) + { + BOOST_TEST(&i == &global_i); + } +}; + +int main() +{ + Binder s; + s = global_i; + return boost::report_errors(); +} + +#endif diff --git a/libs/optional/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp b/libs/optional/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp new file mode 100644 index 00000000..942b8565 --- /dev/null +++ b/libs/optional/test/optional_xconfig_NO_PROPER_ASSIGN_FROM_CONST_INT_pass.cpp @@ -0,0 +1,41 @@ +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" + +#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT + +const int global_i = 0; + +struct Binder +{ + void operator=(const int& i) + { + BOOST_TEST(&i == &global_i); + } +}; + +int main() +{ + Binder s; + s = global_i; + return boost::report_errors(); +} + +#else + +int main() +{ + return boost::report_errors(); +} + +#endif diff --git a/libs/optional/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp b/libs/optional/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp new file mode 100644 index 00000000..07bb1b6b --- /dev/null +++ b/libs/optional/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_fail.cpp @@ -0,0 +1,43 @@ +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/core/ignore_unused.hpp" +#include "boost/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" + +#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT + +int main() +{ + BOOST_ERROR("failed as requested"); + return boost::report_errors(); +} + +#else + +const int global_i = 0; + +struct Binder +{ + Binder(const int& i) + { + BOOST_TEST(&i == &global_i); + } +}; + +int main() +{ + Binder b = global_i; + boost::ignore_unused(b); + return boost::report_errors(); +} + +#endif diff --git a/libs/optional/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp b/libs/optional/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp new file mode 100644 index 00000000..b71554e1 --- /dev/null +++ b/libs/optional/test/optional_xconfig_NO_PROPER_CONVERT_FROM_CONST_INT_pass.cpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/lib/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#include "boost/core/ignore_unused.hpp" +#include "boost/core/lightweight_test.hpp" +#include "boost/optional/detail/optional_config.hpp" + +#ifndef BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT + +const int global_i = 0; + +struct Binder +{ + Binder(const int& i) + { + BOOST_TEST(&i == &global_i); + } +}; + +int main() +{ + Binder b = global_i; + boost::ignore_unused(b); + return boost::report_errors(); +} + +#else + +int main() +{ + return boost::report_errors(); +} + +#endif diff --git a/libs/optional/test/testable_classes.hpp b/libs/optional/test/testable_classes.hpp new file mode 100644 index 00000000..3b2a436d --- /dev/null +++ b/libs/optional/test/testable_classes.hpp @@ -0,0 +1,103 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// akrzemi1@gmail.com + +#ifndef BOOST_OPTIONAL_TEST_TESTABKE_CLASSES_AK_07JAN2015_HPP +#define BOOST_OPTIONAL_TEST_TESTABKE_CLASSES_AK_07JAN2015_HPP + +#include "boost/optional/optional.hpp" + +struct ScopeGuard // no copy/move ctor/assign +{ + int val_; + explicit ScopeGuard(int v) : val_(v) {} + int& val() { return val_; } + const int& val() const { return val_; } + +private: + ScopeGuard(ScopeGuard const&); + void operator=(ScopeGuard const&); +}; + +struct Abstract +{ + virtual int& val() = 0; + virtual const int& val() const = 0; + virtual ~Abstract() {} + Abstract(){} + +private: + Abstract(Abstract const&); + void operator=(Abstract const&); +}; + +struct Impl : Abstract +{ + int val_; + Impl(int v) : val_(v) {} + int& val() { return val_; } + const int& val() const { return val_; } +}; + +template +struct concrete_type_of +{ + typedef T type; +}; + +template <> +struct concrete_type_of +{ + typedef Impl type; +}; + +template <> +struct concrete_type_of +{ + typedef const Impl type; +}; + +template +struct has_arrow +{ + static const bool value = true; +}; + +template <> +struct has_arrow +{ + static const bool value = false; +}; + +template <> +struct has_arrow< boost::optional > +{ + static const bool value = false; +}; + +int& val(int& i) { return i; } +int& val(Abstract& a) { return a.val(); } +int& val(Impl& a) { return a.val(); } +int& val(ScopeGuard& g) { return g.val(); } +template int& val(T& o) { return *o; } + +const int& val(const int& i) { return i; } +const int& val(const Abstract& a) { return a.val(); } +const int& val(const Impl& a) { return a.val(); } +const int& val(const ScopeGuard& g) { return g.val(); } +template const int& val(const T& o) { return *o; } + +bool operator==(const Abstract& l, const Abstract& r) { return l.val() == r.val(); } +bool operator==(const ScopeGuard& l, const ScopeGuard& r) { return l.val() == r.val(); } + +bool operator<(const Abstract& l, const Abstract& r) { return l.val() < r.val(); } +bool operator<(const ScopeGuard& l, const ScopeGuard& r) { return l.val() < r.val(); } + +#endif //BOOST_OPTIONAL_TEST_TESTABKE_CLASSES_AK_07JAN2015_HPP diff --git a/libs/range/.gitattributes b/libs/range/.gitattributes new file mode 100644 index 00000000..3e84d7c7 --- /dev/null +++ b/libs/range/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain diff --git a/libs/range/.travis.yml b/libs/range/.travis.yml new file mode 100644 index 00000000..dcfdd499 --- /dev/null +++ b/libs/range/.travis.yml @@ -0,0 +1,151 @@ +# Copyright 2016, 2017 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +language: cpp + +sudo: false + +python: "2.7" + +branches: + only: + - master + - develop + - /feature\/.*/ + +env: + matrix: + - BOGUS_JOB=true + +matrix: + + exclude: + - env: BOGUS_JOB=true + + include: + - os: linux + compiler: g++ + env: TOOLSET=gcc CXXSTD=03,11 + + - os: linux + compiler: g++-4.4 + env: TOOLSET=gcc-4.4 CXXSTD=98,0x + addons: + apt: + packages: + - g++-4.4 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-4.6 + env: TOOLSET=gcc-4.6 CXXSTD=03,0x + addons: + apt: + packages: + - g++-4.6 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-5 + env: TOOLSET=gcc-5 CXXSTD=03,11 + addons: + apt: + packages: + - g++-5 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-5 + env: TOOLSET=gcc-5 CXXSTD=14,1z + addons: + apt: + packages: + - g++-5 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-6 + env: TOOLSET=gcc-6 CXXSTD=03,11 + addons: + apt: + packages: + - g++-6 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-6 + env: TOOLSET=gcc-6 CXXSTD=14,1z + addons: + apt: + packages: + - g++-6 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-7 + env: TOOLSET=gcc-7 CXXSTD=03,11 + addons: + apt: + packages: + - g++-7 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-7 + env: TOOLSET=gcc-7 CXXSTD=14,17 + addons: + apt: + packages: + - g++-7 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++ + env: TOOLSET=clang CXXSTD=03,11 + + - os: linux + compiler: clang++ + env: TOOLSET=clang CXXSTD=14,1z + addons: + apt: + packages: + - libstdc++-4.9-dev + sources: + - ubuntu-toolchain-r-test + + - os: osx + compiler: clang++ + env: TOOLSET=clang CXXSTD=03,11 + + - os: osx + compiler: clang++ + env: TOOLSET=clang CXXSTD=14,1z + +install: + - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true + - cd .. + - git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root + - cd boost-root + - git submodule update --init tools/build + - git submodule update --init libs/config + - git submodule update --init tools/boostdep + - cp -r $TRAVIS_BUILD_DIR/* libs/range + - python tools/boostdep/depinst/depinst.py range + - ./bootstrap.sh + - ./b2 headers + +script: + - ./b2 -j 3 libs/range/test toolset=$TOOLSET cxxstd=$CXXSTD + +notifications: + email: + on_success: always diff --git a/libs/range/CMakeLists.txt b/libs/range/CMakeLists.txt new file mode 100644 index 00000000..57102f40 --- /dev/null +++ b/libs/range/CMakeLists.txt @@ -0,0 +1,41 @@ +# Generated by `boostdep --cmake range` +# Copyright 2020 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.5...3.16) + +project(boost_range VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) + +add_library(boost_range INTERFACE) +add_library(Boost::range ALIAS boost_range) + +target_include_directories(boost_range INTERFACE include) + +target_link_libraries(boost_range + INTERFACE + Boost::array + Boost::assert + Boost::concept_check + Boost::config + Boost::container_hash + Boost::conversion + Boost::core + Boost::detail + Boost::iterator + Boost::mpl + Boost::optional + Boost::preprocessor + Boost::regex + Boost::static_assert + Boost::tuple + Boost::type_traits + Boost::utility +) + +if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") + + add_subdirectory(test) + +endif() + diff --git a/libs/range/doc/Jamfile.v2 b/libs/range/doc/Jamfile.v2 new file mode 100644 index 00000000..c5071808 --- /dev/null +++ b/libs/range/doc/Jamfile.v2 @@ -0,0 +1,35 @@ +#// Boost.Range library +#// +#// Copyright Thorsten Ottosen 2003-2008. Use, modification and +#// distribution is subject to 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) +#// +#// For more information, see http://www.boost.org/libs/range/ +#// + +project boost/libs/range/doc ; +using boostbook ; +using quickbook ; + +path-constant images_location : html ; + +boostbook quickbook + : + boost_range.qbk + : + boost.root=../../../.. + chunk.section.depth=4 + chunk.first.sections=1 + toc.section.depth=3 + toc.max.depth=3 + generate.section.toc.level=4 + pdf:boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html + pdf:img.src.path=$(images_location)/ + ; + +############################################################################### +alias boostdoc ; +explicit boostdoc ; +alias boostrelease : quickbook ; +explicit boostrelease ; diff --git a/libs/range/doc/boost_range.qbk b/libs/range/doc/boost_range.qbk new file mode 100644 index 00000000..d509fb99 --- /dev/null +++ b/libs/range/doc/boost_range.qbk @@ -0,0 +1,199 @@ +[/============================================================================== + Copyright (C) 2003-2010 Thorsten Ottosen, Neil Groves + + Use, modification and distribution is subject to 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 +==============================================================================/] +[library Range + [quickbook 1.5] + [version 2.0] + [authors [Ottosen, Thorsten], [Groves, Neil]] + [copyright 2003-2010 Thorsten Ottosen, Neil Groves] + [purpose Half-open range library] + [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]) + ] +] + +[/ Converted to Quickbook format by Darren Garvey, 2007] + +[def __note__ [$images/note.png]] +[def __alert__ [$images/alert.png]] +[def __tip__ [$images/tip.png]] +[def __caution__ [$images/caution.png]] + +[def __boost_range_home__ [link range Boost.Range]] +[def __ranges__ [link range.concepts Ranges]] +[def __range_concepts__ [link range.concepts Range concepts]] +[def __forward_range__ [link range.concepts.forward_range Forward Range]] +[def __single_pass_range__ [link range.concepts.single_pass_range Single Pass Range]] +[def __bidirectional_range__ [link range.concepts.bidirectional_range Bidirectional Range]] +[def __random_access_range__ [link range.concepts.random_access_range Random Access Range]] + +[def __iterator_range__ [link range.reference.utilities.iterator_range `iterator_range`]] +[def __sub_range__ [link range.reference.utilities.sub_range `sub_range`]] +[def __minimal_interface__ [link range.reference.extending minimal interface]] +[def __range_result_iterator__ [link range.reference.concept_implementation.semantics.metafunctions `range_result_iterator`]] +[def __extending_for_udts__ [link range.reference.extending Extending the library for UDTs]] +[def __implementation_of_metafunctions__ [link range.reference.concept_implementation.semantics.metafunctions Implementation of metafunctions]] +[def __implementation_of_functions__ [link range.reference.concept_implementation.semantics.functions Implementation of functions]] + +[def __range_value__ [link range.reference.concept_implementation.semantics.metafunctions `range_value`]] +[def __range_iterator__ [link range.reference.concept_implementation.semantics.metafunctions `range_iterator`]] +[def __range_difference__ [link range.reference.concept_implementation.semantics.metafunctions `range_difference`]] +[def __range_pointer__ [link range.reference.concept_implementation.semantics.metafunctions `range_pointer`]] +[def __range_category__ [link range.reference.concept_implementation.semantics.metafunctions `range_category`]] +[def __range_reverse_iterator__ [link range.reference.concept_implementation.semantics.metafunctions `range_reverse_iterator`]] +[def __begin__ [link range.reference.concept_implementation.semantics.functions `begin`]] +[def __const_begin__ [link range.reference.concept_implementation.semantics.functions `const_begin`]] +[def __end__ [link range.reference.concept_implementation.semantics.functions `end`]] +[def __const_end__ [link range.reference.concept_implementation.semantics.functions `const_end`]] +[def __empty__ [link range.reference.concept_implementation.semantics.functions `empty`]] +[def __distance__ [link range.reference.concept_implementation.semantics.functions `distance`]] +[def __size__ [link range.reference.concept_implementation.semantics.functions `size`]] +[def __rbegin__ [link range.reference.concept_implementation.semantics.functions `rbegin`]] +[def __const_rbegin__ [link range.reference.concept_implementation.semantics.functions `const_rbegin`]] +[def __rend__ [link range.reference.concept_implementation.semantics.functions `rend`]] +[def __const_rend__ [link range.reference.concept_implementation.semantics.functions `const_rend`]] +[def __as_array__ [link range.reference.concept_implementation.semantics.functions `as_array`]] +[def __as_literal__ [link range.reference.concept_implementation.semantics.functions `as_literal`]] +[def __counting_range__ [link range.reference.ranges.counting_range `counting_range`]] +[def __irange__ [link range.reference.ranges.irange `irange`]] +[def __istream_range__ [link range.reference.ranges.istream_range `istream_range`]] +[def __combine__ [link range.reference.utilities.combine `combine`]] +[def __join__ [link range.reference.utilities.join `join`]] + +[def __range_adaptors__ [link range.reference.adaptors Range adaptors]] +[def __range_adaptors_adjacent_filtered__ [link range.reference.adaptors.reference.adjacent_filtered adjacent_filtered]] +[def __range_adaptors_copied__ [link range.reference.adaptors.reference.copied copied]] +[def __range_adaptors_filtered__ [link range.reference.adaptors.reference.filtered filtered]] +[def __range_adaptors_formatted__ [link.range.reference.adaptors.reference.formatted formatted]] +[def __range_adaptors_indexed__ [link range.reference.adaptors.reference.indexed indexed]] +[def __range_adaptors_indirected__ [link range.reference.adaptors.reference.indirected indirected]] +[def __range_adaptors_map_keys__ [link range.reference.adaptors.reference.map_keys map_keys]] +[def __range_adaptors_map_values__ [link range.reference.adaptors.reference.map_values map_values]] +[def __range_adaptors_replaced__ [link range.reference.adaptors.reference.replaced replaced]] +[def __range_adaptors_replaced_if__ [link range.reference.adaptors.reference.replaced_if replaced_if]] +[def __range_adaptors_reversed__ [link range.reference.adaptors.reference.reversed reversed]] +[def __range_adaptors_sliced__ [link range.reference.adaptors.reference.sliced sliced]] +[def __range_adaptors_strided__ [link range.reference.adaptors.reference.strided strided]] +[def __range_adaptors_type_erased__ [link range.reference.adaptors.reference.type_erased type_erased]] +[def __range_adaptors_tokenized__ [link range.reference.adaptors.reference.tokenized tokenized]] +[def __range_adaptors_transformed__ [link range.reference.adaptors.reference.transformed transformed]] +[def __range_adaptors_uniqued__ [link range.reference.adaptors.reference.uniqued uniqued]] + + +[def __range_algorithms__ [link range.reference.algorithms Range algorithms]] +[def __range_algorithms_adjacent_find__ [link range.reference.algorithms.non_mutating.adjacent_find adjacent_find]] +[def __range_algorithms_binary_search__ [link range.reference.algorithms.non_mutating.binary_search binary_search]] +[def __range_algorithms_count__ [link range.reference.algorithms.non_mutating.count count]] +[def __range_algorithms_count_if__ [link range.reference.algorithms.non_mutating.count_if count_if]] +[def __range_algorithms_equal__ [link range.reference.algorithms.non_mutating.equal equal]] +[def __range_algorithms_equal_range__ [link range.reference.algorithms.non_mutating.equal_range equal_range]] +[def __range_algorithms_for_each__ [link range.reference.algorithms.non_mutating.for_each for_each]] +[def __range_algorithms_find__ [link range.reference.algorithms.non_mutating.find find]] +[def __range_algorithms_find_end__ [link range.reference.algorithms.non_mutating.find_end find_end]] +[def __range_algorithms_find_first_of__ [link range.reference.algorithms.non_mutating.find_first_of find_first_of]] +[def __range_algorithms_find_if__ [link range.reference.algorithms.non_mutating.find_if find_if]] +[def __range_algorithms_lexicographical_compare__ [link range.reference.algorithms.non_mutating.lexicographical_compare lexicographical_compare]] +[def __range_algorithms_lower_bound__ [link range.reference.algorithms.non_mutating.lower_bound lower_bound]] +[def __range_algorithms_max_element__ [link range.reference.algorithms.non_mutating.max_element max_element]] +[def __range_algorithms_min_element__ [link range.reference.algorithms.non_mutating.min_element min_element]] +[def __range_algorithms_mismatch__ [link range.reference.algorithms.non_mutating.mismatch mismatch]] +[def __range_algorithms_search__ [link range.reference.algorithms.non_mutating.search search]] +[def __range_algorithms_search_n__ [link range.reference.algorithms.non_mutating.search_n search_n]] +[def __range_algorithms_upper_bound__ [link range.reference.algorithms.non_mutating.upper_bound upper_bound]] + +[def __range_algorithms_copy__ [link range.reference.algorithms.mutating.copy copy]] +[def __range_algorithms_copy_backward__ [link range.reference.algorithms.mutating.copy_backward copy_backward]] +[def __range_algorithms_fill__ [link range.reference.algorithms.mutating.fill fill]] +[def __range_algorithms_fill_n__ [link range.reference.algorithms.mutating.fill_n fill_n]] +[def __range_algorithms_generate__ [link range.reference.algorithms.mutating.generate generate]] +[def __range_algorithms_inplace_merge__ [link range.reference.algorithms.mutating.inplace_merge inplace_merge]] +[def __range_algorithms_merge__ [link range.reference.algorithms.mutating.merge merge]] +[def __range_algorithms_nth_element__ [link range.reference.algorithms.mutating.nth_element nth_element]] +[def __range_algorithms_partial_sort__ [link range.reference.algorithms.mutating.partial_sort partial_sort]] +[def __range_algorithms_partition__ [link range.reference.algorithms.mutating.partition partition]] +[def __range_algorithms_random_shuffle__ [link range.reference.algorithms.mutating.random_shuffle random_shuffle]] +[def __range_algorithms_remove__ [link range.reference.algorithms.mutating.remove remove]] +[def __range_algorithms_remove_copy__ [link range.reference.algorithms.mutating.remove_copy remove_copy]] +[def __range_algorithms_remove_copy_if__ [link range.reference.algorithms.mutating.remove_copy_if remove_copy_if]] +[def __range_algorithms_remove_if__ [link range.reference.algorithms.mutating.remove_if remove_if]] +[def __range_algorithms_replace__ [link range.reference.algorithms.mutating.replace replace]] +[def __range_algorithms_replace_copy__ [link range.reference.algorithms.mutating.replace_copy replace_copy]] +[def __range_algorithms_replace_copy_if__ [link range.reference.algorithms.mutating.replace_copy_if replace_copy_if]] +[def __range_algorithms_replace_if__ [link range.reference.algorithms.mutating.replace_if replace_if]] +[def __range_algorithms_reverse__ [link range.reference.algorithms.mutating.reverse reverse]] +[def __range_algorithms_reverse_copy__ [link range.reference.algorithms.mutating.reverse_copy reverse_copy]] +[def __range_algorithms_rotate__ [link range.reference.algorithms.mutating.rotate rotate]] +[def __range_algorithms_rotate_copy__ [link range.reference.algorithms.mutating.rotate_copy rotate_copy]] +[def __range_algorithms_sort__ [link range.reference.algorithms.mutating.sort sort]] +[def __range_algorithms_stable_partition__ [link range.reference.algorithms.mutating.stable_partition stable_partition]] +[def __range_algorithms_stable_sort__ [link range.reference.algorithms.mutating.stable_sort stable_sort]] +[def __range_algorithms_swap_ranges__ [link range.reference.algorithms.mutating.swap_ranges swap_ranges]] +[def __range_algorithms_transform__ [link range.reference.algorithms.mutating.transform transform]] +[def __range_algorithms_unique__ [link range.reference.algorithms.mutating.unique unique]] +[def __range_algorithms_unique_copy__ [link range.reference.algorithms.mutating.unique_copy unique_copy]] + +[def __range_algorithms_includes__ [link range.reference.algorithms.set.includes includes]] +[def __range_algorithms_set_union__ [link range.reference.algorithms.set.set_union set_union]] +[def __range_algorithms_set_intersection__ [link range.reference.algorithms.set.set_intersection set_intersection]] +[def __range_algorithms_set_difference__ [link range.reference.algorithms.set.set_difference set_difference]] +[def __range_algorithms_set_symmetric_difference__ [link range.reference.algorithms.set.set_symmetric_difference set_symmetric_difference]] + +[def __range_algorithms_push_heap__ [link range.reference.algorithms.heap.push_heap push_heap]] +[def __range_algorithms_pop_heap__ [link range.reference.algorithms.heap.pop_heap pop_heap]] +[def __range_algorithms_make_heap__ [link range.reference.algorithms.heap.make_heap make_heap]] +[def __range_algorithms_sort_heap__ [link range.reference.algorithms.heap.sort_heap sort_heap]] + +[def __range_algorithms_next_permutation__ [link range.reference.algorithms.permutation.next_permutation next_permutation]] +[def __range_algorithms_prev_permutation__ [link range.reference.algorithms.permutation.prev_permutation prev_permutation]] + +[def __range_algorithm_ext_copy_n__ [link range.reference.algorithms.new.copy_n copy_n]] +[def __range_algorithm_ext_erase__ [link range.reference.algorithms.new.erase erase]] +[def __range_algorithm_ext_for_each__ [link range.reference.algorithms.new.for_each for_each]] +[def __range_algorithm_ext_insert__ [link range.reference.algorithms.new.insert insert]] +[def __range_algorithm_ext_iota__ [link range.reference.algorithms.new.iota iota]] +[def __range_algorithm_ext_is_sorted__ [link range.reference.algorithms.new.is_sorted is_sorted]] +[def __range_algorithm_ext_overwrite__ [link range.reference.algorithms.new.overwrite overwrite]] +[def __range_algorithm_ext_push_back__ [link range.reference.algorithms.new.push_back push_back]] +[def __range_algorithm_ext_push_front__ [link range.reference.algorithms.new.push_front push_front]] + +[def __single_pass_iterator__ [@boost:/libs/iterator/doc/new-iter-concepts.html#singls-pass-iterators-lib-single-pass-iterators Single Pass Iterator]] +[def __forward_traversal_iterator__ [@boost:/libs/iterator/doc/new-iter-concepts.html#forward-traversal-iterators-lib-forward-traversal-iterators Forward Traversal Iterator]] +[def __bidirectional_traversal_iterator__ [@boost:/libs/iterator/doc/new-iter-concepts.html#bidirectional-traversal-iterators-lib-bidirectional-traversal-iterators Bidirectional Traversal Iterator]] +[def __random_access_traversal_iterator__ [@boost:/libs/iterator/doc/new-iter-concepts.html#random-access-traversal-iterators-lib-random-access-traversal-iterators Random Access Traversal Iterator]] +[def __new_style_iterators__ [@boost:/libs/iterator/doc/new-iter-concepts.html new style iterators]] +[def __iterator_concepts__ [@boost:/libs/iterator/doc/iterator_concepts.html Iterator concepts]] + +[def __container__ [@http://www.sgi.com/Technology/STL/Container.html Container]] +[def __metafunctions__ [@boost:/libs/mpl/doc/refmanual/metafunction.html metafunctions]] +[def __concept_check__ [@boost:/libs/concept_check/index.html Boost Concept Check library]] +[def __boost_array__ [@boost:/libs/array/index.html boost::array]] +[def __the_forwarding_problem__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm The Forwarding Problem]] + +[def __sgi_inner_product__ [@http://www.sgi.com/tech/stl/inner_product.html inner_product]] +[def __sgi_partial_sum__ [@http://www.sgi.com/tech/stl/partial_sum.html partial_sum]] +[def __type_erasure_article__ [@http://www.artima.com/cppsource/type_erasure.html type erasure article]] + +Boost.Range is a collection of concepts and utilities, range-based algorithms, +as well as range adaptors that allow for efficient and expressive code. + +Using Boost.Range inplace of the standard library alternatives results in more +readable code and in many cases greater efficiency. + +[include introduction.qbk] +[include concepts.qbk] +[include reference.qbk] +[include style.qbk] +[include headers.qbk] +[include examples.qbk] +[include mfc_atl.qbk] +[include upgrade.qbk] +[include portability.qbk] +[include faq.qbk] +[include history_ack.qbk] + diff --git a/libs/range/doc/concepts.qbk b/libs/range/doc/concepts.qbk new file mode 100644 index 00000000..e0b5f414 --- /dev/null +++ b/libs/range/doc/concepts.qbk @@ -0,0 +1,255 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:concepts Range Concepts] + +[section Overview] + +A Range is a [*/concept/] similar to the STL [@http://www.sgi.com/tech/stl/Container.html Container] concept. A Range provides iterators for accessing a half-open range `[first,one_past_last)` of elements and provides information about the number of elements in the Range. However, a Range has fewer requirements than a Container. + +The motivation for the Range concept is that there are many useful Container-like types that do not meet the full requirements of Container, and many algorithms that can be written with this reduced set of requirements. In particular, a Range does not necessarily + +* own the elements that can be accessed through it, +* have copy semantics, + +Because of the second requirement, a Range object must be passed by (const or non-const) reference in generic code. + +The operations that can be performed on a Range is dependent on the [@boost:/libs/iterator/doc/new-iter-concepts.html#iterator-traversal-concepts-lib-iterator-traversal traversal category] of the underlying iterator type. Therefore the range concepts are named to reflect which traversal category its iterators support. See also terminology and style guidelines. for more information about naming of ranges. + +The concepts described below specifies associated types as [@boost:/libs/mpl/doc/refmanual/metafunction.html metafunctions] and all functions as free-standing functions to allow for a layer of indirection. + +[endsect] + + +[section Single Pass Range] + +[heading Notation] + +[table + [] + [[`X`] [A type that is a model of __single_pass_range__.]] + [[`a`] [Object of type X.]] +] + +[heading Description] + +A range `X` where `boost::range_iterator::type` is a model of __single_pass_iterator__. + +[heading Associated types] + +[table + [] + [[Iterator type ] [`boost::range_iterator::type` ] [The type of iterator used to iterate through a Range's elements. The iterator's value type is expected to be the Range's value type. A conversion from the iterator type to the `const` iterator type must exist.]] + [[Const iterator type] [`boost::range_iterator::type`] [A type of iterator that may be used to examine, but not to modify, a Range's elements.]] +] + +[heading Valid expressions] + +The following expressions must be valid. + +[table + [[Name ] [Expression ] [Return type ]] + [[Beginning of range] [`boost::begin(a)`] [`boost::range_iterator::type` if `a` is mutable, `boost::range_iterator::type` otherwise]] + [[End of range ] [`boost::end(a)` ] [`boost::range_iterator::type` if `a` is mutable, `boost::range_iterator::type` otherwise]] +] + +[heading Expression semantics] + +[table + [[Expression ] [Semantics ] [Postcondition]] + [[`boost::begin(a)`] [Returns an iterator pointing to the first element in the Range. ] [`boost::begin(a)` is either dereferenceable or past-the-end. It is past-the-end if and only if `boost::distance(a) == 0`.]] + [[`boost::end(a)` ] [Returns an iterator pointing one past the last element in the Range. ] [`boost::end(a)` is past-the-end.]] +] + +[heading Complexity guarantees] + +`boost::end(a)` is at most amortized linear time, `boost::begin(a)` is amortized constant time. For most practical purposes, one can expect both to be amortized constant time. + +[heading Invariants] + +[table + [] + [[Valid range ] [For any Range `a`, `[boost::begin(a),boost::end(a))` is a valid range, that is, `boost::end(a)` is reachable from `boost::begin(a)` in a finite number of increments.]] + + [[Completeness] [An algorithm that iterates through the range `[boost::begin(a),boost::end(a))` will pass through every element of `a`.]] +] + +[heading See also] + +__extending_for_udts__ + +__implementation_of_metafunctions__ + +__implementation_of_functions__ + +__container__ + +[endsect] + + +[section Forward Range] + +[heading Notation] + +[table + [] + [[`X`] [A type that is a model of __forward_range__.]] + [[`a`] [Object of type X.]] +] + +[heading Description] + +A range `X` where `boost::range_iterator::type` is a model of __forward_traversal_iterator__. + +[heading Refinement of] + +__single_pass_range__ + +[heading Associated types] + +[table + [] + [[Distance type] [`boost::range_difference::type`] [A signed integral type used to represent the distance between two of the Range's iterators. This type must be the same as the iterator's distance type.]] + [[Size type ] [`boost::range_size::type` ] [An unsigned integral type that can represent any nonnegative value of the Range's distance type.]] +] + +[heading See also] + +__implementation_of_metafunctions__ + +__implementation_of_functions__ + +[endsect] + + +[section Bidirectional Range] + +[heading Notation] + +[table + [] + [[`X`] [A type that is a model of __bidirectional_range__.]] + [[`a`] [Object of type X.]] +] + +[heading Description] + +This concept provides access to iterators that traverse in both directions (forward and reverse). The `boost::range_iterator::type` iterator must meet all of the requirements of __bidirectional_traversal_iterator__. + +[heading Refinement of] + +__forward_range__ + +[heading Associated types] + +[table + [] + [[Reverse Iterator type ] [`boost::range_reverse_iterator::type` ] [The type of iterator used to iterate through a Range's elements in reverse order. The iterator's value type is expected to be the Range's value type. A conversion from the reverse iterator type to the const reverse iterator type must exist.]] + + [[Const reverse iterator type] [`boost::range_reverse_iterator::type`] [A type of reverse iterator that may be used to examine, but not to modify, a Range's elements.]] +] + +[heading Valid expressions] + +[table + [[Name ] [Expression ] [Return type] [Semantics]] + [[Beginning of range] [`boost::rbegin(a)`] [`boost::range_reverse_iterator::type` if `a` is mutable `boost::range_reverse_iterator::type` otherwise.] [Equivalent to `boost::range_reverse_iterator::type(boost::end(a))`.]] + + [[End of range ] [`boost::rend(a)` ] [`boost::range_reverse_iterator::type` if `a` is mutable, `boost::range_reverse_iterator::type` otherwise.] [Equivalent to `boost::range_reverse_iterator::type(boost::begin(a))`.]] +] + +[heading Complexity guarantees] + +`boost::rbegin(a)` has the same complexity as `boost::end(a)` and `boost::rend(a)` has the same complexity as `boost::begin(a)` from __forward_range__. + +[heading Invariants] + +[table + [] + [[Valid reverse range] [For any Bidirectional Range a, `[boost::rbegin(a),boost::rend(a))` is a valid range, that is, `boost::rend(a)` is reachable from `boost::rbegin(a)` in a finite number of increments.]] + + [[Completeness ] [An algorithm that iterates through the range `[boost::rbegin(a),boost::rend(a))` will pass through every element of `a`.]] +] + +[heading See also] + +__implementation_of_metafunctions__ + +__implementation_of_functions__ + +[endsect] + + +[section Random Access Range] + +[heading Description] + +A range `X` where `boost::range_iterator::type` is a model of __random_access_traversal_iterator__. + +[heading Refinement of] + +__bidirectional_range__ + +[heading Valid expressions] + +[table + [[Name ] [Expression ] [Return type ]] + [[Size of range] [`boost::size(a)`] [`boost::range_size::type`]] +] + +[heading Expression semantics] + +[table + [[Expression ] [Semantics] [Postcondition]] + [[`boost::size(a)`] [Returns the size of the Range, that is, its number of elements. Note `boost::size(a) == 0u` is equivalent to `boost::empty(a)`.] [`boost::size(a) >= 0`]] +] + +[heading Complexity guarantees] + +`boost::size(a)` completes in amortized constant time. + +[heading Invariants] + +[table + [] + [[Range size] [`boost::size(a)` is equal to the `boost::end(a)` - `boost::begin(a)`.]] +] + +[endsect] + + +[section Concept Checking] + +Each of the range concepts has a corresponding concept checking class in the file [@boost:/boost/range/concepts.hpp ``]. These classes may be used in conjunction with the __concept_check__ to ensure that the type of a template parameter is compatible with a range concept. If not, a meaningful compile time error is generated. Checks are provided for the range concepts related to iterator traversal categories. For example, the following line checks that the type `T` models the __forward_range__ concept. + +`` +BOOST_CONCEPT_ASSERT(( ForwardRangeConcept )); +`` + +An additional concept check is required for the value access property of the range based on the range's iterator type. For example to check for a ForwardReadableRange, the following code is required. + +`` +BOOST_CONCEPT_ASSERT(( ForwardRangeConcept )); +BOOST_CONCEPT_ASSERT(( ReadableIteratorConcept::type> )); +`` + +The following range concept checking classes are provided. + +* Class SinglePassRangeConcept checks for __single_pass_range__ +* Class ForwardRangeConcept checks for __forward_range__ +* Class BidirectionalRangeConcept checks for __bidirectional_range__ +* Class RandomAccessRangeConcept checks for __random_access_range__ + +[heading See also] + +[link range.style_guide Range Terminology and style guidelines] + +__iterator_concepts__ + +__concept_check__ + +[endsect] +[endsect] + diff --git a/libs/range/doc/example.cpp b/libs/range/doc/example.cpp new file mode 100644 index 00000000..d3dec7cb --- /dev/null +++ b/libs/range/doc/example.cpp @@ -0,0 +1,151 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2008. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include // for std::iterator_traits, std::distance() + +namespace Foo +{ + // + // Our sample UDT. A 'Pair' + // will work as a range when the stored + // elements are iterators. + // + template< class T > + struct Pair + { + T first, last; + }; + +} // namespace 'Foo' + +namespace boost +{ + // + // Specialize metafunctions. We must include the range.hpp header. + // We must open the 'boost' namespace. + // + /* + template< class T > + struct range_value< Foo::Pair > + { + typedef typename std::iterator_traits::value_type type; + }; + */ + + template< class T > + struct range_iterator< Foo::Pair > + { + typedef T type; + }; + + template< class T > + struct range_const_iterator< Foo::Pair > + { + // + // Remark: this is defined similar to 'range_iterator' + // because the 'Pair' type does not distinguish + // between an iterator and a const_iterator. + // + typedef T type; + }; + + /* + template< class T > + struct range_difference< Foo::Pair > + { + typedef typename std::iterator_traits::difference_type type; + }; + */ + + template< class T > + struct range_size< Foo::Pair > + { + int static_assertion[ sizeof( std::size_t ) >= + sizeof( typename range_difference< Foo::Pair >::type ) ]; + typedef std::size_t type; + }; + +} // namespace 'boost' + +namespace Foo +{ + // + // The required functions. These should be defined in + // the same namespace as 'Pair', in this case + // in namespace 'Foo'. + // + + template< class T > + inline T boost_range_begin( Pair& x ) + { + return x.first; + } + + template< class T > + inline T boost_range_begin( const Pair& x ) + { + return x.first; + } + + template< class T > + inline T boost_range_end( Pair& x ) + { + return x.last; + } + + template< class T > + inline T boost_range_end( const Pair& x ) + { + return x.last; + } + + template< class T > + inline typename boost::range_size< Pair >::type + boost_range_size( const Pair& x ) + { + return std::distance(x.first,x.last); + } + +} // namespace 'Foo' + +#include + +int main() +{ + typedef std::vector::iterator iter; + std::vector vec; + vec.push_back( 42 ); + Foo::Pair pair = { vec.begin(), vec.end() }; + const Foo::Pair& cpair = pair; + // + // Notice that we call 'begin' etc with qualification. + // + iter i = boost::begin( pair ); + iter e = boost::end( pair ); + i = boost::begin( cpair ); + e = boost::end( cpair ); + boost::range_size< Foo::Pair >::type s = boost::size( pair ); + s = boost::size( cpair ); + boost::range_const_reverse_iterator< Foo::Pair >::type + ri = boost::rbegin( cpair ), + re = boost::rend( cpair ); + + // + // Test metafunctions + // + + boost::range_value< Foo::Pair >::type + v = *boost::begin(pair); + + boost::range_difference< Foo::Pair >::type + d = boost::end(pair) - boost::begin(pair); +} + diff --git a/libs/range/doc/examples.qbk b/libs/range/doc/examples.qbk new file mode 100644 index 00000000..1dfb9242 --- /dev/null +++ b/libs/range/doc/examples.qbk @@ -0,0 +1,28 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:examples Examples] + +Some examples are given in the accompanying test files: + +* [@http://www.boost.org/libs/range/test/string.cpp string.cpp] shows how to implement a container version of `std::find()` that works with `char[]`,`wchar_t[]`,`char*`,`wchar_t*`. + +* [@http://www.boost.org/libs/range/test/algorithm_example.cpp algorithm_example.cpp] shows the replace example from the introduction. + +* [@http://www.boost.org/libs/range/test/iterator_range.cpp iterator_range.cpp] + +* [@http://www.boost.org/libs/range/test/sub_range.cpp sub_range.cpp] + +* [@http://www.boost.org/libs/range/test/iterator_pair.cpp iterator_pair.cpp] + +* [@http://www.boost.org/libs/range/test/reversible_range.cpp reversible_range.cpp] + +* [@http://www.boost.org/libs/range/test/std_container.cpp std_container.cpp] + +* [@http://www.boost.org/libs/range/test/array.cpp array.cpp] + +[endsect] + + diff --git a/libs/range/doc/faq.qbk b/libs/range/doc/faq.qbk new file mode 100644 index 00000000..ada63615 --- /dev/null +++ b/libs/range/doc/faq.qbk @@ -0,0 +1,30 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:faq FAQ] + +1. ['[*Why is there no difference between `range_iterator::type` and `range_const_iterator::type` for `std::pair`?]] + +[:In general it is not possible nor desirable to find a corresponding `const_iterator`. When it is possible to come up with one, the client might choose to construct a `std::pair` object.] + +[:Note that an __iterator_range__ is somewhat more convenient than a `pair` and that a __sub_range__ does propagate const-ness.] + +2. ['[*Why is there not supplied more types or more functions?]] + +[:The library has been kept small because its current interface will serve most purposes. If and when a genuine need arises for more functionality, it can be implemented.] + +3. ['[*How should I implement generic algorithms for ranges?]] + +[:One should always start with a generic algorithm that takes two iterators (or more) as input. Then use Boost.Range to build handier versions on top of the iterator based algorithm. Please notice that once the range version of the algorithm is done, it makes sense not to expose the iterator version in the public interface.] + +4. ['[*Why is there no Incrementable Range concept?]] + +[:Even though we speak of incrementable iterators, it would not make much sense for ranges; for example, we cannot determine the size and emptiness of a range since we cannot even compare its iterators.] + +[:Note also that incrementable iterators are derived from output iterators and so there exist no output range.] + +[endsect] + + diff --git a/libs/range/doc/headers.qbk b/libs/range/doc/headers.qbk new file mode 100644 index 00000000..2e5ae02f --- /dev/null +++ b/libs/range/doc/headers.qbk @@ -0,0 +1,143 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:headers Library Headers] + +[section:general General] +[table + [[Header ] [Includes ] [Related Concept ]] + [[`` ] [everything from Boost.Range version 1 (Boost versions 1.42 and below). Includes the core range functions and metafunctions, but excludes Range Adaptors and Range Algorithms. ] [- ]] + [[`` ] [every metafunction ] [- ]] + [[`` ] [every function ] [- ]] + [[`` ] [__range_value__ ] [__single_pass_range__ ]] + [[`` ] [__range_iterator__ ] [__single_pass_range__ ]] + [[`` ] [__range_difference__ ] [__forward_range__ ]] + [[`` ] [__range_pointer__ ] [-]] + [[`` ] [__range_category__ ] [-]] + [[``] [__range_reverse_iterator__ ] [__bidirectional_range__ ]] + [[`` ] [__begin__ and __const_begin__ ] [__single_pass_range__ ]] + [[`` ] [__end__ and __const_end__ ] [__single_pass_range__ ]] + [[`` ] [__empty__ ] [__single_pass_range__ ]] + [[`` ] [__distance__ ] [__forward_range__ ]] + [[`` ] [__size__ ] [__random_access_range__ ]] + [[`` ] [__rbegin__ and __const_rbegin__] [__bidirectional_range__ ]] + [[`` ] [__rend__ and __const_rend__ ] [__bidirectional_range__ ]] + [[`` ] [__as_array__ ] [- ]] + [[`` ] [__as_literal__ ] [- ]] + [[`` ] [__iterator_range__ ] [- ]] + [[`` ] [__sub_range__ ] [- ]] + [[`` ] [__range_concepts__ ] [- ]] + [[`` ] [every range adaptor ] [- ]] + [[`` ] [every range equivalent of an STL algorithm ] [- ]] + [[`` ] [every range algorithm that is an extension of the STL algorithms ] [- ]] + [[`` ] [ __counting_range__ ] [-]] + [[`` ] [ __istream_range__ ] [-]] + [[`` ] [ __irange__ ] [-]] + [[`` ] [ __join__ ] [-]] +] +[endsect] + +[section:adaptors Adaptors] +[table + [[Header ][Includes ]] + [[``] [__range_adaptors_adjacent_filtered__ ]] + [[``] [__range_adaptors_copied__]] + [[``] [__range_adaptors_filtered__]] + [[``] [__range_adaptors_indexed__]] + [[``] [__range_adaptors_indirected__]] + [[``] [__range_adaptors_map_keys__ __range_adaptors_map_values__]] + [[``] [__range_adaptors_replaced__]] + [[``] [__range_adaptors_replaced_if__]] + [[``] [__range_adaptors_reversed__]] + [[``] [__range_adaptors_sliced__]] + [[``] [__range_adaptors_strided__]] + [[``] [__range_adaptors_tokenized__]] + [[``] [__range_adaptors_transformed__]] + [[``] [__range_adaptors_uniqued__]] +] +[endsect] + +[section:algorithm Algorithm] +[table + [[Header ][Includes ]] + [[``] [__range_algorithms_adjacent_find__]] + [[``] [__range_algorithms_binary_search__]] + [[``] [__range_algorithms_copy__]] + [[``] [__range_algorithms_copy_backward__]] + [[``] [__range_algorithms_count__]] + [[``] [__range_algorithms_count_if__]] + [[``] [__range_algorithms_equal__]] + [[``] [__range_algorithms_equal_range__]] + [[``] [__range_algorithms_fill__]] + [[``] [__range_algorithms_fill_n__]] + [[``] [__range_algorithms_find__]] + [[``] [__range_algorithms_find_end__]] + [[``] [__range_algorithms_find_first_of__]] + [[``] [__range_algorithms_find_if__]] + [[``] [__range_algorithms_for_each__]] + [[``] [__range_algorithms_generate__]] + [[``] [__range_algorithms_push_heap__ + __range_algorithms_pop_heap__ + __range_algorithms_make_heap__ + __range_algorithms_sort_heap__]] + [[``] [__range_algorithms_inplace_merge__]] + [[``] [__range_algorithms_lexicographical_compare__]] + [[``] [__range_algorithms_lower_bound__]] + [[``] [__range_algorithms_max_element__]] + [[``] [__range_algorithms_merge__]] + [[``] [__range_algorithms_min_element__]] + [[``] [__range_algorithms_mismatch__]] + [[``] [__range_algorithms_nth_element__]] + [[``] [__range_algorithms_partial_sort__]] + [[``] [__range_algorithms_partition__]] + [[``] [__range_algorithms_next_permutation__ + __range_algorithms_prev_permutation__]] + [[``] [__range_algorithms_random_shuffle__]] + [[``] [__range_algorithms_remove__]] + [[``] [__range_algorithms_remove_copy__]] + [[``] [__range_algorithms_remove_copy_if__]] + [[``] [__range_algorithms_remove_if__]] + [[``] [__range_algorithms_replace__]] + [[``] [__range_algorithms_replace_copy__]] + [[``] [__range_algorithms_replace_copy_if__]] + [[``] [__range_algorithms_replace_if__]] + [[``] [__range_algorithms_reverse__]] + [[``] [__range_algorithms_reverse_copy__]] + [[``] [__range_algorithms_rotate__]] + [[``] [__range_algorithms_rotate_copy__]] + [[``] [__range_algorithms_search__]] + [[``] [__range_algorithms_search_n__]] + [[``] [__range_algorithms_includes__ + __range_algorithms_set_union__ + __range_algorithms_set_intersection__ + __range_algorithms_set_difference__ + __range_algorithms_set_symmetric_difference__]] + [[``] [__range_algorithms_sort__]] + [[``] [__range_algorithms_stable_partition__]] + [[``] [__range_algorithms_swap_ranges__]] + [[``] [__range_algorithms_transform__]] + [[``] [__range_algorithms_unique__]] + [[``] [__range_algorithms_unique_copy__]] + [[``] [__range_algorithms_upper_bound__]] +] +[endsect] + +[section:algorithm_ext Algorithm Extensions] +[table + [[Header ][Includes ]] + [[``] [__range_algorithm_ext_copy_n__]] + [[``] [__range_algorithm_ext_erase__]] + [[``] [__range_algorithm_ext_for_each__]] + [[``] [__range_algorithm_ext_insert__]] + [[``] [__range_algorithm_ext_iota__]] + [[``] [__range_algorithm_ext_is_sorted__]] + [[``] [__range_algorithm_ext_overwrite__]] + [[``] [__range_algorithm_ext_push_back__]] + [[``] [__range_algorithm_ext_push_front__]] +] +[endsect] + +[endsect] + diff --git a/libs/range/doc/history_ack.qbk b/libs/range/doc/history_ack.qbk new file mode 100644 index 00000000..27f9e2a7 --- /dev/null +++ b/libs/range/doc/history_ack.qbk @@ -0,0 +1,58 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:history_ack History and Acknowledgement] + +[heading Version 1 - before Boost 1.43] +The library have been under way for a long time. Dietmar Kühl originally intended to submit an `array_traits` class template which had most of the functionality present now, but only for arrays and standard containers. + +Meanwhile work on algorithms for containers in various contexts showed the need for handling pairs of iterators, and string libraries needed special treatment of character arrays. In the end it made sense to formalize the minimal requirements of these similar concepts. And the results are the Range concepts found in this library. + +The term Range was adopted because of paragraph 24.1/7 from the C++ standard: + +Most of the library's algorithmic templates that operate on data structures have interfaces that use ranges. A range is a pair of iterators that designate the beginning and end of the computation. A range [i, i) is an empty range; in general, a range [i, j) refers to the elements in the data structure starting with the one pointed to by i and up to but not including the one pointed to by j. Range [i, j) is valid if and only if j is reachable from i. The result of the application of functions in the library to invalid ranges is undefined. + +Special thanks goes to + +* Pavol Droba for help with documentation and implementation +* Pavel Vozenilek for help with porting the library +* Jonathan Turkanis and John Torjo for help with documentation +* Hartmut Kaiser for being review manager +* Jonathan Turkanis for porting the lib (as far as possible) to vc6 and vc7. + +The concept checks and their documentation was provided by Daniel Walker. + +[heading Version 2 - Boost 1.43 and beyond] +This version introduced Range Adaptors and Range Algorithms. This version 2 is +the result of a merge of all of the RangeEx features into Boost.Range. + +There were an enormous number of very significant contributors through all +stages of this library. + +Prior to Boost.RangeEx there had been a number of Range library implementations, +these include library implementations by Eric Niebler, Adobe, +Shunsuke Sogame etc. Eric Niebler contributed the Range Adaptor idea which is +arguably the single biggest innovation in this library. Inevitably a great deal +of commonality evolved in each of these libraries, but a considerable amount +of effort was expended to learn from all of the divergent techniques. + +The people in the following list all made contributions in the form of reviews, +user feedback, design suggestions, or defect detection: + +* Thorsten Ottosen: review management, design advice, documentation feedback +* Eric Niebler: early implementation, and review feedback +* Joel de Guzman: review +* Mathias Gaunard: review +* David Abrahams: implementation advice +* Robert Jones: defect reports, usage feedback +* Sean Parent: contributed experience from the Adobe range library +* Arno Schoedl: implementations, and review +* Rogier van Dalen: review +* Vincente Botet: review, documentation feedback + +Regardless of how I write this section it will never truly fairly capture the +gratitude that I feel to all who have contributed. Thank you everyone. + +[endsect] diff --git a/libs/range/doc/introduction.qbk b/libs/range/doc/introduction.qbk new file mode 100644 index 00000000..d03a65bc --- /dev/null +++ b/libs/range/doc/introduction.qbk @@ -0,0 +1,43 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:introduction Introduction] + +Generic algorithms have so far been specified in terms of two or more iterators. Two iterators would together form a range of values that the algorithm could work on. This leads to a very general interface, but also to a somewhat clumsy use of the algorithms with redundant specification of container names. Therefore we would like to raise the abstraction level for algorithms so they specify their interface in terms of __ranges__ as much as possible. + +The most common form of ranges used throughout the C++ community are standard library containers. When writing algorithms however, one often finds it desirable for the algorithm to accept other types that offer enough functionality to satisfy the needs of the generic code [*/if a suitable layer of indirection is applied/] . For example, raw arrays are often suitable for use with generic code that works with containers, provided a suitable adapter is used. Likewise, null terminated strings can be treated as containers of characters, if suitably adapted. + +This library therefore provides the means to adapt standard-like containers, null terminated strings, `std::pairs` of iterators, and raw arrays (and more), such that the same generic code can work with them all. The basic idea is to add another layer of indirection using __metafunctions__ and free-standing functions so syntactic and/or semantic differences can be removed. + +The main advantages are + +* simpler implementation and specification of generic range algorithms +* more flexible, compact and maintainable client code +* safe use of built-in arrays (for legacy code; why else would you use built-in arrays?) + +[heading Example - Iterate over the values in a map] +`` +using namespace boost; +using namespace boost::adaptors; +for_each( my_map | map_values, fn ); +`` + +[heading Example - Iterate over the keys in a map] +`` +using namespace boost; +using namespace boost::adaptors; +for_each( my_map | map_keys, fn ); +`` + +[heading Example - Push the even values from a map in reverse order into the container `target`] +`` +using namespace boost; +using namespace boost::adaptors; +// Assume that is_even is a predicate that has been implemented elsewhere... +push_back(target, my_map | map_values | filtered(is_even()) | reversed); +`` + +[endsect] + diff --git a/libs/range/doc/mfc_atl.qbk b/libs/range/doc/mfc_atl.qbk new file mode 100644 index 00000000..0056283d --- /dev/null +++ b/libs/range/doc/mfc_atl.qbk @@ -0,0 +1,148 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[def __mfc_collections__ [@http://msdn.microsoft.com/en-us/library/942860sh.aspx MFC Collection Classes]] +[def __atl_collections__ [@http://msdn.microsoft.com/en-us/library/15e672bd.aspx ATL Collection Classes]] + +[section:mfc_atl MFC/ATL (courtesy of Shunsuke Sogame)] + +[h4 Introduction] +This implementation was kindly donated by Shunsuke Sogame. This header adapts MFC and ATL containers to the appropriate Range concepts. + +[table + [] + [[[*Author:]] [Shunsuke Sogame]] + [[[*Contact:]] [mb2act@yahoo.co.jp]] + [[[*Date:]] [26th of May 2006]] + [[[*Copyright:]] [Shunsuke Sogame 2005-2006. Use, modification and distribution is subject to the Boost Software License, Version 1.0]] +] + +[h4 Overview] + +Boost.Range MFC/ATL Extension provides Boost.Range support for MFC/ATL collection and string types. + +`` +CTypedPtrArray *> myArray; +... +BOOST_FOREACH (CList *theList, myArray) +{ + BOOST_FOREACH (CString& str, *theList) + { + boost::to_upper(str); + std::sort(boost::begin(str), boost::end(str)); + ... + } +} +`` + +[section:requirements Requirements] + +* Boost C++ Libraries Version 1.34.0 or later (no compilation required) +* Visual C++ 7.1 or later (for MFC and ATL) + +[endsect] + +[section:mfc_ranges MFC Ranges] +If the `` is included before or after Boost.Range headers, the MFC collections and strings become models of Range. The table below lists the Traversal Category and `range_reference` of MFC ranges. + +[table + [[Range] [Traversal Category] [`range_reference::type`]] + [[`CArray`] [__random_access_range__] [`T&`]] + [[`CList`] [__bidirectional_range__] [`T&`]] + [[`CMap`] [__forward_range__] [`Range::CPair&`]] + [[`CTypedPtrArray`] [__random_access_range__] [`T* const`]] + [[`CTypedPtrList`] [__bidirectional_range__] [`T* const`]] + [[`CTypedPtrMap`] [__forward_range__] [`std::pair const`]] + [[`CByteArray`] [__random_access_range__] [`BYTE&`]] + [[`CDWordArray`] [__random_access_range__] [`DWORD&`]] + [[`CObArray`] [__random_access_range__] [`CObject*&`]] + [[`CPtrArray`] [__random_access_range__] [`void*&`]] + [[`CStringArray`] [__random_access_range__] [`CString&`]] + [[`CUIntArray`] [__random_access_range__] [`UINT&`]] + [[`CWordArray`] [__random_access_range__] [`WORD&`]] + [[`CObList`] [__bidirectional_range__] [`CObject*&`]] + [[`CPtrList`] [__bidirectional_range__] [`void*&`]] + [[`CStringList`] [__bidirectional_range__] [`CString&`]] + [[`CMapPtrToWord`] [__forward_range__] [`std::pair const`]] + [[`CMapPtrToPtr`] [__forward_range__] [`std::pair const`]] + [[`CMapStringToOb`] [__forward_range__] [`std::pair const`]] + [[`CMapStringToString`] [__forward_range__] [`Range::CPair&`]] + [[`CMapWordToOb`] [__forward_range__] [`std::pair const`]] + [[`CMapWordToPtr`] [__forward_range__] [`std::pair const`]] +] + +Other Boost.Range metafunctions are defined by the following. Let `Range` be any type listed above and `Ref` be the same as `range_reference::type`. `range_value::type` is the same as `remove_reference::type>::type`, `range_difference::type` is the same as `std::ptrdiff_t`, and `range_pointer::type` is the same as `add_pointer::type>::type`. As for `const Range`, see below. + +Adam Walling has provided the header `` to add support +for the map adaptor with MFC map types. + +[endsect] + +[section:atl_ranges ATL Ranges] + +If the `` is included before or after Boost.Range headers, the ATL collections and strings become models of Range. The table below lists the Traversal Category and `range_reference` of ATL ranges. + +[table + [[Range] [Traversal Category] [`range_reference::type`]] + [[`CAtlArray`] [__random_access_range__] [`E&`]] + [[`CAutoPtrArray`] [__random_access_range__] [`E&`]] + [[`CInterfaceArray`] [__random_access_range__] [`CComQIPtr&`]] + [[`CAtlList`] [__bidirectional_range__] [`E&`]] + [[`CAutoPtrList`] [__bidirectional_range__] [`E&`]] + [[`CHeapPtrList`] [__bidirectional_range__] [`E&`]] + [[`CInterfaceList`] [__bidirectional_range__] [`CComQIPtr&`]] + [[`CAtlMap`] [__forward_range__] [`Range::CPair&`]] + [[`CRBTree`] [__bidirectional_range__] [`Range::CPair&`]] + [[`CRBMap`] [__bidirectional_range__] [`Range::CPair&`]] + [[`CRBMultiMap`] [__bidirectional_range__] [`Range::CPair&`]] + [[`CSimpleStringT`] [__random_access_range__] [`B&`]] + [[`CStringT`] [__random_access_range__] [`B&`]] + [[`CFixedStringT`] [__random_access_range__] [`range_reference::type`]] + [[`CComBSTR`] [__random_access_range__] [`OLECHAR&`]] + [[`CSimpleArray`] [__random_access_range__] [`T&`]] +] + +Other __boost_range_home__ metafunctions are defined by the following. Let `Range` be any type listed above and `Ref` be the same as `range_reference::type`. `range_value::type` is the same as `remove_reference::type`, `range_difference::type` is the same as `std::ptrdiff_t`, and `range_pointer::type` is the same as `add_pointer::type>::type`. As for `const Range`, see below. + +[endsect] + +[section:const_ranges const Ranges] + +`range_reference::type` is defined by the following algorithm. Let `Range` be any type listed above and `Ref` be the same as `range_reference::type`. + +`` +if (Range is CObArray || Range is CObList) + return CObject const * & +else if (Range is CPtrArray || Range is CPtrList) + return void const * & +else if (there is a type X such that X& is the same as Ref) + return X const & +else if (there is a type X such that X* const is the same as Ref) + return X const * const +else + return Ref +`` + + +Other Boost.Range metafunctions are defined by the following. + +[table + [[Range metafunction] [Result]] + [[`range_value::type`] [`range_value::type`]] + [[`range_difference::type`] [`std::ptrdiff_t`]] + [[`range_pointer::type`] [`add_pointer::type>::type>::type`]] +] + +[endsect] + +[section:references References] + +# __boost_range_home__ +# __mfc_collections__ +# __atl_collections__ + +[endsect] + +[endsect] diff --git a/libs/range/doc/mfc_atl.rst b/libs/range/doc/mfc_atl.rst new file mode 100644 index 00000000..67498fb2 --- /dev/null +++ b/libs/range/doc/mfc_atl.rst @@ -0,0 +1,232 @@ + +++++++++++++++++++++++++++++++++ + |Boost| Range MFC/ATL Extension +++++++++++++++++++++++++++++++++ + +.. |Boost| image:: http://www.boost.org/libs/ptr_container/doc/boost.png + + + +:Author: Shunsuke Sogame +:Contact: mb2act@yahoo.co.jp +:date: 26th of May 2006 +:copyright: Shunsuke Sogame 2005-2006. Use, modification and distribution is subject to the Boost Software License, Version 1.0 (see LICENSE_1_0.txt__). + +__ http://www.boost.org/LICENSE_1_0.txt + + + +======== +Overview +======== + +Boost.Range MFC/ATL Extension provides `Boost.Range`_ support for MFC/ATL collection and string types. + + +.. parsed-literal:: + + CTypedPtrArray \*> myArray; + ... + BOOST_FOREACH (CList \*theList, myArray) + { + BOOST_FOREACH (CString& str, \*theList) + { + boost::to_upper(str); + std::sort(boost::begin(str), boost::end(str)); + ... + } + } + + + +* `Requirements`_ +* `MFC Ranges`_ +* `ATL Ranges`_ +* `const Ranges`_ +* `References`_ + + + +============ +Requirements +============ + +- `Boost C++ Libraries Version 1.34.0`__ or later (no compilation required) +- Visual C++ 7.1 or Visual C++ 8.0 + +__ Boost_ + + + +========== +MFC Ranges +========== + +If the ```` is included before or after `Boost.Range`_ headers, +the MFC collections and strings become models of Range. +The table below lists the Traversal Category and ``range_reference`` of MFC ranges. + + +============================= ================== ======================================= +``Range`` Traversal Category ``range_reference::type`` +============================= ================== ======================================= +``CArray`` Random Access ``T&`` +----------------------------- ------------------ --------------------------------------- +``CList`` Bidirectional ``T&`` +----------------------------- ------------------ --------------------------------------- +``CMap`` Forward ``Range::CPair&`` +----------------------------- ------------------ --------------------------------------- +``CTypedPtrArray`` Random Access ``T* const`` +----------------------------- ------------------ --------------------------------------- +``CTypedPtrList`` Bidirectional ``T* const`` +----------------------------- ------------------ --------------------------------------- +``CTypedPtrMap`` Forward ``std::pair const`` +----------------------------- ------------------ --------------------------------------- +``CByteArray`` Random Access ``BYTE&`` +----------------------------- ------------------ --------------------------------------- +``CDWordArray`` Random Access ``DWORD&`` +----------------------------- ------------------ --------------------------------------- +``CObArray`` Random Access ``CObject* &`` +----------------------------- ------------------ --------------------------------------- +``CPtrArray`` Random Access ``void* &`` +----------------------------- ------------------ --------------------------------------- +``CStringArray`` Random Access ``CString&`` +----------------------------- ------------------ --------------------------------------- +``CUIntArray`` Random Access ``UINT&`` +----------------------------- ------------------ --------------------------------------- +``CWordArray`` Random Access ``WORD&`` +----------------------------- ------------------ --------------------------------------- +``CObList`` Bidirectional ``CObject* &`` +----------------------------- ------------------ --------------------------------------- +``CPtrList`` Bidirectional ``void* &`` +----------------------------- ------------------ --------------------------------------- +``CStringList`` Bidirectional ``CString&`` +----------------------------- ------------------ --------------------------------------- +``CMapPtrToWord`` Forward ``std::pair const`` +----------------------------- ------------------ --------------------------------------- +``CMapPtrToPtr`` Forward ``std::pair const`` +----------------------------- ------------------ --------------------------------------- +``CMapStringToOb`` Forward ``std::pair const`` +----------------------------- ------------------ --------------------------------------- +``CMapStringToString`` Forward ``Range::CPair&`` +----------------------------- ------------------ --------------------------------------- +``CMapWordToOb`` Forward ``std::pair const`` +----------------------------- ------------------ --------------------------------------- +``CMapWordToPtr`` Forward ``std::pair const`` +============================= ================== ======================================= + + +Other `Boost.Range`_ metafunctions are defined by the following. +Let ``Range`` be any type listed above and ``ReF`` be the same as ``range_reference::type``. +``range_value::type`` is the same as ``remove_reference::type>::type``, +``range_difference::type`` is the same as ``std::ptrdiff_t``, and +``range_pointer::type`` is the same as ``add_pointer::type>::type``. +As for ``const Range``, see `const Ranges`_. + + + +========== +ATL Ranges +========== + +If the ```` is included before or after `Boost.Range`_ headers, +the ATL collections and strings become models of Range. +The table below lists the Traversal Category and ``range_reference`` of ATL ranges. + + +============================= ================== ======================================= +``Range`` Traversal Category ``range_reference::type`` +============================= ================== ======================================= +``CAtlArray`` Random Access ``E&`` +----------------------------- ------------------ --------------------------------------- +``CAutoPtrArray`` Random Access ``E&`` +----------------------------- ------------------ --------------------------------------- +``CInterfaceArray`` Random Access ``CComQIPtr&`` +----------------------------- ------------------ --------------------------------------- +``CAtlList`` Bidirectional ``E&`` +----------------------------- ------------------ --------------------------------------- +``CAutoPtrList`` Bidirectional ``E&`` +----------------------------- ------------------ --------------------------------------- +``CHeapPtrList`` Bidirectional ``E&`` +----------------------------- ------------------ --------------------------------------- +``CInterfaceList`` Bidirectional ``CComQIPtr&`` +----------------------------- ------------------ --------------------------------------- +``CAtlMap`` Forward ``Range::CPair&`` +----------------------------- ------------------ --------------------------------------- +``CRBTree`` Bidirectional ``Range::CPair&`` +----------------------------- ------------------ --------------------------------------- +``CRBMap`` Bidirectional ``Range::CPair&`` +----------------------------- ------------------ --------------------------------------- +``CRBMultiMap`` Bidirectional ``Range::CPair&`` +----------------------------- ------------------ --------------------------------------- +``CSimpleStringT`` Random Access ``B&`` +----------------------------- ------------------ --------------------------------------- +``CStringT`` Random Access ``B&`` +----------------------------- ------------------ --------------------------------------- +``CFixedStringT`` Random Access ``range_reference::type`` +----------------------------- ------------------ --------------------------------------- +``CStringT`` Random Access ``B&`` +----------------------------- ------------------ --------------------------------------- +``CComBSTR`` Random Access ``OLECHAR&`` +----------------------------- ------------------ --------------------------------------- +``CSimpleArray`` Random Access ``T&`` +============================= ================== ======================================= + + +Other `Boost.Range`_ metafunctions are defined by the following. +Let ``Range`` be any type listed above and ``ReF`` be the same as ``range_reference::type``. +``range_value::type`` is the same as ``remove_reference::type``, +``range_difference::type`` is the same as ``std::ptrdiff_t``, and +``range_pointer::type`` is the same as ``add_pointer::type>::type``. +As for ``const Range``, see `const Ranges`_. + + + +============ +const Ranges +============ + +``range_reference::type`` is defined by the following algorithm. +Let ``Range`` be any type listed above and ``ReF`` be the same as ``range_reference::type``. + + +.. parsed-literal:: + + if (Range is CObArray || Range is CObList) + return CObject const \* & + else if (Range is CPtrArray || Range is CPtrList) + return void const \* & + else if (there is a type X such that X& is the same as ReF) + return X const & + else if (there is a type X such that X* const is the same as ReF) + return X const \* const + else + return ReF + + +Other `Boost.Range`_ metafunctions are defined by the following. +``range_value::type`` is the same as ``range_value::type``, +``range_difference::type`` is the same as ``std::ptrdiff_t``, and +``range_pointer::type`` is the same as ``add_pointer::type>::type>::type``. + + + +========== +References +========== +- `Boost.Range`_ +- `MFC Collections`__ +- `ATL Collection Classes`__ + +__ http://msdn2.microsoft.com/en-us/library/942860sh.aspx +__ http://msdn2.microsoft.com/en-US/library/15e672bd.aspx + + + +.. _Boost C++ Libraries: http://www.boost.org/ +.. _Boost: `Boost C++ Libraries`_ +.. _Boost.Range: ../index.html +.. _forward: range.html#forward_range +.. _bidirectional: range.html#forward_range +.. _random access: range.html#random_access_range + diff --git a/libs/range/doc/portability.qbk b/libs/range/doc/portability.qbk new file mode 100644 index 00000000..fabaafcb --- /dev/null +++ b/libs/range/doc/portability.qbk @@ -0,0 +1,27 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:portability Portability] + +A huge effort has been made to port the library to as many compilers as possible. + +Full support for built-in arrays require that the compiler supports class template partial specialization. For non-conforming compilers there might be a chance that it works anyway thanks to workarounds in the type traits library. +Visual C++ 6/7.0 has a limited support for arrays: as long as the arrays are of built-in type it should work. + +Notice also that some compilers cannot do function template ordering properly. In that case one must rely of __range_iterator__ and a single function definition instead of overloaded versions for const and non-const arguments. So if one cares about old compilers, one should not pass rvalues to the functions. + +For maximum portability you should follow these guidelines: + +# do not use built-in arrays, +# do not pass rvalues to __begin__`()`, __end__`()` and __iterator_range__ Range constructors and assignment operators, +# use __const_begin__`()` and __const_end__`()` whenever your code by intention is read-only; this will also solve most rvalue problems, +# do not rely on ADL: + * if you overload functions, include that header before the headers in this library, + * put all overloads in namespace boost. + + + +[endsect] + diff --git a/libs/range/doc/reference.qbk b/libs/range/doc/reference.qbk new file mode 100644 index 00000000..14cf8e86 --- /dev/null +++ b/libs/range/doc/reference.qbk @@ -0,0 +1,21 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:reference Reference] + +[include reference/overview.qbk] + +[section:concept_implementation Range concept implementation] +[include reference/synopsis.qbk] +[include reference/semantics.qbk] +[endsect] + +[include reference/adaptors.qbk] +[include reference/algorithms.qbk] +[include reference/ranges.qbk] +[include reference/utilities.qbk] +[include reference/extending.qbk] + +[endsect] diff --git a/libs/range/doc/reference/adaptors.qbk b/libs/range/doc/reference/adaptors.qbk new file mode 100644 index 00000000..2cead364 --- /dev/null +++ b/libs/range/doc/reference/adaptors.qbk @@ -0,0 +1,188 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:adaptors Range Adaptors] + +[section:introduction Introduction and motivation] + +A [*Range Adaptor] is a class that wraps an existing Range to provide a new Range with different behaviour. Since the behaviour of Ranges is determined by their associated iterators, a Range Adaptor simply wraps the underlying iterators with new special iterators. In this example + +`` +#include +#include +#include +#include + +std::vector vec; +boost::copy( vec | boost::adaptors::reversed, + std::ostream_iterator(std::cout) ); +`` + +the iterators from `vec` are wrapped `reverse_iterator`s. The type of the underlying Range Adapter is not documented because you do not need to know it. All that is relevant is that the expression + +`` +vec | boost::adaptors::reversed +`` + +returns a Range Adaptor where the iterator type is now the iterator type of the range `vec` wrapped in `reverse_iterator`. The expression `boost::adaptors::reversed` is called an *Adaptor Generator*. + +There are two ways of constructing a range adaptor. The first is by using `operator|()`. This is my preferred technique, however while discussing range adaptors with others it became clear that some users of the library strongly prefer a more familiar function syntax, so equivalent functions of the present tense form have been added as an alternative syntax. The equivalent to `rng | reversed` is `adaptors::reverse(rng)` for example. + +Why do I prefer the `operator|` syntax? The answer is readability: + +`` +std::vector vec; +boost::copy( boost::adaptors::reverse(vec), + std::ostream_iterator(std::cout) ); +`` + +This might not look so bad, but when we apply several adaptors, it becomes much worse. Just compare + +`` +std::vector vec; +boost::copy( boost::adaptors::unique( boost::adaptors::reverse( vec ) ), + std::ostream_iterator(std::cout) ); +`` + +to + +`` +std::vector vec; +boost::copy( vec | boost::adaptors::reversed + | boost::adaptors::uniqued, + std::ostream_iterator(std::cout) ); +`` + +Furthermore, some of the adaptor generators take arguments themselves and these arguments are expressed with function call notation too. In those situations, you will really appreciate the succinctness of `operator|()`. + +[heading Composition of Adaptors] + +Range Adaptors are a powerful complement to Range algorithms. The reason is that adaptors are ['*orthogonal*] to algorithms. For example, consider these Range algorithms: + +* `boost::copy( rng, out )` +* `boost::count( rng, pred )` + +What should we do if we only want to copy an element `a` if it satisfies some predicate, say `pred(a)`? And what if we only want to count the elements that satisfy the same predicate? The naive answer would be to use these algorithms: + +* `boost::copy_if( rng, pred, out )` +* `boost::count_if( rng, pred )` + +These algorithms are only defined to maintain a one to one relationship with the standard library algorithms. This approach of adding algorithm suffers a combinatorial explosion. Inevitably many algorithms are missing `_if` variants and there is redundant development overhead for each new algorithm. The Adaptor Generator is the design solution to this problem. It is conceivable that some algorithms are capable of optimization by tightly coupling the filter with the algorithm. The adaptors provide a more general solution with superior separation of orthogonal concerns. + +[heading Range Adaptor alternative to copy_if algorithm] +`` +boost::copy_if( rng, pred, out ); +`` +can be expressed as +`` +boost::copy( rng | boost::adaptors::filtered(pred), out ); +`` + +[heading Range Adaptor alternative to count_if algorithm] +`` +boost::count_if( rng, pred ); +`` +can be expressed as +`` +boost::size( rng | boost::adaptors::filtered(pred) ); +`` + +What this means is that many algorithms no longer require nor benefit from an optimized implementation with an `_if` suffix. Furthermore, it turns out that algorithms with the `_copy` suffix are often not needed either. Consider `replace_copy_if()` which may be used as + +`` +std::vector vec; +boost::replace_copy_if( rng, std::back_inserter(vec), pred, new_value ); +`` + +With adaptors and algorithms we can express this as + +`` +std::vector vec; +boost::push_back(vec, rng | boost::adaptors::replaced_if(pred, new_value)); +`` + +The latter code has several benefits: + +1. it is more ['*efficient*] because we avoid extra allocations as might happen with `std::back_inserter` + +2. it is ['*flexible*] as we can subsequently apply even more adaptors, for example: `` +boost::push_back(vec, rng | boost::adaptors::replaced_if(pred, new_value) + | boost::adaptors::reversed); +`` + +3. it is ['*safer*] because there is no use of an unbounded output iterator. + +In this manner, the ['*composition*] of Range Adaptors has the following consequences: + +1. we no longer need many of the `_if`, `_copy`, `_copy_if` and `_n` variants of algorithms. + +2. we can generate a multitude of new algorithms on the fly, for example, above we generated `reverse_replace_copy_if()` + +In other words: + +[*Range Adaptors are to algorithms what algorithms are to containers] + +[endsect] + +[section:general_requirements General Requirements] + +In the description of generator expressions, the following notation is used: + +* `fwdRng` is an expression of a type `R` that models `ForwardRange` +* `biRng` is an expression of a type `R` that models `BidirectionalRange` +* `rndRng` is an expression of a type `R` that models `RandomAccessRange` +* `pred` is an expression of a type that models `UnaryPredicate` +* `bi_pred` is an expression of a type that models `BinaryPredicate` +* `fun` is an expression of a type that models `UnaryFunction` +* `value`, `new_value` and `old_value` are objects convertible to `boost::range_value::type` +* `n,m` are integer expressions convertible to `range_difference::type` + +Also note that `boost::range_value::type` must be implicitly convertible to the type arguments to `pred`, `bi_pred` and `fun`. + +Range Category in the following adaptor descriptions refers to the minimum range concept required by the range passed to the adaptor. The resultant range is a model of the same range concept as the input range unless specified otherwise. + +Returned Range Category is the concept of the returned range. In some cases the returned range is of a lesser category than the range passed to the adaptor. For example, the `filtered` adaptor returns only a `ForwardRange` regardless of the input. + +Furthermore, the following rules apply to any expression of the form +`` +rng | boost::adaptors::adaptor_generator +`` + +1. Applying `operator|()` to a range `R` (always left argument) and a range adapter `RA` (always right argument) yields a new range type which may not conform to the same range concept as `R`. + +2. The return-type of `operator|()` is otherwise unspecified. + +3. `operator|()` is found by Argument Dependent Lookup (ADL) because a range adaptor is implemented in namespace `boost::adaptors`. + +4. `operator|()` is used to add new behaviour ['*lazily*] and never modifies its left argument. + +5. All iterators extracted from the left argument are extracted using qualified calls to `boost::begin()` and `boost::end()`. + +6. In addition to the `throw`-clauses below, `operator|()` may throw exceptions as a result of copying iterators. If such copying cannot throw an exception, then neither can the whole expression. + +[endsect] + +[section:reference Reference] +[include adaptors/adjacent_filtered.qbk] +[include adaptors/copied.qbk] +[include adaptors/filtered.qbk] +[include adaptors/indexed.qbk] +[include adaptors/indirected.qbk] +[include adaptors/map_keys.qbk] +[include adaptors/map_values.qbk] +[include adaptors/ref_unwrapped.qbk] +[include adaptors/replaced.qbk] +[include adaptors/replaced_if.qbk] +[include adaptors/reversed.qbk] +[include adaptors/sliced.qbk] +[include adaptors/strided.qbk] +[include adaptors/type_erased.qbk] +[include adaptors/tokenized.qbk] +[include adaptors/transformed.qbk] +[include adaptors/uniqued.qbk] +[endsect] + +[endsect] + diff --git a/libs/range/doc/reference/adaptors/adjacent_filtered.qbk b/libs/range/doc/reference/adaptors/adjacent_filtered.qbk new file mode 100644 index 00000000..312646c1 --- /dev/null +++ b/libs/range/doc/reference/adaptors/adjacent_filtered.qbk @@ -0,0 +1,32 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:adjacent_filtered adjacent_filtered] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::adjacent_filtered(bi_pred)`]] + [[Function] [`boost::adaptors::adjacent_filter(rng, bi_pred)`]] +] + +* [*Precondition:] The `value_type` of the range is convertible to both argument types of `bi_pred`. +* [*Postcondition:] For all adjacent elements `[x,y]` in the returned range, `bi_pred(x,y)` is `true`. +* [*Throws:] Whatever the copy constructor of `bi_pred` might throw. +* [*Range Category:] __forward_range__ +* [*Return Type:] `boost::adjacent_filtered_range` +* [*Returned Range Category:] The minimum of the range category of `rng` and __forward_range__ + +[section:adjacent_filtered_example adjacent_filtered example] +[import ../../../test/adaptor_test/adjacent_filtered_example.cpp] +[adjacent_filtered_example] +[endsect] + +This would produce the output: +`` +1,2,3,4,5,6, +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/copied.qbk b/libs/range/doc/reference/adaptors/copied.qbk new file mode 100644 index 00000000..2a8abcc5 --- /dev/null +++ b/libs/range/doc/reference/adaptors/copied.qbk @@ -0,0 +1,30 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:copied copied] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::copied(n, m)`]] + [[Function] [`boost::adaptors::copy(rng, n, m)`]] +] + +* [*Precondition:] `0 <= n && n <= m && m < distance(rng)` +* [*Returns:] A new `iterator_range` that holds the sliced range `[n,m)` of the original range. +* [*Range Category:] __random_access_range__ +* [*Returned Range Category:] __random_access_range__ + +[section:copied_example copied example] +[import ../../../test/adaptor_test/copied_example.cpp] +[copied_example] +[endsect] + +This would produce the output: +`` +2,3,4,5, +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/examples/indirected.cpp b/libs/range/doc/reference/adaptors/examples/indirected.cpp new file mode 100644 index 00000000..efb9d13c --- /dev/null +++ b/libs/range/doc/reference/adaptors/examples/indirected.cpp @@ -0,0 +1,32 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include +#include +#include + +int main(int argc, const char* argv[]) +{ + using namespace boost::adaptors; + + std::vector > input; + + for (int i = 0; i < 10; ++i) + input.push_back(boost::shared_ptr(new int(i))); + + boost::copy( + input | indirected, + std::ostream_iterator(std::cout, ",")); + + return 0; +} + diff --git a/libs/range/doc/reference/adaptors/filtered.qbk b/libs/range/doc/reference/adaptors/filtered.qbk new file mode 100644 index 00000000..4ca3f916 --- /dev/null +++ b/libs/range/doc/reference/adaptors/filtered.qbk @@ -0,0 +1,32 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:filtered filtered] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::filtered(pred)`]] + [[Function] [`boost::adaptors::filter(rng, pred)`]] +] + +* [*Precondition:] The `value_type` of the range is convertible to the argument type of `pred`. +* [*Postcondition:] For all elements `[x]` in the returned range, `pred(x)` is `true`. +* [*Throws:] Whatever the copy constructor of `pred` might throw. +* [*Range Category:] __singlepass_range__ +* [*Range Return Type:] `boost::filtered_range` +* [*Returned Range Category:] The minimum of the range category of `rng` and __bidirectional_range__ + +[section:filtered_example filtered example] +[import ../../../test/adaptor_test/filtered_example.cpp] +[filtered_example] +[endsect] + +This would produce the output: +`` +2,4,6,8, +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/formatted.qbk b/libs/range/doc/reference/adaptors/formatted.qbk new file mode 100644 index 00000000..9dd69c2e --- /dev/null +++ b/libs/range/doc/reference/adaptors/formatted.qbk @@ -0,0 +1,51 @@ +[/ + Copyright 2014 Neil Groves + 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) +/] +[section:formatted formatted] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::formatted()`]] + [[Pipe] [`rng | boost::adaptors::formatted(sep)`]] + [[Pipe] [`rng | boost::adaptors::formatted(sep, prefix)`]] + [[Pipe] [`rng | boost::adaptors::formatted(sep, prefix, postfix)`]] + [[Function] [`boost::adaptors::format(rng)`]] + [[Function] [`boost::adaptors::format(rng, sep)`]] + [[Function] [`boost::adaptors::format(rng, sep, prefix)`]] + [[Function] [`boost::adaptors::format(rng, sep, prefix, postfix)`]] +] + +This adaptor produces a range that can be output streamed to a +`std::basic_ostream` to produce the output string formatted output. With the +default paramters given numbers 1 to 5 inclusively in a range the output when +streamed would be "{0,1,2,3,4,5}". The prefix, separator and postfix may be +passed as parameters. + +The general format of the output is thus: +... + +* [*Precondition:] + * `0 <= n`. + * `sep` has a type that is CopyConstructible and able to be streamed to `std::basic_ostream` + * `prefix` has a type that is CopyConstructible and able to be streamed to `std::basic_ostream` + * `postfix` has a type that is CopyConstructible and able to be streamed to `std::basic_ostream` +* [*Returns:] `boost::range::formatted_range` where +`Iter` is `typename boost::range_iterator::type`, `Sep` is the separator +type, `Prefix` is the prefix type and `Postfix` is the postfix type. +* [*Range Category:] __single_pass_range__ +* [*Returned Range Category:] The range category of `rng`. + +[section:formatted_example formatted example] +[import ../../../test/adaptor_test/formatted_example.cpp] +[separated_example] +[endsect] + +This would produce the output: +`` +{1,2,3,4,5} +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/indexed.qbk b/libs/range/doc/reference/adaptors/indexed.qbk new file mode 100644 index 00000000..4503fe6c --- /dev/null +++ b/libs/range/doc/reference/adaptors/indexed.qbk @@ -0,0 +1,84 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:indexed indexed] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::indexed()`]] + [[Pipe] [`rng | boost::adaptors::indexed(start_index)`]] + [[Function] [`boost::adaptors::index(rng)`]] + [[Function] [`boost::adaptors::index(rng, start_index)`]] +] + +[heading Description] +The index within each returned `boost::range::index_value` is equal to +`start_index` + the offset of the element from the beginning of the range. In +the versions of the functions that omit `start_index` the starting index is +taken to be `0`. + +* [*Purpose:] Adapt `rng` to return elements that have the corresponding value +from `rng` and a numeric index. +* [*Returns:] A range adapted to return both the element and the associated +index. The returned range has elements of type: + +`` +boost::range::index_value< + typename boost::range_reference::type, + typename boost::range_difference::type +> +`` + +The synopsis of index_value is as follows: +`` +template +class index_value : public boost::tuple +{ +public: + + typedef ...unspecified... index_type; + typedef ...unspecified... const_index_type; + + typedef ...unspecified... value_type; + typedef ...unspecified... const_value_type; + + // ...unspecified... constructors + + index_type index(); + const_index_type index() const; + + value_type value(); + const_value_type value() const; +}; +`` + +* [*Range Category:] __single_pass_range__ +* [*Range Return Type:] `boost::indexed_range` +* [*Returned Range Category:] The range category of `rng` if and only if `rng` +is not a __bidirectional_range__. If `rng` is a __bidirectional_range__ then the +returned range category is __forward_range__. The rationale for the demotion of +__bidirectional_range__ inputs to __forward_range__ is to avoid slow calculation +of indices for `boost::end(rng)`. + +[section:indexed_example indexed example] +[import ../../../test/adaptor_test/indexed_example.cpp] +[indexed_example] +[endsect] + +This would produce the output: +`` +Element = 10 Index = 0 +Element = 20 Index = 1 +Element = 30 Index = 2 +Element = 40 Index = 3 +Element = 50 Index = 4 +Element = 60 Index = 5 +Element = 70 Index = 6 +Element = 80 Index = 7 +Element = 90 Index = 8 +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/indirected.qbk b/libs/range/doc/reference/adaptors/indirected.qbk new file mode 100644 index 00000000..3d6f4167 --- /dev/null +++ b/libs/range/doc/reference/adaptors/indirected.qbk @@ -0,0 +1,31 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:indirected indirected] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::indirected`]] + [[Function] [`boost::adaptors::indirect(rng)`]] +] + +* [*Precondition:] The `value_type` of the range defines unary `operator*()` +* [*Postcondition:] For all elements `x` in the returned range, `x` is the result of `*y` where `y` is the corresponding element in the original range. +* [*Range Category:] __single_pass_range__ +* [*Range Return Type:] `boost::indirected_range` +* [*Returned Range Category:] The range category of `rng` + +[section:indirected_example indirected example] +[import ../../../test/adaptor_test/indirected_example.cpp] +[indirected_example] +[endsect] + +This would produce the output: +`` +0,1,2,3,4,5,6,7,8,9, +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/map_keys.qbk b/libs/range/doc/reference/adaptors/map_keys.qbk new file mode 100644 index 00000000..e70b4b8c --- /dev/null +++ b/libs/range/doc/reference/adaptors/map_keys.qbk @@ -0,0 +1,31 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:map_keys map_keys] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::map_keys`]] + [[Function] [`boost::adaptors::keys(rng)`]] +] + +* [*Precondition:] The `value_type` of the range is an instantiation of `std::pair`. +* [*Postcondition:] For all elements `x` in the returned range, `x` is the result of `y.first` where `y` is the corresponding element in the original range. +* [*Range Category:] __single_pass_range__ +* [*Range Return Type:] `boost::select_first_range` +* [*Returned Range Category:] The range category of `rng`. + +[section:map_keys_example map_keys example] +[import ../../../test/adaptor_test/map_keys_example.cpp] +[map_keys_example] +[endsect] + +This would produce the output: +`` +0,1,2,3,4,5,6,7,8,9, +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/map_values.qbk b/libs/range/doc/reference/adaptors/map_values.qbk new file mode 100644 index 00000000..845c9e87 --- /dev/null +++ b/libs/range/doc/reference/adaptors/map_values.qbk @@ -0,0 +1,31 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:map_values map_values] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::map_values`]] + [[Function] [`boost::adaptors::values(rng)`]] +] + +* [*Precondition:] The `value_type` of the range is an instantiation of `std::pair`. +* [*Postcondition:] For all elements `x` in the returned range, `x` is the result of `y.second` where `y` is the corresponding element in the original range. +* [*Range Category:] __single_pass_range__ +* [*Range Return Type:] for constant ranges, `boost::select_second_const` otherwise `boost:select_second_mutable` +* [*Returned Range Category:] The range category of `rng`. + +[section:map_values_example map_values example] +[import ../../../test/adaptor_test/map_values_example.cpp] +[map_values_example] +[endsect] + +This would produce the output: +`` +0,10,20,30,40,50,60,70,80,90, +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/ref_unwrapped.qbk b/libs/range/doc/reference/adaptors/ref_unwrapped.qbk new file mode 100644 index 00000000..156ad67b --- /dev/null +++ b/libs/range/doc/reference/adaptors/ref_unwrapped.qbk @@ -0,0 +1,32 @@ +[/ + Copyright 2015 Robin Eckert + 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) +/] +[section:ref_unwrapped ref_unwrapped] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::ref_unwrapped`]] + [[Function] [`boost::adaptors::ref_unwrap(rng)`]] +] + +This adaptor produces a range than applies `.get()` on all values in +the range. It is useful for iterating ranges of +`std::reference_wrapper` values or values using similar semantics. + +The adaptor is C++11 (and above) only. + +* [*Precondition:] The `value_type` of the range has a `.get() const`. +* [*Postcondition:] For all elements `x` in the returned range, `x` is the result of `y.get()` where `y` is the corresponding element in the original range. +* [*Range Category:] __single_pass_range__ +* [*Range Return Type:] `boost::unwrap_ref_range` +* [*Returned Range Category:] The range category of `rng`. + +[section:ref_unwrapped_example ref_unwrapped example] +[import ../../../test/adaptor_test/ref_unwrapped_example.cpp] +[ref_unwrapped_example] +[endsect] + +This would produce the output `123`. +[endsect] diff --git a/libs/range/doc/reference/adaptors/replaced.qbk b/libs/range/doc/reference/adaptors/replaced.qbk new file mode 100644 index 00000000..1c34ab93 --- /dev/null +++ b/libs/range/doc/reference/adaptors/replaced.qbk @@ -0,0 +1,33 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:replaced replaced] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::replaced(old_value, new_value)`]] + [[Function] [`boost::adaptors::replace(rng, old_value, new_value)`]] +] + +* [*Precondition:] + * `new_value` is convertible to the `value_type` of the range. + * `old_value` is convertible to the `value_type` of the range. +* [*Postcondition:] For all elements `x` in the returned range, the value `x` is equal to the value of `(y == old_value) ? new_value : y` where `y` is the corresponding element in the original range. +* [*Range Category:] __single_pass_range__ +* [*Range Return Type:] `boost::replaced_range` +* [*Returned Range Category:] The range category of `rng`. + +[section:replaced_example replaced example] +[import ../../../test/adaptor_test/replaced_example.cpp] +[replaced_example] +[endsect] + +This would produce the output: +`` +1,10,3,10,5,10,7,10,9, +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/replaced_if.qbk b/libs/range/doc/reference/adaptors/replaced_if.qbk new file mode 100644 index 00000000..99c1ed82 --- /dev/null +++ b/libs/range/doc/reference/adaptors/replaced_if.qbk @@ -0,0 +1,33 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:replaced_if replaced_if] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::replaced_if(pred, new_value)`]] + [[Function] [`boost::adaptors::replace_if(rng, pred, new_value)`]] +] + +* [*Precondition:] + * The range `value_type` is convertible to the argument type of `pred`. + * `new_value` is convertible to the `value_type` of the range. +* [*Postconditions:] For all elements `x` in the returned range, the value `x` is equal to the value of `pred(y) ? new_value : y` where `y` is the corresponding element in the original range. +* [*Range Category:] __single_pass_range__ +* [*Range Return Type:] `boost::replaced_if_range` +* [*Returned Range Category:] The range category of `rng`. + +[section:replaced_if_example replaced_if example] +[import ../../../test/adaptor_test/replaced_if_example.cpp] +[replaced_if_example] +[endsect] + +This would produce the output: +`` +1,10,3,10,5,10,7,10,9, +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/reversed.qbk b/libs/range/doc/reference/adaptors/reversed.qbk new file mode 100644 index 00000000..8fe813fa --- /dev/null +++ b/libs/range/doc/reference/adaptors/reversed.qbk @@ -0,0 +1,30 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:reversed reversed] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::reversed`]] + [[Function] [`boost::adaptors::reverse(rng)`]] +] + +* [*Returns:] A range whose iterators behave as if they were the original iterators wrapped in `reverse_iterator`. +* [*Range Category:] __bidirectional_range__ +* [*Range Return Type:] `boost::reversed_range` +* [*Returned Range Category:] The range category of `rng`. + +[section:reversed_example reversed example] +[import ../../../test/adaptor_test/reversed_example.cpp] +[reversed_example] +[endsect] + +This would produce the output: +`` +9,8,7,6,5,4,3,2,1, +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/sliced.qbk b/libs/range/doc/reference/adaptors/sliced.qbk new file mode 100644 index 00000000..81b4a160 --- /dev/null +++ b/libs/range/doc/reference/adaptors/sliced.qbk @@ -0,0 +1,31 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:sliced sliced] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::sliced(n, m)`]] + [[Function] [`boost::adaptors::slice(rng, n, m)`]] +] + +* [*Precondition:] `0 <= n && n <= m && m < distance(rng)` +* [*Returns:] `make_range(rng, n, m)` +* [*Range Category:] __random_access_range__ +* [*Range Return Type:] `boost::sliced_range` +* [*Returned Range Category:] __random_access_range__ + +[section:sliced_example sliced example] +[import ../../../test/adaptor_test/sliced_example.cpp] +[sliced_example] +[endsect] + +This would produce the output: +`` +3,4,5, +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/strided.qbk b/libs/range/doc/reference/adaptors/strided.qbk new file mode 100644 index 00000000..a672e3d2 --- /dev/null +++ b/libs/range/doc/reference/adaptors/strided.qbk @@ -0,0 +1,30 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:strided strided] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::strided(n)`]] + [[Function] [`boost::adaptors::stride(rng, n)`]] +] + +* [*Precondition:] `0 <= n`. +* [*Returns:] A new range based on `rng` where traversal is performed in steps of `n`. +* [*Range Category:] __single_pass_range__ +* [*Returned Range Category:] The range category of `rng`. + +[section:strided_example strided example] +[import ../../../test/adaptor_test/strided_example.cpp] +[strided_example] +[endsect] + +This would produce the output: +`` +1,3,5,7,9, +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/tokenized.qbk b/libs/range/doc/reference/adaptors/tokenized.qbk new file mode 100644 index 00000000..2105323d --- /dev/null +++ b/libs/range/doc/reference/adaptors/tokenized.qbk @@ -0,0 +1,67 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:tokenized tokenized] + +[table + [[Syntax] [Code]] + [ + [Pipe] + [ + `` + rng | boost::adaptors::tokenized(regex) + rng | boost::adaptors::tokenized(regex, i) + rng | boost::adaptors::tokenized(regex, rndRng) + rng | boost::adaptors::tokenized(regex, i, flags) + rng | boost::adaptors::tokenized(regex, rndRng, flags) + `` + ] + ] + [ + [Function] + [ + `` + boost::adaptors::tokenize(rng, regex) + boost::adaptors::tokenize(rng, regex, i) + boost::adaptors::tokenize(rng, regex, rndRng) + boost::adaptors::tokenize(rng, regex, i, flags) + boost::adaptors::tokenize(rng, regex, rndRng, flags) + `` + ] + ] +] + +* [*Precondition:] + * Let `T` denote `typename range_value::type`, then `regex` has the type `basic_regex` or is implicitly convertible to one of these types. + * `i` has the type `int`. + * the `value_type` of `rndRng` is `int`. + * `flags` has the type `regex_constants::syntax_option_type`. +* [*Returns:] A range whose iterators behave as if they were the original iterators wrapped in `regex_token_iterator`. The first iterator in the range would be constructed by forwarding all the arguments of `tokenized()` to the `regex_token_iterator` constructor. +* [*Throws:] Whatever constructing and copying equivalent `regex_token_iterator`s might throw. +* [*Range Category:] __random_access_range__ +* [*Range Return Type:] `boost::tokenized_range` +* [*Returned Range Category:] __random_access_range__ + +[section:tokenized_example tokenized_example] +[import ../../../test/adaptor_test/tokenized_example.cpp] +[tokenized_example] +[endsect] + +This would produce the output: +`` +a +b +c +d +e +f +g +hijklmnopqrstuvwxyz + +`` + +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/transformed.qbk b/libs/range/doc/reference/adaptors/transformed.qbk new file mode 100644 index 00000000..0c71e8d8 --- /dev/null +++ b/libs/range/doc/reference/adaptors/transformed.qbk @@ -0,0 +1,32 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:transformed transformed] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::transformed(fun)`]] + [[Function] [`boost::adaptors::transform(rng, fun)`]] +] + +* [*Precondition:] The `value_type` of the range is convertible to the argument type of `fun`. +* [*Postcondition:] For all elements `x` in the returned range, `x` is the result of `fun(y)` where `y` is the corresponding element in the original range. +* [*Throws:] Whatever the copy-constructor of `fun` might throw. +* [*Range Category:] __single_pass_range__ +* [*Range Return Type:] `boost::transformed_range` +* [*Returned Range Category:] The range category of `rng`. + +[section:transformed_example transformed example] +[import ../../../test/adaptor_test/transformed_example.cpp] +[transformed_example] +[endsect] + +This would produce the output: +`` +2,4,6,8,10,12,14,16,18,20, +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/type_erased.qbk b/libs/range/doc/reference/adaptors/type_erased.qbk new file mode 100644 index 00000000..e55ff665 --- /dev/null +++ b/libs/range/doc/reference/adaptors/type_erased.qbk @@ -0,0 +1,65 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:type_erased type_erased] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::type_erased()`]] + [[Function] [`boost::adaptors::type_erase(rng, boost::adaptors::type_erased)`]] +] + +Please note that it is frequently unnecessary to use the `type_erased` adaptor. It is often better to use the implicit conversion to `any_range`. + +Let `Rng` be the type of `rng`. + +* [*Template parameters:] + * `Value` is the `value_type` for the `any_range`. If this is set to boost::use_default, `Value` will be calculated from the + range type when the adaptor is applied. + * `Traversal` is the tag used to identify the traversal of the resultant range. Frequently it is desirable to set a traversal category lower than the source container or range to maximize the number of ranges that can convert to the `any_range`. If this is left as boost::use_default then `Traversal` will be `typename boost::iterator_traversal::type>::type` + * `Reference` is the `reference` for the `any_range`. `boost::use_default` will equate to `typename range_reference::type`. + * `Difference` is the `difference_type` for the any_range. `boost::use_default` will equate to `typename boost::range_difference::type` + * `Buffer` is the storage used to allocate the underlying iterator wrappers. This can typically be ignored, but is available as a template parameter for customization. Buffer must be a model of the `AnyIteratorBufferConcept`. +* [*Precondition:] `Traversal` is one of `{ boost::use_default, boost::single_pass_traversal_tag, boost::forward_traversal_tag, boost::bidirectional_traversal_tag, boost::random_access_traversal_tag }` +* [*Returns:] The returned value is the same as `typename any_range_type_generator< Rng, Value, Traversal, Reference, Difference, Buffer >` that represents `rng` in a type-erased manner. +* [*Range Category:] __single_pass_range__ +* [*Returned Range Category:] if `Traversal` was specified as `boost::use_default` then `typename boost::iterator_traversal::type>::type`, otherwise `Traversal`. + +[heading AnyIteratorBufferConcept] +`` +class AnyIteratorBufferConcept +{ +public: + AnyIteratorBufferConcept(); + ~AnyIteratorBufferConcept(); + + // bytes is the requested size to allocate. This function + // must return a pointer to an adequate area of memory. + // throws: bad_alloc + // + // The buffer will only ever have zero or one + // outstanding memory allocations. + void* allocate(std::size_t bytes); + + // deallocate this buffer + void deallocate(); +}; +`` + +[section:type_erased_example type-erased example] +[import ../../../test/adaptor_test/type_erased_example.cpp] +[type_erased_example] +[endsect] + +This would produce the output: +`` +1,2,3,4,5, +6,7,8,9,10, +11,12,13,14,15, +11,12,13,14,15, +`` +[endsect] + + diff --git a/libs/range/doc/reference/adaptors/uniqued.qbk b/libs/range/doc/reference/adaptors/uniqued.qbk new file mode 100644 index 00000000..3fb38d76 --- /dev/null +++ b/libs/range/doc/reference/adaptors/uniqued.qbk @@ -0,0 +1,31 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:uniqued uniqued] + +[table + [[Syntax] [Code]] + [[Pipe] [`rng | boost::adaptors::uniqued`]] + [[Function] [`boost::adaptors::unique(rng)`]] +] + +* [*Precondition:] The `value_type` of the range is comparable with `operator==()`. +* [*Postcondition:] For all adjacent elements `[x,y]` in the returned range, `x==y` is false. +* [*Range Category:] __forward_range__ +* [*Range Return Type:] `boost::uniqued_range` +* [*Returned Range Category:] The minimum of the range concept of `rng` and __forward_range__. + +[section:uniqued_example uniqued example] +[import ../../../test/adaptor_test/uniqued_example.cpp] +[uniqued_example] +[endsect] + +This would produce the output: +`` +1,2,3,4,5,6, +`` +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/adjacent_find.qbk b/libs/range/doc/reference/algorithm/adjacent_find.qbk new file mode 100644 index 00000000..67d78d48 --- /dev/null +++ b/libs/range/doc/reference/algorithm/adjacent_find.qbk @@ -0,0 +1,85 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:adjacent_find adjacent_find] + +[heading Prototype] + +`` +template +typename range_iterator::type +adjacent_find(ForwardRange& rng); + +template +typename range_iterator::type +adjacent_find(const ForwardRange& rng); + +template +typename range_iterator::type +adjacent_find(ForwardRange& rng, BinaryPred pred); + +template +typename range_iterator::type +adjacent_find(const ForwardRange& rng, BinaryPred pred); + +template +typename range_return::type +adjacent_find(ForwardRange& rng); + +template +typename range_return::type +adjacent_find(const ForwardRange& rng); + +template< + range_return_value re, + class ForwardRange, + class BinaryPredicate + > +typename range_return::type +adjacent_find(ForwardRange& rng, BinaryPredicate pred); + +template< + range_return_value re, + class ForwardRange, + class BinaryPredicate + > +typename range_return::type +adjacent_find(const ForwardRange& rng, BinaryPredicate pred); +`` + +[heading Description] + +[*Non-predicate versions:] + +`adjacent_find` finds the first adjacent elements `[x,y]` in `rng` where `x == y` + +[*Predicate versions:] + +`adjacent_find` finds the first adjacent elements `[x,y]` in `rng` where `pred(x,y)` is `true`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/adjacent_find.hpp` + +[heading Requirements] + +[*For the non-predicate versions of adjacent_find:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange`'s value type is a model of the `EqualityComparableConcept`. + +[*For the predicate versions of adjacent_find:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `BinaryPredicate` is a model of the `BinaryPredicateConcept`. +* `ForwardRange`'s value type is convertible to `BinaryPredicate`'s first argument type and to `BinaryPredicate`'s second argument type. + +[heading Complexity] + +Linear. If `empty(rng)` then no comparisons are performed; otherwise, at most `distance(rng) - 1` comparisons. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/binary_search.qbk b/libs/range/doc/reference/algorithm/binary_search.qbk new file mode 100644 index 00000000..42031b33 --- /dev/null +++ b/libs/range/doc/reference/algorithm/binary_search.qbk @@ -0,0 +1,60 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:binary_search binary_search] + +[heading Prototype] + +`` +template +bool binary_search(const ForwardRange& rng, const Value& val); + +template +bool binary_search(const ForwardRange& rng, const Value& val, BinaryPredicate pred); +`` + +[heading Description] + +`binary_search` returns `true` if and only if the value `val` exists in the range `rng`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/binary_search.hpp` + +[heading Requirements] + +[*For the non-predicate versions of binary_search:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `Value` is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `Value` is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. +* `ForwardRange`'s value type is the same type as `Value`. + +[*For the predicate versions of binary_search:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `ForwardRange`'s value type is the same type as `Value`. +* `ForwardRange`'s value type is convertible to `BinaryPredicate`'s argument type. + +[heading Precondition:] + +[*For the non-predicate version:] + +`rng` is ordered in ascending order according to `operator<`. + +[*For the predicate version:] + +`rng` is ordered in ascending order according to the function object `pred`. + +[heading Complexity] + +For non-random-access ranges, the complexity is `O(N)` where `N` is `distance(rng)`. + +For random-access ranges, the complexity is `O(log N)` where `N` is `distance(rng)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/copy.qbk b/libs/range/doc/reference/algorithm/copy.qbk new file mode 100644 index 00000000..e40f1b13 --- /dev/null +++ b/libs/range/doc/reference/algorithm/copy.qbk @@ -0,0 +1,41 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:copy copy] + +[heading Prototype] + +`` +template +OutputIterator copy(const SinglePassRange& source_rng, OutputIterator out_it); +`` + +[heading Description] + +`copy` copies all elements from `source_rng` to the range `[out_it, out_it + distance(source_rng))`. +The return value is `out_it + distance(source_rng)` + +[heading Definition] + +Defined in the header file `boost/range/algorithm/copy.hpp` + +[heading Requirements] + +* `SinglePassRange` is a model of the __single_pass_range__ Concept. +* `OutputIterator` is a model of the `OutputIteratorConcept`. +* The `value_type` of __single_pass_range__ Concept is convertible to a type in `OutputIterator`'s set of value types. + +[heading Precondition:] + +* `out_it` is not an iterator within the `source_rng`. +* `[out_it, out_it + distance(source_rng))` is a valid range. + +[heading Complexity] + +Linear. Exactly `distance(source_rng)` assignments are performed. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/copy_backward.qbk b/libs/range/doc/reference/algorithm/copy_backward.qbk new file mode 100644 index 00000000..8fdac5a8 --- /dev/null +++ b/libs/range/doc/reference/algorithm/copy_backward.qbk @@ -0,0 +1,46 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:copy_backward copy_backward] + +[heading Prototype] + +`` +template + BidirectionalOutputIterator + copy_backward(const BidirectionalRange& source_rng, + BidirectionalOutputIterator out_it); +`` + +[heading Description] + +`copy_backward` copies all elements from `source_rng` to the range `[out_it - distance(source_rng), out_it)`. + +The values are copied in reverse order. The return value is `out_it - distance(source_rng)`. + +Note well that unlike all other standard algorithms `out_it` denotes the *end* of the output sequence. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/copy_backward.hpp` + +[heading Requirements] + +* `BidirectionalRange` is a model of __bidirectional_range__ Concept. +* `OutputIterator` is a model of the `OutputIteratorConcept`. +* The `value_type` of __bidirectional_range__ Concept is convertible to a type in `OutputIterator`'s set of value types. + +[heading Precondition:] + +* `out_it` is not an iterator within the `source_rng`. +* `[out_it, out_it + distance(source_rng))` is a valid range. + +[heading Complexity] + +Linear. Exactly `distance(source_rng)` assignments are performed. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/count.qbk b/libs/range/doc/reference/algorithm/count.qbk new file mode 100644 index 00000000..a84af3c4 --- /dev/null +++ b/libs/range/doc/reference/algorithm/count.qbk @@ -0,0 +1,41 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:count count] + +[heading Prototype] + +`` +template +typename range_difference::type +count(SinglePassRange& rng, const Value& val); + +template +typename range_difference::type +count(const SinglePassRange& rng, const Value& val); +`` + +[heading Description] + +`count` returns the number of elements `x` in `rng` where `x == val` is `true`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/count.hpp` + +[heading Requirements] + +* `SinglePassRange` is a model of the __single_pass_range__ Concept. +* `Value` is a model of the `EqualityComparableConcept`. +* `SinglePassRange`'s value type is a model of the `EqualityComparableConcept`. +* An object of `SinglePassRange`'s value type can be compared for equality with an object of type `Value`. + +[heading Complexity] + +Linear. Exactly `distance(rng)` comparisons. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/count_if.qbk b/libs/range/doc/reference/algorithm/count_if.qbk new file mode 100644 index 00000000..b95cc919 --- /dev/null +++ b/libs/range/doc/reference/algorithm/count_if.qbk @@ -0,0 +1,37 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:count_if count_if] + +[heading Prototype] + +`` +template +typename range_difference::type +count_if(const SinglePassRange& rng, UnaryPredicate pred); +`` + +[heading Description] + +`count_if` returns the number of elements `x` in `rng` where `pred(x)` is `true`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/count_if.hpp` + +[heading Requirements] + +* `SinglePassRange` is a model of the __single_pass_range__ Concept. +* `UnaryPredicate` is a model of the `UnaryPredicateConcept`. +* `SinglePassRange`'s value type is a model of the `EqualityComparableConcept`. +* The value type of `SinglePassRange` is convertible to the argument type of `UnaryPredicate`. + +[heading Complexity] + +Linear. Exactly `distance(rng)` invocations of `pred`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/equal.qbk b/libs/range/doc/reference/algorithm/equal.qbk new file mode 100644 index 00000000..37d1c02f --- /dev/null +++ b/libs/range/doc/reference/algorithm/equal.qbk @@ -0,0 +1,64 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:equal equal] + +[heading Prototype] + +`` +template< + class SinglePassRange1, + class SinglePassRange2 +> +bool equal(const SinglePassRange1& rng1, + const SinglePassRange2& rng2); + +template< + class SinglePassRange1, + class SinglePassRange2, + class BinaryPredicate +> +bool equal(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + BinaryPredicate pred); +`` + +[heading Description] + +`equal` returns `true` if `distance(rng1)` is equal to the `distance(rng2)` and for each element `x` in `rng1`, the corresponding element `y` in `rng2` is equal. Otherwise `false` is returned. + +In this range version of `equal` it is perfectly acceptable to pass in two ranges of unequal lengths. + +Elements are considered equal in the non-predicate version if `operator==` returns `true`. Elements are considered equal in the predicate version if `pred(x,y)` is `true`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/equal.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `SinglePassRange1`'s value type is a model of the `EqualityComparableConcept`. +* `SinglePassRange2`'s value type is a model of the `EqualityComparableConcept`. +* `SinglePassRange1`'s value type can be compared for equality with `SinglePassRange2`'s value type. + +[*For the predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `BinaryPredicate` is a model of the `BinaryPredicateConcept`. +* `SinglePassRange1`'s value type is convertible to `BinaryPredicate`'s first argument type. +* `SinglePassRange2`'s value type is convertible to `BinaryPredicate`'s second argument type. + +[heading Complexity] + +Linear. At most `min(distance(rng1), distance(rng2))` comparisons. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/equal_range.qbk b/libs/range/doc/reference/algorithm/equal_range.qbk new file mode 100644 index 00000000..2d6c342d --- /dev/null +++ b/libs/range/doc/reference/algorithm/equal_range.qbk @@ -0,0 +1,83 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:equal_range equal_range] + +[heading Prototype] + +`` +template< + class ForwardRange, + class Value + > +std::pair::type, + typename range_iterator::type> +equal_range(ForwardRange& rng, const Value& val); + +template< + class ForwardRange, + class Value + > +std::pair::type, + typename range_iterator::type> +equal_range(const ForwardRange& rng, const Value& val); + +template< + class ForwardRange, + class Value, + class SortPredicate + > +std::pair::type, + typename range_iterator::type> +equal_range(ForwardRange& rng, const Value& val, SortPredicate pred); + +template< + class ForwardRange, + class Value, + class SortPredicate + > +std::pair::type, + typename range_iterator::type> +equal_range(const ForwardRange& rng, const Value& val, SortPredicate pred); + `` + +[heading Description] + +`equal_range` returns a range in the form of a pair of iterators where all of the elements are equal to `val`. If no values are found that are equal to `val`, then an empty range is returned, hence `result.first == result.second`. For the non-predicate versions of `equal_range` the equality of elements is determined by `operator<`. +For the predicate versions of `equal_range` the equality of elements is determined by `pred`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/equal_range.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `Value` is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `Value` is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. +* `ForwardRange`'s value type is the same type as `Value`. + +[*For the predicate versions:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `SortPredicate` is a model of the `StrictWeakOrderingConcept`. +* `ForwardRange`'s value type is the same as `Value`. +* `ForwardRange`'s value type is convertible to both of `SortPredicate`'s argument types. + +[heading Precondition:] + +For the non-predicate versions: `rng` is ordered in ascending order according to `operator<`. + +For the predicate versions: `rng` is ordered in ascending order according to `pred`. + +[heading Complexity] + +For random-access ranges, the complexity is `O(log N)`, otherwise the complexity is `O(N)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/fill.qbk b/libs/range/doc/reference/algorithm/fill.qbk new file mode 100644 index 00000000..4df2c0f4 --- /dev/null +++ b/libs/range/doc/reference/algorithm/fill.qbk @@ -0,0 +1,36 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:fill fill] + +[heading Prototype] + +`` +template +ForwardRange& fill( ForwardRange& rng, const Value& val ); +`` + +[heading Description] + +`fill` assigns the value `val` to every element in the range `rng`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/fill.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `Value` is a model of the `AssignableConcept`. +* `Value` is convertible to `ForwardRange`'s value type. + +[heading Complexity] + +Linear. Exactly `distance(rng)` assignments are performed. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/fill_n.qbk b/libs/range/doc/reference/algorithm/fill_n.qbk new file mode 100644 index 00000000..1375d4ee --- /dev/null +++ b/libs/range/doc/reference/algorithm/fill_n.qbk @@ -0,0 +1,36 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:fill_n fill_n] + +[heading Prototype] + +`` +template +ForwardRange& fill( ForwardRange& rng, Size n, const Value& val ); +`` + +[heading Description] + +`fill_n` assigns the value `val` to `n` elements in the range `rng` beginning with `boost::begin(rng)`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/fill_n.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `Value` is a model of the `AssignableConcept`. +* `Value` is convertible to `ForwardRange`'s value type. + +[heading Complexity] + +Linear. Exactly `n` assignments are performed. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/find.qbk b/libs/range/doc/reference/algorithm/find.qbk new file mode 100644 index 00000000..ba576372 --- /dev/null +++ b/libs/range/doc/reference/algorithm/find.qbk @@ -0,0 +1,45 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:find find] + +[heading Prototype] + +`` +template +typename range_iterator::type +find(SinglePassRange& rng, Value val); + +template< + range_return_value re, + class SinglePassRange, + class Value + > +typename range_return::type +find(SinglePassRange& rng, Value val); +`` + +[heading Description] + +The versions of `find` that return an iterator, returns the first iterator in the range `rng` such that `*i == value`. `end(rng)` is returned if no such iterator exists. +The versions of find that return a `range_return`, defines `found` in the same manner as the returned iterator described above. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/find.hpp` + +[heading Requirements] + +* `SinglePassRange` is a model of the __single_pass_range__ Concept. +* `Value` is a model of the `EqualityComparableConcept`. +* The `operator==` is defined for type `Value` to be compared with the `SinglePassRange`'s value type. + +[heading Complexity] + +Linear. At most `distance(rng)` comparisons for equality. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/find_end.qbk b/libs/range/doc/reference/algorithm/find_end.qbk new file mode 100644 index 00000000..dff17cdb --- /dev/null +++ b/libs/range/doc/reference/algorithm/find_end.qbk @@ -0,0 +1,74 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:find_end find_end] + +[heading Prototype] + +`` +template +typename range_iterator::type +find_end(ForwardRange1& rng1, const ForwardRange2& rng2); + +template< + class ForwardRange1, + class ForwardRange2, + class BinaryPredicate + > +typename range_iterator::type +find_end(ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred); + +template< + range_return_value re, + class ForwardRange1, + class ForwardRange2 + > +typename range_return::type +find_end(ForwardRange1& rng1, const ForwardRange2& rng2); + +template< + range_return_value re, + class ForwardRange1, + class ForwardRange2, + class BinaryPredicate + > +typename range_return::type +find_end(ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred); +`` + +[heading Description] + +The versions of `find_end` that return an iterator, return an iterator to the beginning of the last sub-sequence equal to `rng2` within `rng1`. +Equality is determined by `operator==` for non-predicate versions of `find_end`, and by satisfying `pred` in the predicate versions. The versions of `find_end` that return a `range_return`, defines `found` in the same manner as the returned iterator described above. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/find_end.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `ForwardRange1` is a model of the __forward_range__ Concept. +* `ForwardRange2` is a model of the __forward_range__ Concept. +* `ForwardRange1`'s value type is a model of the `EqualityComparableConcept`. +* `ForwardRange2`'s value type is a model of the `EqualityComparableConcept`. +* Objects of `ForwardRange1`'s value type can be compared for equality with objects of `ForwardRange2`'s value type. + +[*For the predicate versions:] + +* `ForwardRange1` is a model of the __forward_range__ Concept. +* `ForwardRange2` is a model of the __forward_range__ Concept. +* `BinaryPredicate` is a model of the `BinaryPredicateConcept`. +* `ForwardRange1`'s value type is convertible to `BinaryPredicate`'s first argument type. +* `ForwardRange2`'s value type is convertible to `BinaryPredicate`'s second argument type. + +[heading Complexity] + +The number of comparisons is proportional to `distance(rng1) * distance(rng2)`. If both `ForwardRange1` and `ForwardRange2` are models of `BidirectionalRangeConcept` then the average complexity is linear and the worst case is `distance(rng1) * distance(rng2)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/find_first_of.qbk b/libs/range/doc/reference/algorithm/find_first_of.qbk new file mode 100644 index 00000000..d10d986f --- /dev/null +++ b/libs/range/doc/reference/algorithm/find_first_of.qbk @@ -0,0 +1,74 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:find_first_of find_first_of] + +[heading Prototype] + +`` +template +typename range_iterator::type +find_first_of(SinglePassRange1& rng1, const ForwardRange2& rng2); + +template< + class SinglePassRange1, + class ForwardRange2, + class BinaryPredicate + > +typename range_iterator::type +find_first_of(SinglePassRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred); + +template< + range_return_value re, + class SinglePassRange1, + class ForwardRange2 + > +typename range_return::type +find_first_of(SinglePassRange1& rng1, const ForwardRange2& rng2); + +template< + range_return_value re, + class SinglePassRange1, + class ForwardRange2, + class BinaryPredicate + > +typename range_return::type +find_first_of(SinglePassRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred); +`` + +[heading Description] + +The versions of `find_first_of` that return an iterator, return an iterator to the first occurrence in `rng1` of any of the elements in `rng2`. +Equality is determined by `operator==` for non-predicate versions of `find_first_of`, and by satisfying `pred` in the predicate versions. + +The versions of `find_first_of` that return a `range_return`, defines `found` in the same manner as the returned iterator described above. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/find_first_of.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `ForwardRange2` is a model of the __forward_range__ Concept. +* `SinglePassRange1`'s value type is a model of the `EqualityComparableConcept`, and can be compared for equality with `ForwardRange2`'s value type. + +[*For the predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `ForwardRange2` is a model of the __forward_range__ Concept. +* `BinaryPredicate` is a model of the `BinaryPredicateConcept`. +* `SinglePassRange1`'s value type is convertible to `BinaryPredicate`'s first argument type. +* `ForwardRange2`'s value type is convertible to `BinaryPredicate`'s second argument type. + +[heading Complexity] + +At most `distance(rng1) * distance(rng2)` comparisons. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/find_if.qbk b/libs/range/doc/reference/algorithm/find_if.qbk new file mode 100644 index 00000000..12ff91bc --- /dev/null +++ b/libs/range/doc/reference/algorithm/find_if.qbk @@ -0,0 +1,50 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:find_if find_if] + +[heading Prototype] + +`` +template +typename range_iterator::type +find_if(SinglePassRange& rng, UnaryPredicate pred); + +template< + range_return_value re, + class SinglePassRange, + class UnaryPredicate + > +typename range_return::type +find_if(SinglePassRange& rng, UnaryPredicate pred); +`` + +[heading Description] + +The versions of `find_if` that return an iterator, returns the first iterator in the range `rng` such that `pred(*i)` is `true`. `end(rng)` is returned if no such iterator exists. + +The versions of `find_if` that return a `range_return`, defines found in the same manner as the returned iterator described above. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/find_if.hpp` + +[heading Requirements] + +* `SinglePassRange` is a model of the __single_pass_range__ Concept. +* `UnaryPredicate` is a model of the `PredicateConcept`. +* The value type of `SinglePassRange` is convertible to the argument type of `UnaryPredicate`. + +[heading Precondition:] + +For each iterator `i` in `rng`, `*i` is in the domain of `UnaryPredicate`. + +[heading Complexity] + +Linear. At most `distance(rng)` invocations of `pred`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/for_each.qbk b/libs/range/doc/reference/algorithm/for_each.qbk new file mode 100644 index 00000000..36613680 --- /dev/null +++ b/libs/range/doc/reference/algorithm/for_each.qbk @@ -0,0 +1,45 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:for_each for_each] + +[heading Prototype] + +`` +template< + class SinglePassRange, + class UnaryFunction + > +UnaryFunction for_each(SinglePassRange& rng, UnaryFunction fun); + +template< + class SinglePassRange, + class UnaryFunction + > +UnaryFunction for_each(const SinglePassRange& rng, UnaryFunction fun); +`` + +[heading Description] + +`for_each` traverses forward through `rng` and for each element `x` it invokes `fun(x)`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/for_each.hpp` + +[heading Requirements] + +* `SinglePassRange` is a model of the __single_pass_range__ Concept. +* `UnaryFunction` is a model of the `UnaryFunctionConcept`. +* `UnaryFunction` does not apply any non-constant operation through its argument. +* `SinglePassRange`'s value type is convertible to `UnaryFunction`'s argument type. + +[heading Complexity] + +Linear. Exactly `distance(rng)` applications of `UnaryFunction`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/generate.qbk b/libs/range/doc/reference/algorithm/generate.qbk new file mode 100644 index 00000000..3d196641 --- /dev/null +++ b/libs/range/doc/reference/algorithm/generate.qbk @@ -0,0 +1,44 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:generate generate] + +[heading Prototype] + +`` +template +ForwardRange& generate( ForwardRange& rng, Generator gen ); + +template +const ForwardRange& generate( const ForwardRange& rng, Generator gen ); +`` + +[heading Description] + +`generate` assigns the result of `gen()` to each element in range `rng`. Returns the resultant range. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/generate.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `Generator` is a model of the `GeneratorConcept`. +* The `value_type` of `SinglePassRange` is convertible to a type in `OutputIterator`'s set of value types. + +[heading Precondition:] + +* `out_it` is not an iterator within `rng`. +* `[out_it, out_it + distance(rng))` is a valid range. + +[heading Complexity] + +Linear. Exactly `distance(rng)` assignments are performed. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/includes.qbk b/libs/range/doc/reference/algorithm/includes.qbk new file mode 100644 index 00000000..5f1ca5f4 --- /dev/null +++ b/libs/range/doc/reference/algorithm/includes.qbk @@ -0,0 +1,69 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:includes includes] + +[heading Prototype] + +`` +template +bool includes(const SinglePassRange1& rng1, const SinglePassRange2& rng2); + +template< + class SinglePassRange1, + class SinglePassRange2, + class BinaryPredicate + > +bool includes(const SinglePassRange1& rng1, const SinglePassRange2& rng2, + BinaryPredicate pred); +`` + +[heading Description] + +`includes` returns `true` if and only if, for every element in `rng2`, an equivalent element is also present in `rng1`. +The ordering relationship is determined by using `operator<` in the non-predicate versions, and by evaluating `pred` in the predicate versions. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/set_algorithm.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `SinglePassRange1` and `SinglePassRange2` have the same value type. +* `SinglePassRange1`'s value type is a model of the `LessThanComparableConcept`. +* `SinglePassRange2`'s value type is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `SinglePassRange1`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. +* The ordering of objects of type `SinglePassRange2`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + +[*For the predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `SinglePassRange1` and `SinglePassRange2` have the same value type. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `SinglePassRange1`'s value type is convertible to `BinaryPredicate`'s first argument type. +* `SinglePassRange2`'s value type is convertible to `BinaryPredicate`'s second argument types. + +[heading Precondition:] + +[*For the non-predicate versions:] + +`rng1` and `rng2` are sorted in ascending order according to `operator<`. + +[*For the predicate versions:] + +`rng1` and `rng2` are sorted in ascending order according to `pred`. + +[heading Complexity] + +Linear. `O(N)`, where `N` is `distance(rng1) + distance(rng2)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/inplace_merge.qbk b/libs/range/doc/reference/algorithm/inplace_merge.qbk new file mode 100644 index 00000000..015d9bba --- /dev/null +++ b/libs/range/doc/reference/algorithm/inplace_merge.qbk @@ -0,0 +1,77 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:inplace_merge inplace_merge] + +[heading Prototype] + +`` +template +BidirectionalRange& +inplace_merge( BidirectionalRange& rng, + typename range_iterator::type middle ); + +template +const BidirectionalRange& +inplace_merge( const BidirectionalRange& rng, + typename range_iterator::type middle ); + +template +BidirectionalRange& +inplace_merge( BidirectionalRange& rng, + typename range_iterator::type middle, + BinaryPredicate pred ); + +template +const BidirectionalRange& +inplace_merge( const BidirectionalRange& rng, + typename range_iterator::type middle, + BinaryPredicate pred ); +`` + +[heading Description] + +`inplace_merge` combines two consecutive sorted ranges `[begin(rng), middle)` and `[middle, end(rng))` into a single sorted range `[begin(rng), end(rng))`. That is, it starts with a range `[begin(rng), end(rng))` that consists of two pieces each of which is in ascending order, and rearranges it so that the entire range is in ascending order. `inplace_merge` is stable, meaning both that the relative order of elements within each input range is preserved. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/inplace_merge.hpp` + +[heading Requirements] + +[*For the non-predicate version:] + +* `BidirectionalRange` is a model of the __bidirectional_range__ Concept. +* `BidirectionalRange` is mutable. +* `range_value::type` is a model of `LessThanComparableConcept` +* The ordering on objects of `range_type::type` is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + +[*For the predicate version:] +* `BidirectionalRange` is a model of the __bidirectional_range__ Concept. +* `BidirectionalRange` is mutable. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `BidirectionalRange`'s value type is convertible to both `BinaryPredicate`'s argument types. + +[heading Precondition:] + +[heading For the non-predicate version:] + +* `middle` is in the range `rng`. +* `[begin(rng), middle)` is in ascending order. That is for each pair of adjacent elements `[x,y]`, `y < x` is `false`. +* `[middle, end(rng))` is in ascending order. That is for each pair of adjacent elements `[x,y]`, `y < x` is `false`. + +[heading For the predicate version:] + +* `middle` is in the range `rng`. +* `[begin(rng), middle)` is in ascending order. That is for each pair of adjacent elements `[x,y]`, `pred(y,x) == false`. +* `[middle, end(rng))` is in ascending order. That is for each pair of adjacent elements `[x,y]`, `pred(y,x) == false`. + +[heading Complexity] + +Worst case: `O(N log(N))` + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/lexicographical_compare.qbk b/libs/range/doc/reference/algorithm/lexicographical_compare.qbk new file mode 100644 index 00000000..8160b15f --- /dev/null +++ b/libs/range/doc/reference/algorithm/lexicographical_compare.qbk @@ -0,0 +1,60 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:lexicographical_compare lexicographical_compare] + +[heading Prototype] + +`` +template< + class SinglePassRange1, + class SinglePassRange2 + > +bool lexicographical_compare(const SinglePassRange1& rng1, + const SinglePassRange2& rng2); + +template< + class SinglePassRange1, + class SinglePassRange2, + class BinaryPredicate + > +bool lexicographical_compare(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + BinaryPredicate pred); +`` + +[heading Description] + +`lexicographical_compare` compares element by element `rng1` against `rng2`. If the element from `rng1` is less than the element from `rng2` then `true` is returned. If the end of `rng1` without reaching the end of `rng2` this also causes the return value to be `true`. The return value is `false` in all other circumstances. The elements are compared using `operator<` in the non-predicate versions of `lexicographical_compare` and using `pred` in the predicate versions. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/lexicographical_compare.hpp` + +[heading Requirements] + +[*For the non-predicate versions of lexicographical_compare:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `SinglePassRange1`'s value type is a model of the `LessThanComparableConcept`. +* `SinglePassRange2`'s value type is a model of the `LessThanComparableConcept`. +* Let `x` be an object of `SinglePassRange1`'s value type. Let `y` be an object of `SinglePassRange2`'s value type. `x < y` must be valid. `y < x` must be valid. + +[*For the predicate versions of lexicographical_compare:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `BinaryPredicate` is a model of the `BinaryPredicateConcept`. +* `SinglePassRange1`'s value type is convertible to `BinaryPredicate`'s first argument type. +* `SinglePassRange2`'s value type is convertible to `BinaryPredicate`'s second argument type. + +[heading Complexity] + +Linear. At most `2 * min(distance(rng1), distance(rng2))` comparisons. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/lower_bound.qbk b/libs/range/doc/reference/algorithm/lower_bound.qbk new file mode 100644 index 00000000..2917d267 --- /dev/null +++ b/libs/range/doc/reference/algorithm/lower_bound.qbk @@ -0,0 +1,93 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:lower_bound lower_bound] + +[heading Prototype] + +`` +template< + class ForwardRange, + class Value + > +typename range_iterator::type +lower_bound(ForwardRange& rng, Value val); + +template< + range_return_value re, + class ForwardRange, + class Value + > +typename range_return::type +lower_bound(ForwardRange& rng, Value val); + +template< + class ForwardRange, + class Value, + class SortPredicate + > +typename range_iterator::type +lower_bound(ForwardRange& rng, Value val, SortPredicate pred); + +template< + range_return_value re, + class ForwardRange, + class Value, + class SortPredicate + > +typename range_return::type +lower_bound(ForwardRange& rng, Value val, SortPredicate pred); +`` + +[heading Description] + +The versions of `lower_bound` that return an iterator, returns the first iterator in the range `rng` such that: +without predicate - `*i < value` is `false`, +with predicate - `pred(*i, value)` is `false`. + +`end(rng)` is returned if no such iterator exists. + +The versions of `lower_bound` that return a `range_return`, defines `found` in the same manner as the returned iterator described above. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/lower_bound.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `Value` is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `Value` is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. +* `ForwardRange`'s value type is the same type as `Value`. + +[*For the predicate versions:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `ForwardRange`'s value type is the same type as `Value`. +* `ForwardRange`'s value type is convertible to both of `BinaryPredicate`'s argument types. + +[heading Precondition:] + +[*For the non-predicate versions:] + +`rng` is sorted in ascending order according to `operator<`. + +[*For the predicate versions:] + +`rng` is sorted in ascending order according to `pred`. + +[heading Complexity] + +For ranges that model the __random_access_range__ concept the complexity is `O(log N)`, where `N` is `distance(rng)`. + +For all other range types the complexity is `O(N)`. + + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/make_heap.qbk b/libs/range/doc/reference/algorithm/make_heap.qbk new file mode 100644 index 00000000..df47fac2 --- /dev/null +++ b/libs/range/doc/reference/algorithm/make_heap.qbk @@ -0,0 +1,56 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:make_heap make_heap] + +[heading Prototype] + +`` +template +RandomAccessRange& make_heap(RandomAccessRange& rng); + +template +const RandomAccessRange& make_heap(const RandomAccessRange& rng); + +template +RandomAccessRange& make_heap(RandomAccessRange& rng, Compare pred); + +template +const RandomAccessRange& make_heap(const RandomAccessRange& rng, Compare pred); +`` + +[heading Description] + +`make_heap` turns `rng` into a heap. + +The ordering relationship is determined by using `operator<` in the non-predicate versions, and by evaluating `pred` in the predicate versions. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/heap_algorithm.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `RandomAccessRange`'s value type is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `RandomAccessRange`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + +[*For the predicate versions:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `Compare` is a model of the `StrictWeakOrderingConcept`. +* `RandomAccessRange`'s value type is convertible to both of `Compare`'s argument types. + +[heading Complexity] + +Linear. At most `3 * distance(rng)` comparisons. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/max_element.qbk b/libs/range/doc/reference/algorithm/max_element.qbk new file mode 100644 index 00000000..01101a52 --- /dev/null +++ b/libs/range/doc/reference/algorithm/max_element.qbk @@ -0,0 +1,86 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:max_element max_element] + +[heading Prototype] + +`` +template +typename range_iterator::type +max_element(ForwardRange& rng); + +template +typename range_iterator::type +max_element(const ForwardRange& rng); + +template +typename range_iterator::type +max_element(ForwardRange& rng, BinaryPredicate pred); + +template +typename range_iterator::type +max_element(const ForwardRange& rng, BinaryPredicate pred); + + +template< + range_return_value re, + class ForwardRange + > +typename range_return::type +max_element(ForwardRange& rng); + +template< + range_return_value_re, + class ForwardRange + > +typename range_return::type +max_element(const ForwardRange& rng); + +template< + range_return_value re, + class ForwardRange, + class BinaryPredicate + > +typename range_return::type +max_element(ForwardRange& rng, BinaryPredicate pred); + +template< + range_return_value re, + class ForwardRange, + class BinaryPredicate + > +typename range_return::type +max_element(const ForwardRange& rng, BinaryPredicate pred); +`` + +[heading Description] + +The versions of `max_element` that return an iterator, return the iterator to the maximum value as determined by using `operator<` if a predicate is not supplied. Otherwise the predicate `pred` is used to determine the maximum value. The versions of `max_element` that return a `range_return`, defines `found` in the same manner as the returned iterator described above. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/max_element.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange`'s value type is a model of the `LessThanComparableConcept`. + +[*For the predicate versions:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `BinaryPredicate` is a model of the `BinaryPredicateConcept`. +* `ForwardRange`'s value type is convertible to both of `BinaryPredicate`'s argument types. + +[heading Complexity] + +Linear. Zero comparisons if `empty(rng)`, otherwise `distance(rng) - 1` comparisons. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/merge.qbk b/libs/range/doc/reference/algorithm/merge.qbk new file mode 100644 index 00000000..e8383585 --- /dev/null +++ b/libs/range/doc/reference/algorithm/merge.qbk @@ -0,0 +1,88 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:merge merge] + +[heading Prototype] + +`` +template< + class SinglePassRange1, + class SinglePassRange2, + class OutputIterator + > +OutputIterator merge(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out); + +template< + class SinglePassRange1, + class SinglePassRange2, + class OutputIterator, + class BinaryPredicate + > +OutputIterator merge(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out, + BinaryPredicate pred); +`` + +[heading Description] + +`merge` combines two sorted ranges `rng1` and `rng2` into a single sorted range by copying elements. `merge` is stable. The return value is `out + distance(rng1) + distance(rng2)`. + +The two versions of `merge` differ by how they compare the elements. + +The non-predicate version uses the `operator<()` for the range value type. The predicate version uses the predicate instead of `operator<()`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/merge.hpp` + +[heading Requirements] + +[*For the non-predicate version:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `range_value::type` is the same as `range_value::type`. +* `range_value::type` is a model of the `LessThanComparableConcept`. +* The ordering on objects of `range_value::type` is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. +* `range_value::type` is convertible to a type in `OutputIterator`'s set of value types. + +[*For the predicate version:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `range_value::type` is the same as `range_value::type`. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `SinglePassRange1`'s value type is convertible to both `BinaryPredicate`'s argument types. +* `range_value::type` is convertible to a type in `OutputIterator`'s set of value types. + +[heading Precondition:] + +[heading For the non-predicate version:] + +* The elements of `rng1` are in ascending order. That is, for each adjacent element pair `[x,y]` of `rng1`, `y < x == false`. +* The elements of `rng2` are in ascending order. That is, for each adjacent element pair `[x,y]` of `rng2`, `y < x == false`. +* The ranges `rng1` and `[out, out + distance(rng1) + distance(rng2))` do not overlap. +* The ranges `rng2` and `[out, out + distance(rng1) + distance(rng2))` do not overlap. +* `[out, out + distance(rng1) + distance(rng2))` is a valid range. + +[heading For the predicate version:] + +* The elements of `rng1` are in ascending order. That is, for each adjacent element pair `[x,y]`, of `rng1`, `pred(y, x) == false`. +* The elements of `rng2` are in ascending order. That is, for each adjacent element pair `[x,y]`, of `rng2`, `pred(y, x) == false`. +* The ranges `rng1` and `[out, out + distance(rng1) + distance(rng2))` do not overlap. +* The ranges `rng2` and `[out, out + distance(rng1) + distance(rng2))` do not overlap. +* `[out, out + distance(rng1) + distance(rng2))` is a valid range. + +[heading Complexity] + +Linear. There are no comparisons if both `rng1` and `rng2` are empty, otherwise at most `distance(rng1) + distance(rng2) - 1` comparisons. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/min_element.qbk b/libs/range/doc/reference/algorithm/min_element.qbk new file mode 100644 index 00000000..38955328 --- /dev/null +++ b/libs/range/doc/reference/algorithm/min_element.qbk @@ -0,0 +1,86 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:min_element min_element] + +[heading Prototype] + +`` +template +typename range_iterator::type +min_element(ForwardRange& rng); + +template +typename range_iterator::type +min_element(const ForwardRange& rng); + +template +typename range_iterator::type +min_element(ForwardRange& rng, BinaryPredicate pred); + +template +typename range_iterator::type +min_element(const ForwardRange& rng, BinaryPredicate pred); + + +template< + range_return_value re, + class ForwardRange + > +typename range_return::type +min_element(ForwardRange& rng); + +template< + range_return_value_re, + class ForwardRange + > +typename range_return::type +min_element(const ForwardRange& rng); + +template< + range_return_value re, + class ForwardRange, + class BinaryPredicate + > +typename range_return::type +min_element(ForwardRange& rng, BinaryPredicate pred); + +template< + range_return_value re, + class ForwardRange, + class BinaryPredicate + > +typename range_return::type +min_element(const ForwardRange& rng, BinaryPredicate pred); +`` + +[heading Description] + +The versions of `min_element` that return an iterator, return the iterator to the minimum value as determined by using `operator<` if a predicate is not supplied. Otherwise the predicate `pred` is used to determine the minimum value. The versions of `min_element` that return a `range_return`, defines `found` in the same manner as the returned iterator described above. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/min_element.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange`'s value type is a model of the `LessThanComparableConcept`. + +[*For the predicate versions:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `BinaryPredicate` is a model of the `BinaryPredicateConcept`. +* `ForwardRange`'s value type is convertible to both of `BinaryPredicate`'s argument types. + +[heading Complexity] + +Linear. Zero comparisons if `empty(rng)`, otherwise `distance(rng) - 1` comparisons. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/mismatch.qbk b/libs/range/doc/reference/algorithm/mismatch.qbk new file mode 100644 index 00000000..35997338 --- /dev/null +++ b/libs/range/doc/reference/algorithm/mismatch.qbk @@ -0,0 +1,119 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:mismatch mismatch] + +[heading Prototype] + +`` +template +std::pair< + typename range_iterator::type, + typename range_iterator::type > +mismatch(SinglePassRange1& rng1, const SinglePassRange2& rng2); + +template +std::pair< + typename range_iterator::type, + typename range_iterator::type > +mismatch(const SinglePassRange1& rng1, const SinglePassRange2& rng2); + +template +std::pair< + typename range_iterator::type, + typename range_iterator::type > +mismatch(SinglePassRange1& rng1, SinglePassRange2& rng2); + +template +std::pair< + typename range_iterator::type, + typename range_iterator::type > +mismatch(const SinglePassRange1& rng1, SinglePassRange2& rng2); + + +template< + class SinglePassRange1, + class SinglePassRange2, + class BinaryPredicate + > +std::pair< + typename range_iterator::type, + typename range_iterator::type > +mismatch(SinglePassRange1& rng1, const SinglePassRange2& rng2, + BinaryPredicate pred); + +template< + class SinglePassRange1, + class SinglePassRange2, + class BinaryPredicate + > +std::pair< + typename range_iterator::type, + typename range_iterator::type > +mismatch(const SinglePassRange1& rng1, const SinglePassRange2& rng2, + BinaryPredicate pred); + +template< + class SinglePassRange1, + class SinglePassRange2, + class BinaryPredicate + > +std::pair< + typename range_iterator::type, + typename range_iterator::type > +mismatch(SinglePassRange1& rng1, SinglePassRange2& rng2, + BinaryPredicate pred); + +template< + class SinglePassRange1, + class SinglePassRange2, + class BinaryPredicate + > +std::pair< + typename range_iterator::type, + typename range_iterator::type > +mismatch(const SinglePassRange1& rng1, SinglePassRange2& rng2, + BinaryPredicate pred); +`` + +[heading Description] + +`mismatch` finds the first position where the corresponding elements from the two ranges `rng1` and `rng2` are not equal. + +Equality is determined by `operator==` for non-predicate versions of `mismatch`, and by satisfying `pred` in the predicate versions. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/mismatch.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `SinglePassRange1`'s value type is a model of the `EqualityComparableConcept`. +* `SinglePassRange2`'s value type is a model of the `EqualityComparableConcept`. +* `SinglePassRange1`s value type can be compared for equality with `SinglePassRange2`'s value type. + +[*For the predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `BinaryPredicate` is a model of the `BinaryPredicateConcept`. +* `SinglePassRange1`'s value type is convertible to `BinaryPredicate`'s first argument type. +* `SinglePassRange2`'s value type is convertible to `BinaryPredicate`'s second argument type. + +[heading Precondition:] + +`distance(rng2) >= distance(rng1)` + +[heading Complexity] + +Linear. At most `distance(rng1)` comparisons. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/next_permutation.qbk b/libs/range/doc/reference/algorithm/next_permutation.qbk new file mode 100644 index 00000000..4a8dc216 --- /dev/null +++ b/libs/range/doc/reference/algorithm/next_permutation.qbk @@ -0,0 +1,56 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:next_permutation next_permutation] + +[heading Prototype] + +`` +template +bool next_permutation(BidirectionalRange& rng); + +template +bool next_permutation(const BidirectionalRange& rng); + +template +bool next_permutation(BidirectionalRange& rng, Compare pred); + +template +bool next_permutation(const BidirectionalRange& rng, Compare pred); +`` + +[heading Description] + +`next_permutation` transforms the range of elements `rng` into the lexicographically next greater permutation of the elements if such a permutation exists. If one does not exist then the range is transformed into the lexicographically smallest permutation and `false` is returned. `true` is returned when the next greater permutation is successfully generated. + +The ordering relationship is determined by using `operator<` in the non-predicate versions, and by evaluating `pred` in the predicate versions. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/permutation.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `BidirectionalRange` is a model of the __bidirectional_range__ Concept. +* `BidirectionalRange` is mutable. +* `BidirectionalRange`'s value type is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `BidirectionalRange`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + +[*For the predicate versions:] + +* `BidirectionalRange` is a model of the __bidirectional_range__ Concept. +* `BidirectionalRange` is mutable. +* `Compare` is a model of the `StrictWeakOrderingConcept`. +* `BidirectionalRange`'s value type is convertible to both of `Compare`'s argument types. + +[heading Complexity] + +Linear. At most `distance(rng) / 2` swaps. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/nth_element.qbk b/libs/range/doc/reference/algorithm/nth_element.qbk new file mode 100644 index 00000000..9bd785e9 --- /dev/null +++ b/libs/range/doc/reference/algorithm/nth_element.qbk @@ -0,0 +1,67 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:nth_element nth_element] + +[heading Prototype] + +`` +template +RandomAccessRange& nth_element( + RandomAccessRange& rng, + typename range_iterator::type nth); + +template +const RandomAccessRange& nth_element( + const RandomAccessRange& rng, + typename range_iterator::type nth); + +template +RandomAccessRange& nth_element( + RandomAccessRange& rng, + typename range_iterator::type nth, + BinaryPredicate sort_pred); + +template +const RandomAccessRange& nth_element( + const RandomAccessRange& rng, + typename range_iterator::type nth, + BinaryPredicate sort_pred); +`` + +[heading Description] + +`nth_element` partially orders a range of elements. `nth_element` arranges the range `rng` such that the element corresponding with the iterator `nth` is the same as the element that would be in that position if `rng` has been sorted. + + +[heading Definition] + +Defined in the header file `boost/range/algorithm/nth_element.hpp` + +[heading Requirements] + +[*For the non-predicate version:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `RandomAccessRange`'s value type is a model of the `LessThanComparableConcept`. +* The ordering relation on `RandomAccessRange`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + + +[*For the predicate version:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `RandomAccessRange`'s value type is convertible to both of `BinaryPredicate`'s argument types. + + +[heading Complexity] + +On average, linear in `distance(rng)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/partial_sort.qbk b/libs/range/doc/reference/algorithm/partial_sort.qbk new file mode 100644 index 00000000..e2b88766 --- /dev/null +++ b/libs/range/doc/reference/algorithm/partial_sort.qbk @@ -0,0 +1,69 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:partial_sort partial_sort] + +[heading Prototype] + +`` +template +RandomAccessRange& partial_sort( + RandomAccessRange& rng, + typename range_iterator::type middle); + +template +const RandomAccessRange& partial_sort( + const RandomAccessRange& rng, + typename range_iterator::type middle); + +template +RandomAccessRange& partial_sort( + RandomAccessRange& rng, + typename range_iterator::type middle, + BinaryPredicate sort_pred); + +template +const RandomAccessRange& partial_sort( + const RandomAccessRange& rng, + typename range_iterator::type middle, + BinaryPredicate sort_pred); +`` + +[heading Description] + +`partial_sort` rearranges the elements in `rng`. It places the smallest `distance(begin(rng), middle)` elements, sorted in ascending order, into the range `[begin(rng), middle)`. The remaining elements are placed in an unspecified order into `[middle, last)`. + +The non-predicative versions of this function specify that one element is less than another by using `operator<()`. The predicate versions use the predicate instead. + + +[heading Definition] + +Defined in the header file `boost/range/algorithm/partial_sort.hpp` + +[heading Requirements] + +[*For the non-predicate version:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `RandomAccessRange`'s value type is a model of the `LessThanComparableConcept`. +* The ordering relation on `RandomAccessRange`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + + +[*For the predicate version:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `RandomAccessRange`'s value type is convertible to both of `BinaryPredicate`'s argument types. + + +[heading Complexity] + +Approximately `distance(rng) * log(distance(begin(rng), middle))` comparisons. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/partition.qbk b/libs/range/doc/reference/algorithm/partition.qbk new file mode 100644 index 00000000..a97a8930 --- /dev/null +++ b/libs/range/doc/reference/algorithm/partition.qbk @@ -0,0 +1,63 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:partition partition] + +[heading Prototype] + +`` +template< + class ForwardRange, + class UnaryPredicate + > +typename range_iterator::type +partition(ForwardRange& rng, UnaryPredicate pred); + +template< + class ForwardRange, + class UnaryPredicate + > +typename range_iterator::type +partition(const ForwardRange& rng, UnaryPredicate pred); + +template< + range_return_value re, + class ForwardRange, + class UnaryPredicate + > +typename range_return::type +partition(ForwardRange& rng, UnaryPredicate pred); + +template< + range_return_value re, + class ForwardRange, + class UnaryPredicate + > +typename range_return::type +partition(const ForwardRange& rng, UnaryPredicate pred); +`` + +[heading Description] + +`partition` orders the elements in `rng` based on `pred`, such that the elements that satisfy `pred` precede the elements that do not. In the versions that return a single iterator, the return value is the middle iterator. In the versions that have a configurable range_return, `found` corresponds to the middle iterator. + + +[heading Definition] + +Defined in the header file `boost/range/algorithm/partition.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. For C++ versions prior to C++11 the underlying std::partition requires Bidirectional Iterators, hence the requirement for older library versions is for a __bidirectional_range__. +* `UnaryPredicate` is a model of the `PredicateConcept`. +* `ForwardRange`'s value type is convertible to `UnaryPredicate`'s argument type. + +[heading Complexity] + +Linear. Exactly `distance(rng)` applications of `pred`, and at most `distance(rng) / 2` swaps. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/pop_heap.qbk b/libs/range/doc/reference/algorithm/pop_heap.qbk new file mode 100644 index 00000000..9008de4e --- /dev/null +++ b/libs/range/doc/reference/algorithm/pop_heap.qbk @@ -0,0 +1,61 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:pop_heap pop_heap] + +[heading Prototype] + +`` +template +RandomAccessRange& pop_heap(RandomAccessRange& rng); + +template +const RandomAccessRange& pop_heap(const RandomAccessRange& rng); + +template +RandomAccessRange& pop_heap(RandomAccessRange& rng, Compare pred); + +template +const RandomAccessRange& pop_heap(const RandomAccessRange& rng, Compare pred); +`` + +[heading Description] + +`pop_heap` removes the largest element from the heap. It is assumed that `begin(rng), prior(end(rng))` is already a heap (and therefore the largest element is `*begin(rng)`). + +The ordering relationship is determined by using `operator<` in the non-predicate versions, and by evaluating `pred` in the predicate versions. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/heap_algorithm.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `RandomAccessRange`'s value type is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `RandomAccessRange`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + +[*For the predicate versions:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `Compare` is a model of the `StrictWeakOrderingConcept`. +* `RandomAccessRange`'s value type is convertible to both of `Compare`'s argument types. + +[heading Precondition:] + +* `!empty(rng)` +* `rng` is a heap. + +[heading Complexity] + +Logarithmic. At most `2 * log(distance(rng))` comparisons. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/prev_permutation.qbk b/libs/range/doc/reference/algorithm/prev_permutation.qbk new file mode 100644 index 00000000..6d204317 --- /dev/null +++ b/libs/range/doc/reference/algorithm/prev_permutation.qbk @@ -0,0 +1,56 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:prev_permutation prev_permutation] + +[heading Prototype] + +`` +template +bool prev_permutation(BidirectionalRange& rng); + +template +bool prev_permutation(const BidirectionalRange& rng); + +template +bool prev_permutation(BidirectionalRange& rng, Compare pred); + +template +bool prev_permutation(const BidirectionalRange& rng, Compare pred); +`` + +[heading Description] + +`prev_permutation` transforms the range of elements `rng` into the lexicographically next smaller permutation of the elements if such a permutation exists. If one does not exist then the range is transformed into the lexicographically largest permutation and `false` is returned. `true` is returned when the next smaller permutation is successfully generated. + +The ordering relationship is determined by using `operator<` in the non-predicate versions, and by evaluating `pred` in the predicate versions. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/permutation.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `BidirectionalRange` is a model of the __bidirectional_range__ Concept. +* `BidirectionalRange` is mutable. +* `BidirectionalRange`'s value type is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `BidirectionalRange`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + +[*For the predicate versions:] + +* `BidirectionalRange` is a model of the __bidirectional_range__ Concept. +* `BidirectionalRange` is mutable. +* `Compare` is a model of the `StrictWeakOrderingConcept`. +* `BidirectionalRange`'s value type is convertible to both of `Compare`'s argument types. + +[heading Complexity] + +Linear. At most `distance(rng) / 2` swaps. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/push_heap.qbk b/libs/range/doc/reference/algorithm/push_heap.qbk new file mode 100644 index 00000000..8aff8c2f --- /dev/null +++ b/libs/range/doc/reference/algorithm/push_heap.qbk @@ -0,0 +1,61 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:push_heap push_heap] + +[heading Prototype] + +`` +template +RandomAccessRange& push_heap(RandomAccessRange& rng); + +template +const RandomAccessRange& push_heap(const RandomAccessRange& rng); + +template +RandomAccessRange& push_heap(RandomAccessRange& rng, Compare pred); + +template +const RandomAccessRange& push_heap(const RandomAccessRange& rng, Compare pred); +`` + +[heading Description] + +`push_heap` adds an element to a heap. It is assumed that `begin(rng)`, `prior(end(rng))` is already a heap and that the element to be added is `*prior(end(rng))`. + +The ordering relationship is determined by using `operator<` in the non-predicate versions, and by evaluating `pred` in the predicate versions. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/heap_algorithm.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `RandomAccessRange`'s value type is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `RandomAccessRange`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + +[*For the predicate versions:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `Compare` is a model of the `StrictWeakOrderingConcept`. +* `RandomAccessRange`'s value type is convertible to both of `Compare`'s argument types. + +[heading Precondition:] + +* `!empty(rng)` +* `[begin(rng), prior(end(rng)))` is a heap. + +[heading Complexity] + +Logarithmic. At most `log(distance(rng))` comparisons. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/random_shuffle.qbk b/libs/range/doc/reference/algorithm/random_shuffle.qbk new file mode 100644 index 00000000..b092c361 --- /dev/null +++ b/libs/range/doc/reference/algorithm/random_shuffle.qbk @@ -0,0 +1,55 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:random_shuffle random_shuffle] + +[heading Prototype] + +`` +template +RandomAccessRange& random_shuffle(RandomAccessRange& rng); + +template +const RandomAccessRange& random_shuffle(const RandomAccessRange& rng); + +template +RandomAccessRange& random_shuffle(RandomAccessRange& rng, Generator& gen); + +template +const RandomAccessRange& random_shuffle(const RandomAccessRange& rng, Generator& gen); +`` + +[heading Description] + +`random_shuffle` randomly rearranges the elements in `rng`. The versions of `random_shuffle` that do not specify a `Generator` use an internal random number generator. The versions of `random_shuffle` that do specify a `Generator` use this instead. Returns the shuffles range. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/random_shuffle.hpp` + +[heading Requirements] + +[*For the version without a Generator:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. + +[*For the version with a Generator:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `Generator` is a model of the `RandomNumberGeneratorConcept`. +* `RandomAccessRange`'s distance type is convertible to `Generator`'s argument type. + +[heading Precondition:] + +* `distance(rng)` is less than `gen`'s maximum value. + + +[heading Complexity] + +Linear. If `!empty(rng)`, exactly `distance(rng) - 1` swaps are performed. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/remove.qbk b/libs/range/doc/reference/algorithm/remove.qbk new file mode 100644 index 00000000..f26b277c --- /dev/null +++ b/libs/range/doc/reference/algorithm/remove.qbk @@ -0,0 +1,60 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:remove remove] +[heading Prototype] + +`` +template< + class ForwardRange, + class Value + > +typename range_iterator::type +remove(ForwardRange& rng, const Value& val); + +template< + class ForwardRange, + class Value + > +typename range_iterator::type +remove(const ForwardRange& rng, const Value& val); + +template< + range_return_value re, + class ForwardRange, + class Value + > +typename range_return::type +remove(ForwardRange& rng, const Value& val); + +template< + range_return_value re, + class ForwardRange, + class Value + > +typename range_return::type +remove(const ForwardRange& rng, const Value& val); +`` + +[heading Description] + +`remove` removes from `rng` all of the elements `x` for which `x == val` is `true`. The versions of `remove` that return an iterator, return an iterator `new_last` such that the range `[begin(rng), new_last)` contains no elements equal to `val`. The `range_return` versions of `remove` defines `found` as the new last element. The iterators in the range `[new_last, end(rng))` are dereferenceable, but the elements are unspecified. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/remove.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `Value` is a model of the `EqualityComparableConcept`. +* Objects of type `Value` can be compared for equality with objects of `ForwardRange`'s value type. + +[heading Complexity] + +Linear. `remove` performs exactly `distance(rng)` comparisons for equality. + +[endsect] \ No newline at end of file diff --git a/libs/range/doc/reference/algorithm/remove_copy.qbk b/libs/range/doc/reference/algorithm/remove_copy.qbk new file mode 100644 index 00000000..b98da471 --- /dev/null +++ b/libs/range/doc/reference/algorithm/remove_copy.qbk @@ -0,0 +1,39 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:remove_copy remove_copy] + +[heading Prototype] + +`` +template +OutputIterator +remove_copy(ForwardRange& rng, OutputIterator out, const Value& val); + +template +OutputIterator +remove_copy(const ForwardRange& rng, OutputIterator out, const Value& val); +`` + +[heading Description] + +`remove_copy` copied all of the elements `x` from `rng` for which `x == val` is `false`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/remove_copy.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `Value` is a model of the `EqualityComparableConcept`. +* Objects of type `Value` can be compared for equality with objects of `ForwardRange`'s value type. + +[heading Complexity] + +Linear. `remove_copy` performs exactly `distance(rng)` comparisons for equality. + +[endsect] diff --git a/libs/range/doc/reference/algorithm/remove_copy_if.qbk b/libs/range/doc/reference/algorithm/remove_copy_if.qbk new file mode 100644 index 00000000..d56647bc --- /dev/null +++ b/libs/range/doc/reference/algorithm/remove_copy_if.qbk @@ -0,0 +1,38 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:remove_copy_if remove_copy_if] + +[heading Prototype] + +`` +template +OutputIterator +remove_copy_if(ForwardRange& rng, OutputIterator out, UnaryPred pred); + +template +OutputIterator +remove_copy_if(const ForwardRange& rng, OutputIterator out, UnaryPred pred); +`` + +[heading Description] + +`remove_copy_if` copied all of the elements `x` from `rng` for which `pred(x)` is `false`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/remove_copy_if.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `UnaryPred` is a model of the `UnaryPredicateConcept`. + +[heading Complexity] + +Linear. `remove_copy_if` performs exactly `distance(rng)` comparisons with UnaryPred. + +[endsect] diff --git a/libs/range/doc/reference/algorithm/remove_if.qbk b/libs/range/doc/reference/algorithm/remove_if.qbk new file mode 100644 index 00000000..f25c4555 --- /dev/null +++ b/libs/range/doc/reference/algorithm/remove_if.qbk @@ -0,0 +1,63 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:remove_if remove_if] + +[heading Prototype] + +`` +template< + class ForwardRange, + class UnaryPredicate + > +typename range_iterator::type +remove_if(ForwardRange& rng, UnaryPredicate pred); + +template< + class ForwardRange, + class UnaryPredicate + > +typename range_iterator::type +remove_if(const ForwardRange& rng, UnaryPredicate pred); + +template< + range_return_value re, + class ForwardRange, + class UnaryPredicate + > +typename range_return::type +remove_if(ForwardRange& rng, UnaryPredicate pred); + +template< + range_return_value re, + class ForwardRange, + class UnaryPredicate + > +typename range_return::type +remove_if(const ForwardRange& rng, UnaryPredicate pred); +`` + +[heading Description] + +`remove_if` removes from `rng` all of the elements `x` for which `pred(x)` is `true`. The versions of `remove_if` that return an iterator, return an iterator `new_last` such that the range `[begin(rng), new_last)` contains no elements where `pred(x)` is `true`. The iterators in the range `[new_last, end(rng))` are dereferenceable, but the elements are unspecified. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/remove_if.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `UnaryPredicate` is a model of the `PredicateConcept`. +* `ForwardRange`'s value type is convertible to `UnaryPredicate`'s argument type. + +[heading Complexity] + +Linear. `remove_if` performs exactly `distance(rng)` applications of `pred`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/replace.qbk b/libs/range/doc/reference/algorithm/replace.qbk new file mode 100644 index 00000000..27b6c1b7 --- /dev/null +++ b/libs/range/doc/reference/algorithm/replace.qbk @@ -0,0 +1,46 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:replace replace] + +[heading Prototype] + +`` +template< + class ForwardRange, + class Value + > +ForwardRange& replace(ForwardRange& rng, const Value& what, const Value& with_what); + +template< + class ForwardRange, + class UnaryPredicate + > +const ForwardRange& replace(const ForwardRange& rng, const Value& what, const Value& with_what); +`` + +[heading Description] + +`replace` every element in `rng` equal to `what` with `with_what`. Return a reference to `rng`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/replace.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `Value` is convertible to `ForwardRange`'s value type. +* `Value` is a model of the `AssignableConcept`. +* `Value` is a model of the `EqualityComparableConcept`, and may be compared for equality with objects of `ForwardRange`'s value type. + +[heading Complexity] + +Linear. `replace` performs exactly `distance(rng)` comparisons for equality and at most `distance(rng)` assignments. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/replace_copy.qbk b/libs/range/doc/reference/algorithm/replace_copy.qbk new file mode 100644 index 00000000..e936fc03 --- /dev/null +++ b/libs/range/doc/reference/algorithm/replace_copy.qbk @@ -0,0 +1,38 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:replace_copy replace_copy] + +[heading Prototype] + +`` +template +OutputIterator replace_copy(const ForwardRange& rng, OutputIterator out, + const Value& what, const Value& with_what); +`` + +[heading Description] + +`replace_copy` copy every element `x` in `rng` such that the corresponding element in the output range `y` is `x == what ? with_what : x`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/replace_copy.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `Value` is convertible to `ForwardRange`'s value type. +* `Value` is a model of the `AssignableConcept`. +* `OutputIterator` is a model of the `OutputIteratorConcept`. + +[heading Complexity] + +Linear. `replace_copy` performs exactly `distance(rng)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/replace_copy_if.qbk b/libs/range/doc/reference/algorithm/replace_copy_if.qbk new file mode 100644 index 00000000..13305a77 --- /dev/null +++ b/libs/range/doc/reference/algorithm/replace_copy_if.qbk @@ -0,0 +1,39 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:replace_copy_if replace_copy_if] + +[heading Prototype] + +`` +template +OutputIterator replace_copy_if(const ForwardRange& rng, OutputIterator out, + UnaryPredicate pred, const Value& with_what); +`` + +[heading Description] + +`replace_copy_if` copy every element `x` in `rng` such that the corresponding element in the output range `y` is `pred(x) ? with_what : x`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/replace_copy_if.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `Value` is convertible to `ForwardRange`'s value type. +* `Value` is a model of the `AssignableConcept`. +* `OutputIterator` is a model of the `OutputIteratorConcept`. +* `UnaryPredicate` is a model of the `UnaryPredicateConcept`. + +[heading Complexity] + +Linear. `replace_copy_if` performs exactly `distance(rng)` evaluations of `pred`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/replace_if.qbk b/libs/range/doc/reference/algorithm/replace_if.qbk new file mode 100644 index 00000000..18480a97 --- /dev/null +++ b/libs/range/doc/reference/algorithm/replace_if.qbk @@ -0,0 +1,41 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:replace_if replace_if] + +[heading Prototype] + +`` +template +ForwardRange& replace_if(ForwardRange& rng, UnaryPredicate pred, const Value& with_what); + +template +const ForwardRange& replace_if(const ForwardRange& rng, UnaryPredicate pred, const Value& with_what); +`` + +[heading Description] + +`replace_if` replaces every element `x` in `rng` for which `pred(x) == true` with `with_what`. Returns a reference to `rng`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/replace_if.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `UnaryPredicate` is a model of the `PredicateConcept` +* `ForwardRange`'s value type is convertible to `UnaryPredicate`'s argument type. +* `Value` is convertible to `ForwardRange`'s value type. +* `Value` is a model of the `AssignableConcept`. + +[heading Complexity] + +Linear. `replace_if` performs exactly `distance(rng)` applications of `pred`, and at most `distance(rng)` assignments. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/reverse.qbk b/libs/range/doc/reference/algorithm/reverse.qbk new file mode 100644 index 00000000..6ecb31b5 --- /dev/null +++ b/libs/range/doc/reference/algorithm/reverse.qbk @@ -0,0 +1,37 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:reverse reverse] + +[heading Prototype] + +`` +template +BidirectionalRange& reverse(BidirectionalRange& rng); + +template +const BidirectionalRange& reverse(const BidirectionalRange& rng); +`` + +[heading Description] + +`reverse` reverses a range. Returns a reference to the reversed range. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/reverse.hpp` + +[heading Requirements] + +* `BidirectionalRange` is a model of the __bidirectional_range__ Concept. +* `BidirectionalRange` is mutable. + +[heading Complexity] + +Linear. `reverse` makes `distance(rng)/2` calls to `iter_swap`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/reverse_copy.qbk b/libs/range/doc/reference/algorithm/reverse_copy.qbk new file mode 100644 index 00000000..b19ed9fe --- /dev/null +++ b/libs/range/doc/reference/algorithm/reverse_copy.qbk @@ -0,0 +1,36 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:reverse_copy reverse_copy] + +[heading Prototype] + +`` +template +OutputIterator reverse_copy(const BidirectionalRange& rng, OutputIterator out); +`` + +[heading Description] + +`reverse_copy` copies the elements from `rng` in reverse order to `out`. +Returns the output iterator one passed the last copied element. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/reverse_copy.hpp` + +[heading Requirements] + +* `BidirectionalRange` is a model of the __bidirectional_range__ Concept. +* `BidirectionalRange` is mutable. +* `OutputIterator` is a model of the `OutputIteratorConcept`. + +[heading Complexity] + +Linear. `reverse_copy` makes `distance(rng)` copies. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/rotate.qbk b/libs/range/doc/reference/algorithm/rotate.qbk new file mode 100644 index 00000000..e28641b2 --- /dev/null +++ b/libs/range/doc/reference/algorithm/rotate.qbk @@ -0,0 +1,44 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:rotate rotate] + +[heading Prototype] + +`` +template +ForwardRange& rotate(ForwardRange& rng, + typename range_iterator::type middle); + +template +const ForwardRange& rotate(const ForwardRange& rng, + typename range_iterator::type middle); +`` + +[heading Description] + +`rotate` rotates the elements in a range. It exchanges the two ranges `[begin(rng), middle)` and `[middle, end(rng))`. Returns a reference to `rng`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/rotate.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. + +[heading Precondition:] + +* `[begin(rng), middle)` is a valid range. +* `[middle, end(rng))` is a valid range. + +[heading Complexity] + +Linear. At most `distance(rng)` swaps are performed. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/rotate_copy.qbk b/libs/range/doc/reference/algorithm/rotate_copy.qbk new file mode 100644 index 00000000..0f11bdc7 --- /dev/null +++ b/libs/range/doc/reference/algorithm/rotate_copy.qbk @@ -0,0 +1,43 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:rotate_copy rotate_copy] + +[heading Prototype] + +`` +template +OutputIterator rotate_copy( + const ForwardRange& rng, + typename range_iterator::type middle, + OutputIterator out); +`` + +[heading Description] + +`rotate_copy` rotates the elements in a range. It copies the two ranges `[begin(rng), middle)` and `[middle, end(rng))` to `out`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/rotate_copy.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `OutputIterator` is a model of the `OutputIteratorConcept`. + +[heading Precondition:] + +* `[begin(rng), middle)` is a valid range. +* `[middle, end(rng))` is a valid range. + +[heading Complexity] + +Linear. Exactly `distance(rng)` elements are copied. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/search.qbk b/libs/range/doc/reference/algorithm/search.qbk new file mode 100644 index 00000000..5c2c2a81 --- /dev/null +++ b/libs/range/doc/reference/algorithm/search.qbk @@ -0,0 +1,106 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:search search] + +[heading Prototype] + +`` +template +typename range_iterator::type +search(ForwardRange1& rng1, const ForwardRange2& rng2); + +template +typename range_iterator::type +search(const ForwardRange1& rng1, const ForwardRange2& rng2); + +template< + class ForwardRange1, + class ForwardRange2, + class BinaryPredicate + > +typename range_iterator::type, +search(ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred); + +template< + class ForwardRange1, + class ForwardRange2, + class BinaryPredicate + > +typename range_iterator::type +search(const ForwardRange1& rng1, ForwardRange2& rng2, BinaryPredicate pred); + + +template< + range_return_value re, + class ForwardRange1, + class ForwardRange2 + > +typename range_return::type +search(ForwardRange1& rng1, const ForwardRange2& rng2); + +template< + range_return_value re, + class ForwardRange1, + class ForwardRange2 + > +typename range_return::type +search(const ForwardRange1& rng1, const ForwardRange2& rng2); + +template< + range_return_value re, + class ForwardRange1, + class ForwardRange2, + class BinaryPredicate + > +typename range_return::type, +search(ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred); + +template< + range_return_value re, + class ForwardRange1, + class ForwardRange2, + class BinaryPredicate + > +typename range_return::type +search(const ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred); +`` + +[heading Description] + +The versions of `search` that return an iterator, return an iterator to the start of the first subsequence in `rng1` that is equal to the subsequence `rng2`. The `end(rng1)` is returned if no such subsequence exists in `rng1`. +Equality is determined by `operator==` for non-predicate versions of `search`, and by satisfying `pred` in the predicate versions. + +The versions of `search` that return a `range_return`, defines `found` in the same manner as the returned iterator described above. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/search.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `ForwardRange1` is a model of the __forward_range__ Concept. +* `ForwardRange2` is a model of the __forward_range__ Concept. +* `ForwardRange1`'s value type is a model of the `EqualityComparableConcept`. +* `ForwardRange2`'s value type is a model of the `EqualityComparableConcept`. +* `ForwardRange1`s value type can be compared for equality with `ForwardRange2`'s value type. + +[*For the predicate versions:] + +* `ForwardRange1` is a model of the __forward_range__ Concept. +* `ForwardRange2` is a model of the __forward_range__ Concept. +* `BinaryPredicate` is a model of the `BinaryPredicateConcept`. +* `ForwardRange1`'s value type is convertible to `BinaryPredicate`'s first argument type. +* `ForwardRange2`'s value type is convertible to `BinaryPredicate`'s second argument type. + +[heading Complexity] + +Average complexity is Linear. Worst-case complexity is quadratic. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/search_n.qbk b/libs/range/doc/reference/algorithm/search_n.qbk new file mode 100644 index 00000000..ad8cbd27 --- /dev/null +++ b/libs/range/doc/reference/algorithm/search_n.qbk @@ -0,0 +1,63 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:search_n search_n] + +[heading Prototype] + +`` +template +typename range_iterator::type +search_n(ForwardRange& rng, Integer n, const Value& value); + +template +typename range_iterator::type +search_n(const ForwardRange& rng, Integer n, const Value& value); + +template +typename range_iterator::type +search_n(ForwardRange& rng, Integer n, const Value& value, + BinaryPredicate binary_pred); + +template +typename range_iterator::type +search_n(const ForwardRange& rng, Integer n, const Value& value, + BinaryPredicate binary_pred); +`` + +[heading Description] + +`search_n` searches `rng` for a sequence of length `n` equal to `value` where +equality is determined by operator== in the non-predicate case, and by a +predicate when one is supplied. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/search_n.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange`'s value type is a model of the `EqualityComparableConcept`. +* `ForwardRange`s value type can be compared for equality with `Value`. +* `Integer` is a model of the `IntegerConcept`. + +[*For the predicate versions:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `BinaryPredicate` is a model of the `BinaryPredicateConcept`. +* `ForwardRange`'s value type is convertible to `BinaryPredicate`'s first argument type. +* `Value` is convertible to `BinaryPredicate`'s second argument type. +* `Integer` is a model of the `IntegerConcept`. + +[heading Complexity] + +Average complexity is Linear. Worst-case complexity is quadratic. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/set_difference.qbk b/libs/range/doc/reference/algorithm/set_difference.qbk new file mode 100644 index 00000000..8ab5091a --- /dev/null +++ b/libs/range/doc/reference/algorithm/set_difference.qbk @@ -0,0 +1,81 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:set_difference set_difference] + +[heading Prototype] + +`` +template< + class SinglePassRange1, + class SinglePassRange2, + class OutputIterator + > +OutputIterator set_difference(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out); + +template< + class SinglePassRange1, + class SinglePassRange2, + class OutputIterator, + class BinaryPredicate + > +OutputIterator set_difference(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out, + BinaryPredicate pred); +`` + +[heading Description] + +`set_difference` constructs a sorted range that is the set difference of the sorted ranges `rng1` and `rng2`. The return value is the end of the output range. + +The ordering relationship is determined by using `operator<` in the non-predicate versions, and by evaluating `pred` in the predicate versions. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/set_algorithm.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `OutputIterator` is a model of the `OutputIteratorConcept`. +* `SinglePassRange1` and `SinglePassRange2` have the same value type. +* `SinglePassRange1`'s value type is a model of the `LessThanComparableConcept`. +* `SinglePassRange2`'s value type is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `SinglePassRange1`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. +* The ordering of objects of type `SinglePassRange2`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + +[*For the predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `OutputIterator` is a model of the `OutputIteratorConcept`. +* `SinglePassRange1` and `SinglePassRange2` have the same value type. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `SinglePassRange1`'s value type is convertible to `BinaryPredicate`'s first argument type. +* `SinglePassRange2`'s value type is convertible to `BinaryPredicate`'s second argument types. + +[heading Precondition:] + +[*For the non-predicate versions:] + +`rng1` and `rng2` are sorted in ascending order according to `operator<`. + +[*For the predicate versions:] + +`rng1` and `rng2` are sorted in ascending order according to `pred`. + +[heading Complexity] + +Linear. `O(N)`, where `N` is `distance(rng1) + distance(rng2)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/set_intersection.qbk b/libs/range/doc/reference/algorithm/set_intersection.qbk new file mode 100644 index 00000000..3d46109e --- /dev/null +++ b/libs/range/doc/reference/algorithm/set_intersection.qbk @@ -0,0 +1,81 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:set_intersection set_intersection] + +[heading Prototype] + +`` +template< + class SinglePassRange1, + class SinglePassRange2, + class OutputIterator + > +OutputIterator set_intersection(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out); + +template< + class SinglePassRange1, + class SinglePassRange2, + class OutputIterator, + class BinaryPredicate + > +OutputIterator set_intersection(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out, + BinaryPredicate pred); +`` + +[heading Description] + +`set_intersection` constructs a sorted range that is the intersection of the sorted ranges `rng1` and `rng2`. The return value is the end of the output range. + +The ordering relationship is determined by using `operator<` in the non-predicate versions, and by evaluating `pred` in the predicate versions. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/set_algorithm.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `OutputIterator` is a model of the `OutputIteratorConcept`. +* `SinglePassRange1` and `SinglePassRange2` have the same value type. +* `SinglePassRange1`'s value type is a model of the `LessThanComparableConcept`. +* `SinglePassRange2`'s value type is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `SinglePassRange1`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. +* The ordering of objects of type `SinglePassRange2`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + +[*For the predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `OutputIterator` is a model of the `OutputIteratorConcept`. +* `SinglePassRange1` and `SinglePassRange2` have the same value type. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `SinglePassRange1`'s value type is convertible to `BinaryPredicate`'s first argument type. +* `SinglePassRange2`'s value type is convertible to `BinaryPredicate`'s second argument types. + +[heading Precondition:] + +[*For the non-predicate versions:] + +`rng1` and `rng2` are sorted in ascending order according to `operator<`. + +[*For the predicate versions:] + +`rng1` and `rng2` are sorted in ascending order according to `pred`. + +[heading Complexity] + +Linear. `O(N)`, where `N` is `distance(rng1) + distance(rng2)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/set_symmetric_difference.qbk b/libs/range/doc/reference/algorithm/set_symmetric_difference.qbk new file mode 100644 index 00000000..9110cf07 --- /dev/null +++ b/libs/range/doc/reference/algorithm/set_symmetric_difference.qbk @@ -0,0 +1,83 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:set_symmetric_difference set_symmetric_difference] + +[heading Prototype] + +`` +template< + class SinglePassRange1, + class SinglePassRange2, + class OutputIterator + > +OutputIterator +set_symmetric_difference(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out); + +template< + class SinglePassRange1, + class SinglePassRange2, + class OutputIterator, + class BinaryPredicate + > +OutputIterator +set_symmetric_difference(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out, + BinaryPredicate pred); +`` + +[heading Description] + +`set_symmetric_difference` constructs a sorted range that is the set symmetric difference of the sorted ranges `rng1` and `rng2`. The return value is the end of the output range. + +The ordering relationship is determined by using `operator<` in the non-predicate versions, and by evaluating `pred` in the predicate versions. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/set_algorithm.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `OutputIterator` is a model of the `OutputIteratorConcept`. +* `SinglePassRange1` and `SinglePassRange2` have the same value type. +* `SinglePassRange1`'s value type is a model of the `LessThanComparableConcept`. +* `SinglePassRange2`'s value type is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `SinglePassRange1`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. +* The ordering of objects of type `SinglePassRange2`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + +[*For the predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `OutputIterator` is a model of the `OutputIteratorConcept`. +* `SinglePassRange1` and `SinglePassRange2` have the same value type. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `SinglePassRange1`'s value type is convertible to `BinaryPredicate`'s first argument type. +* `SinglePassRange2`'s value type is convertible to `BinaryPredicate`'s second argument types. + +[heading Precondition:] + +[*For the non-predicate versions:] + +`rng1` and `rng2` are sorted in ascending order according to `operator<`. + +[*For the predicate versions:] + +`rng1` and `rng2` are sorted in ascending order according to `pred`. + +[heading Complexity] + +Linear. `O(N)`, where `N` is `distance(rng1) + distance(rng2)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/set_union.qbk b/libs/range/doc/reference/algorithm/set_union.qbk new file mode 100644 index 00000000..679ec71c --- /dev/null +++ b/libs/range/doc/reference/algorithm/set_union.qbk @@ -0,0 +1,80 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:set_union set_union] + +[heading Prototype] + +`` +template< + class SinglePassRange1, + class SinglePassRange2, + class OutputIterator + > +OutputIterator set_union(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out); + +template< + class SinglePassRange1, + class SinglePassRange2, + class OutputIterator, + class BinaryPredicate + > +OutputIterator set_union(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out, + BinaryPredicate pred); + `` + +[heading Description] + +`set_union` constructs a sorted range that is the union of the sorted ranges `rng1` and `rng2`. The return value is the end of the output range. +The ordering relationship is determined by using `operator<` in the non-predicate versions, and by evaluating `pred` in the predicate versions. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/set_algorithm.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `OutputIterator` is a model of the `OutputIteratorConcept`. +* `SinglePassRange1` and `SinglePassRange2` have the same value type. +* `SinglePassRange1`'s value type is a model of the `LessThanComparableConcept`. +* `SinglePassRange2`'s value type is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `SinglePassRange1`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. +* The ordering of objects of type `SinglePassRange2`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + +[*For the predicate versions:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `OutputIterator` is a model of the `OutputIteratorConcept`. +* `SinglePassRange1` and `SinglePassRange2` have the same value type. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `SinglePassRange1`'s value type is convertible to `BinaryPredicate`'s first argument type. +* `SinglePassRange2`'s value type is convertible to `BinaryPredicate`'s second argument types. + +[heading Precondition:] + +[*For the non-predicate versions:] + +`rng1` and `rng2` are sorted in ascending order according to `operator<`. + +[*For the predicate versions:] + +`rng1` and `rng2` are sorted in ascending order according to `pred`. + +[heading Complexity] + +Linear. `O(N)`, where `N` is `distance(rng1) + distance(rng2)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/sort.qbk b/libs/range/doc/reference/algorithm/sort.qbk new file mode 100644 index 00000000..3027c891 --- /dev/null +++ b/libs/range/doc/reference/algorithm/sort.qbk @@ -0,0 +1,58 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:sort sort] + +[heading Prototype] + +`` +template +RandomAccessRange& sort(RandomAccessRange& rng); + +template +const RandomAccessRange& sort(const RandomAccessRange& rng); + +template +RandomAccessRange& sort(RandomAccessRange& rng, BinaryPredicate pred); + +template +const RandomAccessRange& sort(const RandomAccessRange& rng, BinaryPredicate pred); +`` + +[heading Description] + +`sort` sorts the elements in `rng` into ascending order. `sort` is not guaranteed to be stable. Returns the sorted range. + +For versions of the `sort` function without a predicate, ascending order is defined by `operator<()` such that for all adjacent elements `[x,y]`, `y < x == false`. + +For versions of the `sort` function with a predicate, ascending order is defined by `pred` such that for all adjacent elements `[x,y]`, `pred(y, x) == false`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/sort.hpp` + +[heading Requirements] + +[*For versions of sort without a predicate:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `RandomAccessRange`'s value type is a model of the `LessThanComparableConcept`. +* The ordering relation on `RandomAccessRange`'s value type is a [*strict weak ordering], as defined in the `LessThanComparableConcept` requirements. + +[*For versions of sort with a predicate] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `RandomAccessRange`'s value type is convertible to both of `BinaryPredicate`'s argument types. + +[heading Complexity] + +`O(N log(N))` comparisons (both average and worst-case), where `N` is `distance(rng)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/sort_heap.qbk b/libs/range/doc/reference/algorithm/sort_heap.qbk new file mode 100644 index 00000000..b065ce53 --- /dev/null +++ b/libs/range/doc/reference/algorithm/sort_heap.qbk @@ -0,0 +1,60 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:sort_heap sort_heap] + +[heading Prototype] + +`` +template +RandomAccessRange& sort_heap(RandomAccessRange& rng); + +template +const RandomAccessRange& sort_heap(const RandomAccessRange& rng); + +template +RandomAccessRange& sort_heap(RandomAccessRange& rng, Compare pred); + +template +const RandomAccessRange& sort_heap(const RandomAccessRange& rng, Compare pred); +`` + +[heading Description] + +`sort_heap` turns a heap into a sorted range. + +The ordering relationship is determined by using `operator<` in the non-predicate versions, and by evaluating `pred` in the predicate versions. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/heap_algorithm.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `RandomAccessRange`'s value type is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `RandomAccessRange`'s value type is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. + +[*For the predicate versions:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `Compare` is a model of the `StrictWeakOrderingConcept`. +* `RandomAccessRange`'s value type is convertible to both of `Compare`'s argument types. + +[heading Precondition:] + +`rng` is a heap. + +[heading Complexity] + +At most `N * log(N)` comparisons, where `N` is `distance(rng)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/stable_partition.qbk b/libs/range/doc/reference/algorithm/stable_partition.qbk new file mode 100644 index 00000000..a820bcdb --- /dev/null +++ b/libs/range/doc/reference/algorithm/stable_partition.qbk @@ -0,0 +1,61 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:stable_partition stable_partition] + +[heading Prototype] + +`` +template +typename range_iterator::type +stable_partition(ForwardRange& rng, UnaryPredicate pred); + +template +typename range_iterator::type +stable_partition(const ForwardRange& rng, UnaryPredicate pred); + +template< + range_return_value re, + class ForwardRange, + class UnaryPredicate +> +typename range_return::type +stable_partition(ForwardRange& rng, UnaryPredicate pred); + +template< + range_return_value re, + class ForwardRange, + class UnaryPredicate +> +typename range_return::type +stable_partition(const ForwardRange& rng, UnaryPredicate pred); +`` + +[heading Description] + +`stable_partition` reorders the elements in the range `rng` base on the function object `pred`. Once this function has completed all of the elements that satisfy `pred` appear before all of the elements that fail to satisfy it. `stable_partition` differs from `partition` because it preserves relative order. It is stable. + +For the versions that return an iterator, the return value is the iterator to the first element that fails to satisfy `pred`. + +For versions that return a `range_return`, the `found` iterator is the iterator to the first element that fails to satisfy `pred`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/stable_partition.hpp` + +[heading Requirements] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `UnaryPredicate` is a model of the `PredicateConcept`. + +[heading Complexity] + +Best case: `O(N)` where `N` is `distance(rng)`. +Worst case: `N * log(N)` swaps, where `N` is `distance(rng)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/stable_sort.qbk b/libs/range/doc/reference/algorithm/stable_sort.qbk new file mode 100644 index 00000000..502551f5 --- /dev/null +++ b/libs/range/doc/reference/algorithm/stable_sort.qbk @@ -0,0 +1,59 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:stable_sort stable_sort] + +[heading Prototype] + +`` +template +RandomAccessRange& stable_sort(RandomAccessRange& rng); + +template +const RandomAccessRange& stable_sort(const RandomAccessRange& rng); + +template +RandomAccessRange& stable_sort(RandomAccessRange& rng, BinaryPredicate pred); + +template +const RandomAccessRange& stable_sort(const RandomAccessRange& rng, BinaryPredicate pred); +`` + +[heading Description] + +`stable_sort` sorts the elements in `rng` into ascending order. `stable_sort` is guaranteed to be stable. The order is preserved for equivalent elements. + +For versions of the `stable_sort` function without a predicate ascending order is defined by `operator<()` such that for all adjacent elements `[x,y]`, `y < x == false`. + +For versions of the `stable_sort` function with a predicate, ascending order is designed by `pred` such that for all adjacent elements `[x,y]`, `pred(y,x) == false`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/stable_sort.hpp` + +[heading Requirements] + +[*For versions of stable_sort without a predicate] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `RandomAccessRange`'s value type is a model of the `LessThanComparableConcept`. +* The ordering relation on `RandomAccessRange`'s value type is a [*strict weak ordering], as defined in the `LessThanComparableConcept` requirements. + +[*For versions of stable_sort with a predicate:] + +* `RandomAccessRange` is a model of the __random_access_range__ Concept. +* `RandomAccessRange` is mutable. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `RandomAccessRange`'s value type is convertible to both of `BinaryPredicate`'s argument types. + +[heading Complexity] + +Best case: `O(N)` where `N` is `distance(rng)`. +Worst case: `O(N log(N)^2)` comparisons, where `N` is `distance(rng)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/swap_ranges.qbk b/libs/range/doc/reference/algorithm/swap_ranges.qbk new file mode 100644 index 00000000..9dcb764c --- /dev/null +++ b/libs/range/doc/reference/algorithm/swap_ranges.qbk @@ -0,0 +1,37 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:swap_ranges swap_ranges] + +[heading Prototype] + +`` +template +SinglePassRange2& swap_ranges(SinglePassRange1& rng1, SinglePassRange& rng2); +`` + +[heading Description] + +`swap_ranges` swaps each element `x` in `rng1` with the corresponding element `y` in `rng2`. +Returns a reference to `rng2`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/swap_ranges.hpp` + +[heading Requirements] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange1` is mutable. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is mutable. + +[heading Complexity] + +Linear. Exactly `distance(rng1)` elements are swapped. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/transform.qbk b/libs/range/doc/reference/algorithm/transform.qbk new file mode 100644 index 00000000..d1e5ac44 --- /dev/null +++ b/libs/range/doc/reference/algorithm/transform.qbk @@ -0,0 +1,88 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:transform transform] + +[heading Prototype] + +`` +template< + class SinglePassRange1, + class OutputIterator, + class UnaryOperation +> +OutputIterator transform(const SinglePassRange1& rng, + OutputIterator out, + UnaryOperation fun); + +template< + class SinglePassRange1, + class SinglePassRange2, + class OutputIterator, + class BinaryOperation +> +OutputIterator transform(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out, + BinaryOperation fun); +`` + +[heading Description] + +[*UnaryOperation version:] + +`transform` assigns the value `y` to each element `[out, out + distance(rng)), y = fun(x)` where `x` is the corresponding value to `y` in `rng1`. The return value is `out + distance(rng)`. + +[*BinaryOperation version:] + +`transform` assigns the value `z` to each element `[out, out + min(distance(rng1), distance(rng2))), z = fun(x,y)` where `x` is the corresponding value in `rng1` and `y` is the corresponding value in `rng2`. This version of `transform` stops upon reaching either the end of `rng1`, or the end of `rng2`. Hence there isn't a requirement for `distance(rng1) == distance(rng2)` since there is a safe guaranteed behaviour, unlike with the iterator counterpart in the standard library. + +The return value is `out + min(distance(rng1), distance(rng2))`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/transform.hpp` + +[heading Requirements] + +[*For the unary versions of transform:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `OutputIterator` is a model of the `OutputIteratorConcept`. +* `UnaryOperation` is a model of the `UnaryFunctionConcept`. +* `SinglePassRange1`'s value type must be convertible to `UnaryFunction`'s argument type. +* `UnaryFunction`'s result type must be convertible to a type in `OutputIterator`'s set of value types. + +[*For the binary versions of transform:] + +* `SinglePassRange1` is a model of the __single_pass_range__ Concept. +* `SinglePassRange2` is a model of the __single_pass_range__ Concept. +* `OutputIterator` is a model of the `OutputIteratorConcept`. +* `BinaryOperation` is a model of the `BinaryFunctionConcept`. +* `SinglePassRange1`'s value type must be convertible to `BinaryFunction`'s first argument type. +* `SinglePassRange2`'s value type must be convertible to `BinaryFunction`'s second argument type. +* `BinaryOperation`'s result type must be convertible to a type in `OutputIterator`'s set of value types. + +[heading Precondition:] + +[*For the unary version of transform:] + +* `out` is not an iterator within the range `[begin(rng1) + 1, end(rng1))`. +* `[out, out + distance(rng1))` is a valid range. + +[*For the binary version of transform:] + +* `out` is not an iterator within the range `[begin(rng1) + 1, end(rng1))`. +* `out` is not an iterator within the range `[begin(rng2) + 1, end(rng2))`. +* `[out, out + min(distance(rng1), distance(rng2)))` is a valid range. + + +[heading Complexity] + +Linear. The operation is applied exactly `distance(rng1)` for the unary version and `min(distance(rng1), distance(rng2))` for the binary version. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/unique.qbk b/libs/range/doc/reference/algorithm/unique.qbk new file mode 100644 index 00000000..bc2cdcea --- /dev/null +++ b/libs/range/doc/reference/algorithm/unique.qbk @@ -0,0 +1,77 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:unique unique] + +[heading Prototype] + +`` +template +typename range_return::type +unique(ForwardRange& rng); + +template +typename range_return::type +unique(const ForwardRange& rng); + +template +typename range_return::type +unique(ForwardRange& rng, BinaryPredicate pred); + +template +typename range_return::type +unique(const ForwardRange& rng, BinaryPredicate pred); + +template +typename range_return::type +unique(ForwardRange& rng); + +template +typename range_return::type +unique(const ForwardRange& rng); + +template +typename range_return::type +unique(ForwardRange& rng, BinaryPredicate pred); + +template +typename range_return::type +unique(const ForwardRange& rng, BinaryPredicate pred); +`` + +[heading Description] + +`unique` removes all but the first element of each sequence of duplicate encountered in `rng`. + +Elements in the range `[new_last, end(rng))` are dereferenceable but undefined. + +Equality is determined by the predicate if one is supplied, or by `operator==()` for `ForwardRange`'s value type. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/unique.hpp` + +[heading Requirements] + +[*For the non-predicate versions of unique:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `ForwardRange`'s value type is a model of the `EqualityComparableConcept`. + +[*For the predicate versions of unique:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `ForwardRange` is mutable. +* `BinaryPredicate` is a model of the `BinaryPredicateConcept`. +* `ForwardRange`'s value type is convertible to `BinaryPredicate`'s first argument type and to `BinaryPredicate`'s second argument type. + +[heading Complexity] + +Linear. `O(N)` where `N` is `distance(rng)`. Exactly `distance(rng)` comparisons are performed. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm/unique_copy.qbk b/libs/range/doc/reference/algorithm/unique_copy.qbk new file mode 100644 index 00000000..f10a85fb --- /dev/null +++ b/libs/range/doc/reference/algorithm/unique_copy.qbk @@ -0,0 +1,49 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:unique_copy unique_copy] + +[heading Prototype] + +`` +template +OutputIterator unique_copy(const SinglePassRange& rng, OutputIterator out); + +template +OutputIterator unique_copy(const SinglePassRange& rng, OutputIterator out, BinaryPredicate pred); +`` + +[heading Description] + +`unique_copy` copies the first element of each sequence of duplicates encountered in `rng` to `out`. + +Equality is determined by the predicate if one is supplied, or by `operator==()` for `SinglePassRange`'s value type. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/unique_copy.hpp` + +[heading Requirements] + +[*For the non-predicate versions of unique:] + +* `SinglePassRange` is a model of the __single_pass_range__ Concept. +* `SinglePassRange` is mutable. +* `SinglePassRange`'s value type is a model of the `EqualityComparableConcept`. +* `OutputIterator` is a model of the `OutputIteratorConcept`. + +[*For the predicate versions of unique:] + +* `SinglePassRange` is a model of the __single_pass_range__ Concept. +* `SinglePassRange` is mutable. +* `BinaryPredicate` is a model of the `BinaryPredicateConcept`. +* `SinglePassRange`'s value type is convertible to `BinaryPredicate`'s first argument type and to `BinaryPredicate`'s second argument type. +* `OutputIterator` is a model of the `OutputIteratorConcept`. + +[heading Complexity] + +Linear. `O(N)` where `N` is `distance(rng)`. Exactly `distance(rng)` comparisons are performed. + +[endsect] diff --git a/libs/range/doc/reference/algorithm/upper_bound.qbk b/libs/range/doc/reference/algorithm/upper_bound.qbk new file mode 100644 index 00000000..d636a77b --- /dev/null +++ b/libs/range/doc/reference/algorithm/upper_bound.qbk @@ -0,0 +1,90 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:upper_bound upper_bound] + +[heading Prototype] + +`` +template< + class ForwardRange, + class Value + > +typename range_iterator::type +upper_bound(ForwardRange& rng, Value val); + +template< + range_return_value re, + class ForwardRange, + class Value + > +typename range_return::type +upper_bound(ForwardRange& rng, Value val); + +template< + class ForwardRange, + class Value, + class SortPredicate + > +typename range_iterator::type +upper_bound(ForwardRange& rng, Value val, SortPredicate pred); + +template< + range_return_value re, + class ForwardRange, + class Value, + class SortPredicate + > +typename range_return::type +upper_bound(ForwardRange& rng, Value val, SortPredicate pred); +`` + +[heading Description] + +The versions of `upper_bound` that return an iterator, returns the first iterator in the range `rng` such that: +without predicate - `val < *i` is `true`, +with predicate - `pred(val, *i)` is `true`. + +`end(rng)` is returned if no such iterator exists. + +The versions of `upper_bound` that return a `range_return`, defines `found` in the same manner as the returned iterator described above. + +[heading Definition] + +Defined in the header file `boost/range/algorithm/upper_bound.hpp` + +[heading Requirements] + +[*For the non-predicate versions:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `Value` is a model of the `LessThanComparableConcept`. +* The ordering of objects of type `Value` is a [*/strict weak ordering/], as defined in the `LessThanComparableConcept` requirements. +* `ForwardRange`'s value type is the same type as `Value`. + +[*For the predicate versions:] + +* `ForwardRange` is a model of the __forward_range__ Concept. +* `BinaryPredicate` is a model of the `StrictWeakOrderingConcept`. +* `ForwardRange`'s value type is the same type as `Value`. +* `ForwardRange`'s value type is convertible to both of `BinaryPredicate`'s argument types. + +[heading Precondition:] + +[*For the non-predicate versions:] + +`rng` is sorted in ascending order according to `operator<`. + +[*For the predicate versions:] + +`rng` is sorted in ascending order according to `pred`. + +[heading Complexity] + +For ranges that model the __random_access_range__ Concept the complexity is `O(log N)`, where `N` is `distance(rng)`. For all other range types the complexity is `O(N)`. + +[endsect] + + diff --git a/libs/range/doc/reference/algorithm_ext/copy_n.qbk b/libs/range/doc/reference/algorithm_ext/copy_n.qbk new file mode 100644 index 00000000..6b34c7bf --- /dev/null +++ b/libs/range/doc/reference/algorithm_ext/copy_n.qbk @@ -0,0 +1,37 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:copy_n copy_n] + +[heading Prototype] + +`` +template +OutputIterator copy_n(const SinglePassRange& rng, Size n, OutputIterator out); +`` + +[heading Description] + +`copy_n` is provided to completely replicate the standard algorithm header, +it is preferable to use Range Adaptors and the extension functions to achieve +the same result with greater safety. + +`copy_n` copies elements from `[boost::begin(rng), boost::begin(rng) + n)` to the range `[out, out + n)` + +[heading Definition] + +Defined in the header file `boost/range/algorithm_ext/copy_n.hpp` + +[heading Requirements] + +# `SinglePassRange` is a model of the __single_pass_range__ Concept. +# `Size` is a model of the `Integer` Concept. +# `OutputIterator` is a model of the `OutputIteratorConcept`. + +[heading Complexity] + +Linear. Exactly `n` elements are copied. + +[endsect] diff --git a/libs/range/doc/reference/algorithm_ext/erase.qbk b/libs/range/doc/reference/algorithm_ext/erase.qbk new file mode 100644 index 00000000..5b640a28 --- /dev/null +++ b/libs/range/doc/reference/algorithm_ext/erase.qbk @@ -0,0 +1,37 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:erase erase] + +[heading Prototype] + +`` +template +Container& erase( + Container& target, + iterator_range to_erase); +`` + +[heading Description] + +`erase` the iterator range `to_erase` from the container `target`. + +`remove_erase` performs the frequently used combination equivalent to `target.erase(std::remove(target.begin(), target.end(), value), target.end());` + +`remove_erase_if` performs the frequently used combination equivalent to `target.erase(std::remove_if(target.begin(), target.end(), pred), target.end());` + +[heading Definition] + +Defined in the header file `boost/range/algorithm_ext/erase.hpp` + +[heading Requirements] + +# `Container` supports erase of an iterator range. + +[heading Complexity] + +Linear. Proprotional to `distance(to_erase)`. + +[endsect] diff --git a/libs/range/doc/reference/algorithm_ext/for_each.qbk b/libs/range/doc/reference/algorithm_ext/for_each.qbk new file mode 100644 index 00000000..fdfcb999 --- /dev/null +++ b/libs/range/doc/reference/algorithm_ext/for_each.qbk @@ -0,0 +1,73 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:for_each for_each] + +[heading Prototype] + +`` +template< + class SinglePassRange1, + class SinglePassRange2, + class BinaryFunction + > +BinaryFunction for_each(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + BinaryFunction fn); + +template< + class SinglePassRange1, + class SinglePassRange2, + class BinaryFunction + > +BinaryFunction for_each(const SinglePassRange1& rng1, + SinglePassRange2& rng2, + BinaryFunction fn); + +template< + class SinglePassRange1, + class SinglePassRange2, + class BinaryFunction + > +BinaryFunction for_each(SinglePassRange1& rng1, + const SinglePassRange2& rng2, + BinaryFunction fn); + +template< + class SinglePassRange1, + class SinglePassRange2, + class BinaryFunction + > +BinaryFunction for_each(SinglePassRange1& rng1, + SinglePassRange2& rng2, + BinaryFunction fn); +`` + +[heading Description] + +`for_each` traverses forward through `rng1` and `rng2` simultaneously. +For each iteration, the element `x` is used from `rng1` and the corresponding +element `y` is used from `rng2` to invoke `fn(x,y)`. + +Iteration is stopped upon reaching the end of the shorter of `rng1`, or `rng2`. +It is safe to call this function with unequal length ranges. + +[heading Definition] + +Defined in the header file `boost/range/algorithm_ext/for_each.hpp` + +[heading Requirements] + +# `SinglePassRange1` is a model of the __single_pass_range__ Concept. +# `SinglePassRange2` is a model of the __single_pass_range__ Concept. +# `BinaryFunction` is a model of the `BinaryFunctionConcept`. +# `SinglePassRange1`'s value type is convertible to `BinaryFunction`'s first argument type. +# `SinglepassRange2`'s value type is convertible to `BinaryFunction`'s second argument type. + +[heading Complexity] + +Linear. Exactly `min(distance(rng1), distance(rng2))` applications of `BinaryFunction`. + +[endsect] diff --git a/libs/range/doc/reference/algorithm_ext/insert.qbk b/libs/range/doc/reference/algorithm_ext/insert.qbk new file mode 100644 index 00000000..e9f48ebc --- /dev/null +++ b/libs/range/doc/reference/algorithm_ext/insert.qbk @@ -0,0 +1,46 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:insert insert] + +[heading Prototype] + +`` +template< + class Container, + class SinglePassRange +> +Container& insert(Container& target, + typename Container::iterator before, + const SinglePassRange& from); + +// This overload is for target containers that do not require an insertion +// position e.g. set/map +template< + class Container, + class SinglePassRange +> +Container& insert(Container& target, const SinglePassRange& from); +`` + +[heading Description] + +`insert` all of the elements in the range `from` before the `before` iterator into `target`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm_ext/insert.hpp` + +[heading Requirements] + +# `SinglePassRange` is a model of the __single_pass_range__ Concept. +# `Container` supports insert at a specified position. +# `SinglePassRange`'s value type is convertible to `Container`'s value type. + +[heading Complexity] + +Linear. `distance(from)` assignments are performed. + +[endsect] diff --git a/libs/range/doc/reference/algorithm_ext/iota.qbk b/libs/range/doc/reference/algorithm_ext/iota.qbk new file mode 100644 index 00000000..0a5f7996 --- /dev/null +++ b/libs/range/doc/reference/algorithm_ext/iota.qbk @@ -0,0 +1,33 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:iota iota] + +[heading Prototype] + +`` +template +ForwardRange& iota(ForwardRange& rng, Value x); +`` + +[heading Description] + +`iota` traverses forward through `rng`, each element `y` in `rng` is assigned a value equivalent +to `x + boost::distance(boost::begin(rng), it)` + +[heading Definition] + +Defined in the header file `boost/range/algorithm_ext/iota.hpp` + +[heading Requirements] + +# `ForwardRange` is a model of the __forward_range__ Concept. +# `Value` is a model of the `Incrementable` Concept. + +[heading Complexity] + +Linear. Exactly `distance(rng)` assignments into `rng`. + +[endsect] diff --git a/libs/range/doc/reference/algorithm_ext/is_sorted.qbk b/libs/range/doc/reference/algorithm_ext/is_sorted.qbk new file mode 100644 index 00000000..f9c07b4f --- /dev/null +++ b/libs/range/doc/reference/algorithm_ext/is_sorted.qbk @@ -0,0 +1,40 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:is_sorted is_sorted] + +[heading Prototype] + +`` +template +bool is_sorted(const SinglePassRange& rng); + +template +bool is_sorted(const SinglePassRange& rng, BinaryPredicate pred); +`` + +[heading Description] + +`is_sorted` determines if a range is sorted. +For the non-predicate version the return value is `true` if and only if for +each adjacent elements `[x,y]` the expression `x < y` is `true`. +For the predicate version the return value is `true` is and only if for each +adjacent elements `[x,y]` the expression `pred(x,y)` is `true`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm_ext/is_sorted.hpp` + +[heading Requirements] + +# `SinglePassRange` is a model of the __single_pass_range__ Concept. +# `BinaryPredicate` is a model of the `BinaryPredicate` Concept. +# The value type of `SinglePassRange` is convertible to both argument types of `BinaryPredicate`. + +[heading Complexity] + +Linear. A maximum of `distance(rng)` comparisons are performed. + +[endsect] diff --git a/libs/range/doc/reference/algorithm_ext/overwrite.qbk b/libs/range/doc/reference/algorithm_ext/overwrite.qbk new file mode 100644 index 00000000..a265833c --- /dev/null +++ b/libs/range/doc/reference/algorithm_ext/overwrite.qbk @@ -0,0 +1,39 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:overwrite overwrite] + +[heading Prototype] + +`` +template< + class SinglePassRange1, + class SinglePassRange2 + > +void overwrite(const SinglePassRange1& from, + SinglePassRange2& to); +`` + +[heading Description] + +`overwrite` assigns the values from the range `from` into the range `to`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm_ext/overwrite.hpp` + +[heading Requirements] + +# `SinglePassRange1` is a model of the __single_pass_range__ Concept. +# `SinglePassRange2` is a model of the __single_pass_range__ Concept. +# `SinglePassRange2` is mutable. +# `distance(SinglePassRange1) <= distance(SinglePassRange2)` +# `SinglePassRange1`'s value type is convertible to `SinglePassRange2`'s value type. + +[heading Complexity] + +Linear. `distance(rng1)` assignments are performed. + +[endsect] diff --git a/libs/range/doc/reference/algorithm_ext/push_back.qbk b/libs/range/doc/reference/algorithm_ext/push_back.qbk new file mode 100644 index 00000000..ec46d0b6 --- /dev/null +++ b/libs/range/doc/reference/algorithm_ext/push_back.qbk @@ -0,0 +1,37 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:push_back push_back] + +[heading Prototype] + +`` +template< + class Container, + class SinglePassRange + > +Container& push_back(Container& target, + const SinglePassRange& from); +`` + +[heading Description] + +`push_back` all of the elements in the range `from` to the back of the container `target`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm_ext/push_back.hpp` + +[heading Requirements] + +# `SinglePassRange` is a model of the __single_pass_range__ Concept. +# `Container` supports insert at `end()`. +# `SinglePassRange`'s value type is convertible to `Container`'s value type. + +[heading Complexity] + +Linear. `distance(from)` assignments are performed. + +[endsect] diff --git a/libs/range/doc/reference/algorithm_ext/push_front.qbk b/libs/range/doc/reference/algorithm_ext/push_front.qbk new file mode 100644 index 00000000..d9ca4fe2 --- /dev/null +++ b/libs/range/doc/reference/algorithm_ext/push_front.qbk @@ -0,0 +1,37 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:push_front push_front] + +[heading Prototype] + +`` +template< + class Container, + class SinglePassRange + > +Container& push_front(Container& target, + const SinglePassRange& from); +`` + +[heading Description] + +`push_front` all of the elements in the range `from` to the front of the container `target`. + +[heading Definition] + +Defined in the header file `boost/range/algorithm_ext/push_front.hpp` + +[heading Requirements] + +# `SinglePassRange` is a model of the __single_pass_range__ Concept. +# `Container` supports insert at `begin()`. +# `SinglePassRange`'s value type is convertible to `Container`'s value type. + +[heading Complexity] + +Linear. `distance(from)` assignments are performed. + +[endsect] diff --git a/libs/range/doc/reference/algorithm_ext/remove_erase.qbk b/libs/range/doc/reference/algorithm_ext/remove_erase.qbk new file mode 100644 index 00000000..eecc97b6 --- /dev/null +++ b/libs/range/doc/reference/algorithm_ext/remove_erase.qbk @@ -0,0 +1,33 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:remove_erase remove_erase] + +[heading Prototype] + +`` +template +Container& remove_erase(Container& target, + const Value& value); +`` + +[heading Description] + +`remove_erase` actually eliminates the elements equal to `value` from the container. This +is in contrast to the `remove` algorithm which merely rearranges elements. + +[heading Definition] + +Defined in the header file `boost/range/algorithm_ext/erase.hpp` + +[heading Requirements] + +# `Container` supports erase of an iterator range. + +[heading Complexity] + +Linear. Proportional to `distance(target)`s. + +[endsect] diff --git a/libs/range/doc/reference/algorithm_ext/remove_erase_if.qbk b/libs/range/doc/reference/algorithm_ext/remove_erase_if.qbk new file mode 100644 index 00000000..5eab4466 --- /dev/null +++ b/libs/range/doc/reference/algorithm_ext/remove_erase_if.qbk @@ -0,0 +1,34 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:remove_erase_if remove_erase_if] + +[heading Prototype] + +`` +template +Container& remove_erase_if(Container& target, + Pred pred); +`` + +[heading Description] + +`remove_erase_if` removes the elements `x` that satisfy `pred(x)` from the container. +This is in contrast to the `erase` algorithm which merely rearranges elements. + +[heading Definition] + +Defined in the header file `boost/range/algorithm_ext/erase.hpp` + +[heading Requirements] + +# `Container` supports erase of an iterator range. +# `Pred` is a model of the `Predicate` Concept. + +[heading Complexity] + +Linear. Proportional to `distance(target)`s. + +[endsect] diff --git a/libs/range/doc/reference/algorithms.qbk b/libs/range/doc/reference/algorithms.qbk new file mode 100644 index 00000000..8dcd8489 --- /dev/null +++ b/libs/range/doc/reference/algorithms.qbk @@ -0,0 +1,182 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:algorithms Range Algorithms] +[section:introduction Introduction and motivation] +In its most simple form a [*Range Algorithm] (or range-based algorithm) is simply an iterator-based algorithm where the /two/ iterator arguments have been replaced by /one/ range argument. For example, we may write + +`` +#include +#include + +std::vector vec = ...; +boost::sort(vec); +`` + +instead of + +`` +std::sort(vec.begin(), vec.end()); +`` + +However, the return type of range algorithms is almost always different from that of existing iterator-based algorithms. + +One group of algorithms, like `boost::sort()`, will simply return the same range so that we can continue to pass the range around and/or further modify it. Because of this we may write +`` +boost:unique(boost::sort(vec)); +`` +to first sort the range and then run `unique()` on the sorted range. + +Algorithms like `boost::unique()` fall into another group of algorithms that return (potentially) narrowed views of the original range. By default `boost::unique(rng)` returns the range `[boost::begin(rng), found)` where `found` denotes the iterator returned by `std::unique(boost::begin(rng), boost::end(rng))` + +Therefore exactly the unique values can be copied by writing +`` +boost::copy(boost::unique(boost::sort(vec)), + std::ostream_iterator(std::cout)); +`` + +Algorithms like `boost::unique` usually return the range: `[boost::begin(rng), found)`. +However, this behaviour may be changed by supplying a `range_return_value` +as a template parameter to the algorithm: + +[table + [[Expression] [Return]] + [[`boost::unique(rng)`] [returns a single iterator like `std::unique`]] + [[`boost::unique(rng)`] [returns the range `[boost::begin(rng), found)` (this is the default)]] + [[`boost::unique(rng)`] [returns the range `[boost::begin(rng), boost::next(found))`]] + [[`boost::unique(rng)`] [returns the range `[found, boost::end(rng))`]] + [[`boost::unique(rng)`] [returns the range `[boost::next(found),boost::end(rng))`]] + [[`boost::unique(rng)`] [returns the entire original range.]] +] + +This functionality has the following advantages: + +# it allows for ['*seamless functional-style programming*] where you do not need to use named local variables to store intermediate results +# it is very ['*safe*] because the algorithm can verify out-of-bounds conditions and handle tricky conditions that lead to empty ranges + +For example, consider how easy we may erase the duplicates in a sorted container: + +`` +std::vector vec = ...; +boost::erase(vec, boost::unique(boost::sort(vec))); +`` + +Notice the use of `boost::return_found_end`. What if we wanted to erase all the duplicates except one of them? In old-fashioned STL-programming we might write + +`` +// assume 'vec' is already sorted +std::vector::iterator i = std::unique(vec.begin(), vec.end()); + +// remember this check or you get into problems +if (i != vec.end()) + ++i; + +vec.erase(i, vec.end()); +`` + +The same task may be accomplished simply with +`` +boost::erase(vec, boost::unique(vec)); +`` +and there is no need to worry about generating an invalid range. Furthermore, if the container is complex, calling `vec.end()` several times will be more expensive than using a range algorithm. + +[endsect] + +[section:mutating Mutating algorithms] +[include algorithm/copy.qbk] +[include algorithm/copy_backward.qbk] +[include algorithm/fill.qbk] +[include algorithm/fill_n.qbk] +[include algorithm/generate.qbk] +[include algorithm/inplace_merge.qbk] +[include algorithm/merge.qbk] +[include algorithm/nth_element.qbk] +[include algorithm/partial_sort.qbk] +[include algorithm/partition.qbk] +[include algorithm/random_shuffle.qbk] +[include algorithm/remove.qbk] +[include algorithm/remove_copy.qbk] +[include algorithm/remove_copy_if.qbk] +[include algorithm/remove_if.qbk] +[include algorithm/replace.qbk] +[include algorithm/replace_copy.qbk] +[include algorithm/replace_copy_if.qbk] +[include algorithm/replace_if.qbk] +[include algorithm/reverse.qbk] +[include algorithm/reverse_copy.qbk] +[include algorithm/rotate.qbk] +[include algorithm/rotate_copy.qbk] +[include algorithm/sort.qbk] +[include algorithm/stable_partition.qbk] +[include algorithm/stable_sort.qbk] +[include algorithm/swap_ranges.qbk] +[include algorithm/transform.qbk] +[include algorithm/unique.qbk] +[include algorithm/unique_copy.qbk] +[endsect] + +[section:non_mutating Non-mutating algorithms] +[include algorithm/adjacent_find.qbk] +[include algorithm/binary_search.qbk] +[include algorithm/count.qbk] +[include algorithm/count_if.qbk] +[include algorithm/equal.qbk] +[include algorithm/equal_range.qbk] +[include algorithm/for_each.qbk] +[include algorithm/find.qbk] +[include algorithm/find_end.qbk] +[include algorithm/find_first_of.qbk] +[include algorithm/find_if.qbk] +[include algorithm/lexicographical_compare.qbk] +[include algorithm/lower_bound.qbk] +[include algorithm/max_element.qbk] +[include algorithm/min_element.qbk] +[include algorithm/mismatch.qbk] +[include algorithm/search.qbk] +[include algorithm/search_n.qbk] +[include algorithm/upper_bound.qbk] +[endsect] + +[section:set Set algorithms] +[include algorithm/includes.qbk] +[include algorithm/set_union.qbk] +[include algorithm/set_intersection.qbk] +[include algorithm/set_difference.qbk] +[include algorithm/set_symmetric_difference.qbk] +[endsect] + +[section:heap Heap algorithms] +[include algorithm/push_heap.qbk] +[include algorithm/pop_heap.qbk] +[include algorithm/make_heap.qbk] +[include algorithm/sort_heap.qbk] +[endsect] + +[section:permutation Permutation algorithms] +[include algorithm/next_permutation.qbk] +[include algorithm/prev_permutation.qbk] +[endsect] + +[section:new New algorithms] +[include algorithm_ext/copy_n.qbk] +[include algorithm_ext/erase.qbk] +[include algorithm_ext/for_each.qbk] +[include algorithm_ext/insert.qbk] +[include algorithm_ext/iota.qbk] +[include algorithm_ext/is_sorted.qbk] +[include algorithm_ext/overwrite.qbk] +[include algorithm_ext/push_back.qbk] +[include algorithm_ext/push_front.qbk] +[include algorithm_ext/remove_erase.qbk] +[include algorithm_ext/remove_erase_if.qbk] +[endsect] + +[section:numeric Numeric algorithms] +[include numeric/accumulate.qbk] +[include numeric/adjacent_difference.qbk] +[include numeric/inner_product.qbk] +[include numeric/partial_sum.qbk] +[endsect] +[endsect] diff --git a/libs/range/doc/reference/extending.qbk b/libs/range/doc/reference/extending.qbk new file mode 100644 index 00000000..46652d60 --- /dev/null +++ b/libs/range/doc/reference/extending.qbk @@ -0,0 +1,328 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:extending Extending the library] + +[section:method_1 Method 1: provide member functions and nested types] + +This procedure assumes that you have control over the types that should be made conformant to a Range concept. If not, see [link range.reference.extending.method_2 method 2]. + +The primary templates in this library are implemented such that standard containers will work automatically and so will __boost_array__. Below is given an overview of which member functions and member types a class must specify to be useable as a certain Range concept. + +[table + [[Member function] [Related concept ]] + [[`begin()` ] [__single_pass_range__]] + [[`end()` ] [__single_pass_range__]] +] + +Notice that `rbegin()` and `rend()` member functions are not needed even though the container can support bidirectional iteration. + +The required member types are: + +[table + [[Member type ] [Related concept ]] + [[`iterator` ] [__single_pass_range__]] + [[`const_iterator`] [__single_pass_range__]] +] + +Again one should notice that member types `reverse_iterator` and `const_reverse_iterator` are not needed. + +[endsect] + +[section:method_2 Method 2: provide free-standing functions and specialize metafunctions] + +This procedure assumes that you cannot (or do not wish to) change the types that should be made conformant to a Range concept. If this is not true, see [link range.reference.extending.method_1 method 1]. + +The primary templates in this library are implemented such that certain functions are found via argument-dependent-lookup (ADL). Below is given an overview of which free-standing functions a class must specify to be useable as a certain Range concept. Let `x` be a variable (`const` or `mutable`) of the class in question. + +[table + [[Function ] [Related concept ]] + [[`range_begin(x)`] [__single_pass_range__]] + [[`range_end(x)` ] [__single_pass_range__]] + [[`range_calculate_size(x)`] [ Optional. This can be used to specify a mechanism for constant-time computation of the size of a range. The default behaviour is to return `boost::end(x) - boost::begin(x)` for random access ranges, and to return `x.size()` for ranges with lesser traversal capability. This behaviour can be changed by implementing `range_calculate_size` in a manner that will be found via ADL. The ability to calculate size in O(1) is often possible even with ranges with traversal categories less than random access.]] +] + +`range_begin()` and `range_end()` must be overloaded for both `const` and `mutable` reference arguments. + +You must also specialize two metafunctions for your type `X`: + +[table + [[Metafunction ] [Related concept ]] + [[`boost::range_mutable_iterator`] [__single_pass_range__]] + [[`boost::range_const_iterator`] [__single_pass_range__]] +] + +A complete example is given here: + +`` + #include + #include // for std::iterator_traits, std::distance() + + namespace Foo + { + // + // Our sample UDT. A 'Pair' + // will work as a range when the stored + // elements are iterators. + // + template< class T > + struct Pair + { + T first, last; + }; + + } // namespace 'Foo' + + namespace boost + { + // + // Specialize metafunctions. We must include the range.hpp header. + // We must open the 'boost' namespace. + // + + template< class T > + struct range_mutable_iterator< Foo::Pair > + { + typedef T type; + }; + + template< class T > + struct range_const_iterator< Foo::Pair > + { + // + // Remark: this is defined similar to 'range_iterator' + // because the 'Pair' type does not distinguish + // between an iterator and a const_iterator. + // + typedef T type; + }; + + } // namespace 'boost' + + namespace Foo + { + // + // The required functions. These should be defined in + // the same namespace as 'Pair', in this case + // in namespace 'Foo'. + // + + template< class T > + inline T range_begin( Pair& x ) + { + return x.first; + } + + template< class T > + inline T range_begin( const Pair& x ) + { + return x.first; + } + + template< class T > + inline T range_end( Pair& x ) + { + return x.last; + } + + template< class T > + inline T range_end( const Pair& x ) + { + return x.last; + } + + } // namespace 'Foo' + + #include + + int main(int argc, const char* argv[]) + { + typedef std::vector::iterator iter; + std::vector vec; + Foo::Pair pair = { vec.begin(), vec.end() }; + const Foo::Pair& cpair = pair; + // + // Notice that we call 'begin' etc with qualification. + // + iter i = boost::begin( pair ); + iter e = boost::end( pair ); + i = boost::begin( cpair ); + e = boost::end( cpair ); + boost::range_difference< Foo::Pair >::type s = boost::size( pair ); + s = boost::size( cpair ); + boost::range_reverse_iterator< const Foo::Pair >::type + ri = boost::rbegin( cpair ), + re = boost::rend( cpair ); + + return 0; + } +`` + +[endsect] + +[section:method_3 Method 3: provide range adaptor implementations] + +[section:method_3_1 Method 3.1: Implement a Range Adaptor without arguments] + +To implement a Range Adaptor without arguments (e.g. reversed) you need to: + +# Provide a range for your return type, for example: +`` +#include +#include + +template< typename R > +struct reverse_range : + boost::iterator_range< + boost::reverse_iterator< + typename boost::range_iterator::type> > +{ +private: + typedef boost::iterator_range< + boost::reverse_iterator< + typename boost::range_iterator::type> > base; + +public: + typedef boost::reverse_iterator< + typename boost::range_iterator::type > iterator; + + reverse_range(R& r) + : base(iterator(boost::end(r)), iterator(boost::begin(r))) + { } +}; +`` + +# Provide a tag to uniquely identify your adaptor in the `operator|` function overload set +`` +namespace detail { + struct reverse_forwarder {}; +} +`` + +# Implement `operator|` +`` +template< class BidirectionalRng > +inline reverse_range +operator|( BidirectionalRng& r, detail::reverse_forwarder ) +{ + return reverse_range( r ); +} + +template< class BidirectionalRng > +inline reverse_range +operator|( const BidirectionalRng& r, detail::reverse_forwarder ) +{ + return reverse_range( r ); +} +`` + +# Declare the adaptor itself (it is a variable of the tag type). +`` +namespace +{ + const detail::reverse_forwarder reversed = detail::reverse_forwarder(); +} +`` + +[endsect] + +[section:method_3_2 Method 3.2: Implement a Range Adaptor with arguments] + +# Provide a range for your return type, for example: +`` +#include +#include +#include + +template +class replace_value +{ +public: + typedef const Value& result_type; + typedef const Value& argument_type; + + replace_value(const Value& from, const Value& to) + : m_from(from), m_to(to) + { + } + + const Value& operator()(const Value& x) const + { + return (x == m_from) ? m_to : x; + } +private: + Value m_from; + Value m_to; +}; + +template +class replace_range +: public boost::iterator_range< + boost::transform_iterator< + replace_value::type>, + typename boost::range_iterator::type> > +{ +private: + typedef typename boost::range_value::type value_type; + typedef typename boost::range_iterator::type iterator_base; + typedef replace_value Fn; + typedef boost::transform_iterator replaced_iterator; + typedef boost::iterator_range base_t; + +public: + replace_range(Range& rng, value_type from, value_type to) + : base_t(replaced_iterator(boost::begin(rng), Fn(from,to)), + replaced_iterator(boost::end(rng), Fn(from,to))) + { + } + }; +`` + +# Implement a holder class to hold the arguments required to construct the RangeAdaptor. +The holder combines multiple parameters into one that can be passed as the right operand of `operator|()`. +`` +template +class replace_holder : public boost::range_detail::holder2 +{ +public: + replace_holder(const T& from, const T& to) + : boost::range_detail::holder2(from, to) + { } +private: + void operator=(const replace_holder&); +}; +`` + +# Define an instance of the holder with the name of the adaptor +`` +static boost::range_detail::forwarder2 +replaced = boost::range_detail::forwarder2(); +`` + +# Define `operator|` +`` +template +inline replace_range +operator|(SinglePassRange& rng, + const replace_holder::type>& f) +{ + return replace_range(rng, f.val1, f.val2); +} + +template +inline replace_range +operator|(const SinglePassRange& rng, + const replace_holder::type>& f) +{ + return replace_range(rng, f.val1, f.val2); +} +`` + +[endsect] + +[endsect] + +[endsect] + diff --git a/libs/range/doc/reference/numeric/accumulate.qbk b/libs/range/doc/reference/numeric/accumulate.qbk new file mode 100644 index 00000000..e151e631 --- /dev/null +++ b/libs/range/doc/reference/numeric/accumulate.qbk @@ -0,0 +1,61 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:accumulate accumulate] + +[heading Prototype] + +`` +template< + class SinglePassRange, + class Value + > +Value accumulate(const SinglePassRange& source_rng, + Value init); + +template< + class SinglePassRange, + class Value, + class BinaryOperation + > +Value accumulate(const SinglePassRange& source_rng, + Value init, + BinaryOperation op); +`` + +[heading Description] + +`accumulate` is a generalisation of summation. It computes a binary operation (`operator+` +in the non-predicate version) of `init` and all of the elements in `rng`. + +The return value is the resultant value of the above algorithm. + +[heading Definition] + +Defined in the header file `boost/range/numeric.hpp` + +[heading Requirements] + +[heading For the first version] + +# `SinglePassRange` is a model of the __single_pass_range__ Concept. +# `Value` is a model of the `AssignableConcept`. +# An `operator+` is defined for a left-hand operand of type `Value` and a right-hand operand of the `SinglePassRange` value type. +# The return type of the above operator is convertible to `Value`. + +[heading For the second version] + +# `SinglePassRange` is a model of the __single_pass_range__ Concept. +# `Value` is a model of the `AssignableConcept`. +# `BinaryOperation` is a model of the `BinaryFunctionConcept`. +# `Value` is convertible to `BinaryOperation`'s first argument type. +# `SinglePassRange`'s value type is convertible to `BinaryOperation`'s second argument type. +# The return type of `BinaryOperation` is convertible to `Value`. + +[heading Complexity] + +Linear. Exactly `distance(source_rng)`. + +[endsect] diff --git a/libs/range/doc/reference/numeric/adjacent_difference.qbk b/libs/range/doc/reference/numeric/adjacent_difference.qbk new file mode 100644 index 00000000..7580036a --- /dev/null +++ b/libs/range/doc/reference/numeric/adjacent_difference.qbk @@ -0,0 +1,68 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:adjacent_difference adjacent_difference] + +[heading Prototype] + +`` +template< + class SinglePassRange, + class OutputIterator + > +OutputIterator adjacent_difference( + const SinglePassRange& source_rng, + OutputIterator out_it); + +template< + class SinglePassRange, + class OutputIterator, + class BinaryOperation + > +OutputIterator adjacent_difference( + const SinglePassRange& source_rng, + OutputIterator out_it, + BinaryOperation op); +`` + +[heading Description] + +`adjacent_difference` calculates the differences of adjacent_elements in `rng`. + +The first version of `adjacent_difference` uses `operator-()` to calculate the differences. +The second version uses `BinaryOperation` instead of `operator-()`. + +[heading Definition] + +Defined in the header file `boost/range/numeric.hpp` + +[heading Requirements] + +[heading For the first version] + +# `SinglePassRange` is a model of the __single_pass_range__ Concept. +# `OutputIterator` is a model of the `OutputIteratorConcept`. +# If `x` and `y` are objects of `SinglePassRange`'s value type, then `x - y` is defined. +# The value type of `SinglePassRange` is convertible to a type in `OutputIterator`'s set of value types. +# The return type of `x - y` is convertible to a type in `OutputIterator`'s set of value types. + +[heading For the second version] + +# `SinglePassRange` is a model of the __single_pass_range__ Concept. +# `OutputIterator` is a model of the `OutputIteratorConcept`. +# `BinaryOperation` is a model of the `BinaryFunctionConcept`. +# The value type of `SinglePassRange` is convertible to `BinaryOperation`'s first and second argument types. +# The value type of `SinglePassRange` is convertible to a type in `OutputIterator`'s set of value types. +# The result type of `BinaryOperation` is convertible to a type in `OutputIterator`'s set of value types. + +[heading Precondition:] + +`[result, result + distance(rng))` is a valid range. + +[heading Complexity] + +Linear. If `empty(rng)` then zero applications, otherwise `distance(rng) - 1` applications are performed. + +[endsect] diff --git a/libs/range/doc/reference/numeric/inner_product.qbk b/libs/range/doc/reference/numeric/inner_product.qbk new file mode 100644 index 00000000..bb4fc3c7 --- /dev/null +++ b/libs/range/doc/reference/numeric/inner_product.qbk @@ -0,0 +1,73 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:inner_product inner_product] + +[heading Prototype] + +`` +template + Value inner_product( const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + Value init ); + +template + Value inner_product( const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + Value init, + BinaryOperation1 op1, + BinaryOperation2 op2 ); +`` + +[heading Description] + +`inner_product` calculates a generalised inner product of the range `rng1` and `rng2`. + +For further information on the `inner_product` algorithm please see __sgi_inner_product__. + +[heading Definition] + +Defined in the header file `boost/range/numeric.hpp` + +[heading Requirements] + +[heading For the first version] + +# `SinglePassRange1` is a model of the __single_pass_range__ Concept. +# `SinglePassRange2` is a model of the __single_pass_range__ Concept. +# `Value` is a model of the `AssignableConcept`. +# If `x` is an object of type `Value`, `y` is an object of `SinglePassRange1`'s value +type, and `z` is an object of `SinglePassRange2`'s value type, then `x + y * z` +is defined. +# The result type of the expression `x + y * z` is convertible to `Value`. + +[heading For the second version] + +# `SinglePassRange1` is a model of the __single_pass_range__ Concept. +# `SinglePassRange2` is a model of the __single_pass_range__ Concept. +# `Value` is a model of the `AssignableConcept`. +# `BinaryOperation1` is a model of the `BinaryFunctionConcept`. +# `BinaryOperation2` is a model of the `BinaryFunctionConcept`. +# The value type of `SinglePassRange1` is convertible to the first argument type of `BinaryOperation2`. +# The value type of `SinglePassRange2` is convertible to the second argument type of `BinaryOperation2`. +# `Value` is convertible to the value type of `BinaryOperation1`. +# The return type of `BinaryOperation2` is convertible to the second argument type of `BinaryOperation1`. +# The return type of `BinaryOperation1` is convertible to `Value`. + +[heading Precondition:] + +`distance(rng2) >= distance(rng1)` is a valid range. + +[heading Complexity] + +Linear. Exactly `distance(rng)`. + +[endsect] diff --git a/libs/range/doc/reference/numeric/partial_sum.qbk b/libs/range/doc/reference/numeric/partial_sum.qbk new file mode 100644 index 00000000..f52e4657 --- /dev/null +++ b/libs/range/doc/reference/numeric/partial_sum.qbk @@ -0,0 +1,60 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:partial_sum partial_sum] + +[heading Prototype] + +`` +template +OutputIterator partial_sum(const SinglePassRange& rng, + OutputIterator out_it); + +template +OutputIterator partial_sum(const SinglePassRange& rng, + OutputIterator out_it, + BinaryOperation op); +`` + +[heading Description] + +`partial_sum` calculates a generalised partial sum of `rng` in the same manner as +`std::partial_sum(boost::begin(rng), boost::end(rng), out_it)`. See __sgi_partial_sum__. + + +[heading Definition] + +Defined in the header file `boost/range/numeric.hpp` + +[heading Requirements] + +[heading For the first version] + +# `SinglePassRange` is a model of the __single_pass_range__ Concept. +# `OutputIterator` is a model of the `OutputIteratorConcept`. +# If `x` and `y` are objects of `SinglePassRange`'s value type, then `x + y` is defined. +# The return type of `x + y` is convertible to the value type of `SinglePassRange`. +# The value type of `SinglePassRange` is convertible to a type in `OutputIterator`'s set of value types. + +[heading For the second version] + +# `SinglePassRange` is a model of the __single_pass_range__ Concept. +# `OutputIterator` is a model of the `OutputIteratorConcept`. +# `BinaryOperation` is a model of the `BinaryFunctionConcept`. +# The result type of `BinaryOperation` is convertible to the value type of `SinglePassRange`. +# The value type of `SinglePassRange` is convertible to a type in `OutputIterator`'s set of value types. + +[heading Precondition:] + +`[result, result + distance(rng))` is a valid range. + +[heading Complexity] + +Linear. If `empty(rng)` then zero applications, otherwise `distance(rng) - 1` applications are performed. + +[endsect] diff --git a/libs/range/doc/reference/overview.qbk b/libs/range/doc/reference/overview.qbk new file mode 100644 index 00000000..af7ef2ca --- /dev/null +++ b/libs/range/doc/reference/overview.qbk @@ -0,0 +1,19 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:overview Overview] + +Three types of objects are currently supported by the library: + +* standard-like containers +* `std::pair` +* built-in arrays + +Even though the behavior of the primary templates are exactly such that standard containers will be supported by default, the requirements are much lower than the standard container requirements. For example, the utility class __iterator_range__ implements the __minimal_interface__ required to make the class a __forward_range__. + +Please also see __range_concepts__ for more details. + +[endsect] + diff --git a/libs/range/doc/reference/ranges.qbk b/libs/range/doc/reference/ranges.qbk new file mode 100644 index 00000000..5b853d54 --- /dev/null +++ b/libs/range/doc/reference/ranges.qbk @@ -0,0 +1,14 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:ranges Provided Ranges] + +[include ranges/any_range.qbk] +[include ranges/counting_range.qbk] +[include ranges/istream_range.qbk] +[include ranges/irange.qbk] + +[endsect] + diff --git a/libs/range/doc/reference/ranges/any_range.qbk b/libs/range/doc/reference/ranges/any_range.qbk new file mode 100644 index 00000000..1888ed86 --- /dev/null +++ b/libs/range/doc/reference/ranges/any_range.qbk @@ -0,0 +1,115 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:any_range any_range] + +[heading Description] + +`any_range` is a range that has the type information erased hence a `any_range` +can be used to represent a `std::vector`, a `std::list` or many other types. + +The __type_erasure_article__ covers the motivation and goals of type erasure in this context. Clearly +my implementation is building upon a lot of prior art created by others. Thomas Becker's `any_iterator` was a strong +influence. Adobe also have an `any_iterator` implementation, but this has very tight coupling to other parts of the +library that precluded it from use in Boost.Range. +Early development versions of this Range Adaptor directly used Thomas Becker's any_iterator implementation. +Subsequently I discovered that the heap allocations of this and many other implementations cause poor +speed performance particularly at the tails of the distribution. To solve this required a new design that +incorporated the embedded buffer optimization. + +Despite the underlying `any_iterator` being the fastest available implementation, the performance overhead of `any_range` is still appreciable due to the cost of virtual function calls required to implement `increment`, `decrement`, `advance`, `equal` etc. Frequently a better design choice is to convert to a canonical form. + +Please see the __range_adaptors_type_erased__ for a Range Adaptor that returns `any_range` instances. + +[heading Synopsis] + +`` +template< + class Value + , class Traversal + , class Reference + , class Difference + , class Buffer = any_iterator_default_buffer +> +class any_range + : public iterator_range< + range_detail::any_iterator< + Value + , Traversal + , Reference + , Difference + , Buffer + > + > +{ + typedef range_detail::any_iterator< + Value + , Traversal + , Reference + , Difference + , Buffer + > any_iterator_type; + + typedef iterator_range base_type; + + struct enabler {}; + struct disabler {}; +public: + typedef any_iterator_type iterator; + typedef any_iterator_type const_iterator; + + any_range() + { + } + + any_range(const any_range& other) + : base_type(other) + { + } + + template + any_range(WrappedRange& wrapped_range) + : base_type(boost::begin(wrapped_range), + boost::end(wrapped_range)) + { + } + + template + any_range(const WrappedRange& wrapped_range) + : base_type(boost::begin(wrapped_range), + boost::end(wrapped_range)) + { + } + + template< + class OtherValue + , class OtherTraversal + , class OtherReference + , class OtherDifference + > + any_range(const any_range< + OtherValue + , OtherTraversal + , OtherReference + , OtherDifference + , Buffer + >& other) + : base_type(boost::begin(other), boost::end(other)) + { + } + + template + any_range(Iterator first, Iterator last) + : base_type(first, last) + { + } +}; +`` + +[heading Definition] + +Defined in header file `boost/range/any_range.hpp` + +[endsect] diff --git a/libs/range/doc/reference/ranges/counting_range.qbk b/libs/range/doc/reference/ranges/counting_range.qbk new file mode 100644 index 00000000..31037a95 --- /dev/null +++ b/libs/range/doc/reference/ranges/counting_range.qbk @@ -0,0 +1,36 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:counting_range counting_range] + +[heading Prototype] + +`` +template< class Incrementable > inline +iterator_range< counting_iterator > +counting_range(Incrementable first, Incrementable last); + +template< class SinglePassRange > inline +iterator_range< counting_iterator::type > +counting_range(const SinglePassRange& rng); + +template< class SinglePassRange > inline +iterator_range< counting_iterator::type > +counting_range(SinglePassRange& rng); +`` + +[heading Description] + +`counting_range` is a function to generator that generates an `iterator_range` wrapping a `counting_iterator` (from Boost.Iterator). + +[heading Definition] + +Defined in header file `boost/range/counting_range.hpp` + +[heading Requirements] + +# `Incrementable` is a model of the `Incrementable` Concept. + +[endsect] diff --git a/libs/range/doc/reference/ranges/irange.qbk b/libs/range/doc/reference/ranges/irange.qbk new file mode 100644 index 00000000..1d4ae7e2 --- /dev/null +++ b/libs/range/doc/reference/ranges/irange.qbk @@ -0,0 +1,43 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:irange irange] + +[heading Prototype] + +`` +template +iterator_range< range_detail::integer_iterator > +irange(Integer last); + +template +iterator_range< range_detail::integer_iterator > +irange(Integer first, Integer last); + +template +iterator_range< range_detail::integer_iterator_with_step > +irange(Integer first, Integer last, StepSize step_size); +`` + +[heading Description] + +`irange` is a function to generate an Integer Range. + +`irange` allows treating integers as a model of the __random_access_range__ Concept. It should be noted that the `first` and `last` parameters denoted a half-open range. + +[heading Definition] + +Defined in the header file `boost/range/irange.hpp` + +[heading Requirements] + +# `Integer` is a model of the `Integer` Concept. +# `StepSize` is a model of the `SignedInteger` Concept. + +[heading Complexity] + +Constant. Since this function generates a new range the most significant performance cost is incurred through the iteration of the generated range. + +[endsect] diff --git a/libs/range/doc/reference/ranges/istream_range.qbk b/libs/range/doc/reference/ranges/istream_range.qbk new file mode 100644 index 00000000..66a1e844 --- /dev/null +++ b/libs/range/doc/reference/ranges/istream_range.qbk @@ -0,0 +1,24 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:istream_range istream_range] + +[heading Prototype] + +`` +template< class Type, class Elem, class Traits > inline +iterator_range< std::istream_iterator > +istream_range(std::basic_istream& in); +`` + +[heading Description] + +`istream_range` is a function to generator that generates an `iterator_range` wrapping a `std::istream_iterator`. + +[heading Definition] + +Defined in header file `boost/range/istream_range.hpp` + +[endsect] diff --git a/libs/range/doc/reference/semantics.qbk b/libs/range/doc/reference/semantics.qbk new file mode 100644 index 00000000..c7cf8f4a --- /dev/null +++ b/libs/range/doc/reference/semantics.qbk @@ -0,0 +1,200 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:semantics Semantics] + +[heading notation] + +[table + [[Type ] [Object] [Describes ]] + [[`X` ] [`x` ] [any type ]] + [[`T` ] [`t` ] [denotes behavior of the primary templates]] + [[`P` ] [`p` ] [denotes `std::pair` ]] + [[`A[sz]`] [`a` ] [denotes an array of type `A` of size `sz`]] + [[`Char*`] [`s` ] [denotes either `char*` or `wchar_t*` ]] +] + +[section Metafunctions] + +[table + [[Expression] [Return type] [Complexity]] + [ + [`range_iterator::type`] + [`` + T::iterator + P::first_type + A* + ``] + [compile time] + ] + [ + [`range_iterator::type`] + [`` + T::const_iterator + P::first_type + const A* + ``] + [compile time] + ] + [ + [`range_value::type`] + [`boost::iterator_value::type>::type`] + [compile time] + ] + [ + [`range_reference::type`] + [`boost::iterator_reference::type>::type`] + [compile time] + ] + [ + [`range_pointer::type`] + [`boost::iterator_pointer::type>::type`] + [compile time] + ] + [ + [`range_category::type`] + [`boost::iterator_category::type>::type`] + [compile time] + ] + [ + [`range_difference::type`] + [`boost::iterator_difference::type>::type`] + [compile time] + ] + [ + [`range_reverse_iterator::type`] + [`boost::reverse_iterator::type>`] + [compile time] + ] + [ + [`range_reverse_iterator::type`] + [`boost::reverse_iterator::type`] + [compile time] + ] + [ + [`has_range_iterator::type`] + [`mpl::true_` if `range_mutable_iterator::type` is a valid expression, `mpl::false_` otherwise] + [compile time] + ] + [ + [`has_range_const_iterator::type`] + [`mpl::true_` if `range_const_iterator::type` is a valid expression, `mpl::false_` otherwise] + [compile time] + ] +] + +[endsect] + +[section Functions] + +[table + [[Expression] [Return type] [Returns] [Complexity]] + + [ + [`begin(x)`] + [`range_iterator::type`] + [ + `p.first` if `p` is of type `std::pair` + `a` if `a` is an array + `range_begin(x)` if that expression would invoke a function found by ADL + `t.begin()` otherwise + ] + [constant time] + ] + [ + [`end(x)`] + [`range_iterator::type`] + [ + `p.second` if `p` is of type `std::pair` + `a + sz` if `a` is an array of size `sz` + `range_end(x)` if that expression would invoke a function found by ADL + `t.end()` otherwise + ] + [constant time] + ] + [ + [`empty(x)`] + [`bool`] + [`boost::begin(x) == boost::end(x)`] + [constant time] + ] + [ + [`distance(x)`] + [`range_difference::type`] + [`std::distance(boost::begin(x),boost::end(x))`] + [-] + ] + [ + [`size(x)`] + [`range_size::type`] + [`range_calculate_size(x)` which by default is `boost::end(x) - boost::begin(x)`. Users may supply alternative implementations by implementing `range_calculate_size(x)` so that it will be found via ADL] + [constant time] + ] + [ + [`rbegin(x)`] + [`range_reverse_iterator::type`] + [`range_reverse_iterator::type(boost::end(x))`] + [constant time] + ] + [ + [`rend(x)`] + [`range_reverse_iterator::type`] + [`range_reverse_iterator::type(boost::begin(x))`] + [constant time] + ] + [ + [`const_begin(x)`] + [`range_iterator::type`] + [`range_iterator::type(boost::begin(x))`] + [constant time] + ] + [ + [`const_end(x)`] + [`range_iterator::type`] + [`range_iterator::type(boost::end(x))`] + [constant time] + ] + [ + [`const_rbegin(x)`] + [`range_reverse_iterator::type`] + [`range_reverse_iterator::type(boost::rbegin(x))`] + [constant time] + ] + [ + [`const_rend(x)`] + [`range_reverse_iterator::type`] + [`range_reverse_iterator::type(boost::rend(x))`] + [constant time] + ] + [ + [`as_literal(x)`] + [`iterator_range` where `U` is `Char*` if `x` is a pointer to a string and `U` is `range_iterator::type` otherwise] + [ + `[s,s + std::char_traits::length(s))` if `s` is a `Char*` or an array of `Char` `[boost::begin(x),boost::end(x))` otherwise + ] + [ + linear time for pointers to a string or arrays of `Char`, constant time otherwise + ] + ] + [ + [`as_array(x)`] + [`iterator_range`] + [`[boost::begin(x),boost::end(x))`] + ] +] + +The special `const_`-named functions are useful when you want to document clearly that your code is read-only. + +`as_literal()` can be used ['*internally*] in string algorithm libraries such that arrays of characters are handled correctly. + +`as_array()` can be used with string algorithm libraries to make it clear that arrays of characters are handled like an array and not like a string. + +Notice that the above functions should always be called with qualification (`boost::`) to prevent ['*unintended*] Argument Dependent Lookup (ADL). + +[endsect] + +[endsect] + + diff --git a/libs/range/doc/reference/synopsis.qbk b/libs/range/doc/reference/synopsis.qbk new file mode 100644 index 00000000..26f96411 --- /dev/null +++ b/libs/range/doc/reference/synopsis.qbk @@ -0,0 +1,144 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:synopsis Synopsis] + +`` +namespace boost +{ + // + // Single Pass Range metafunctions + // + + template< class T, class Enabler=void > + struct range_iterator; + + template< class T > + struct range_value; + + template< class T > + struct range_reference; + + template< class T > + struct range_pointer; + + template< class T > + struct range_category; + + // + // Forward Range metafunctions + // + + template< class T > + struct range_difference; + + // + // Bidirectional Range metafunctions + // + + template< class T > + struct range_reverse_iterator; + + // + // Single Pass Range functions + // + + template< class T > + typename range_iterator::type + begin( T& r ); + + template< class T > + typename range_iterator::type + begin( const T& r ); + + template< class T > + typename range_iterator::type + end( T& r ); + + template< class T > + typename range_iterator::type + end( const T& r ); + + template< class T > + bool + empty( const T& r ); + + // + // Forward Range functions + // + + template< class T > + typename range_difference::type + distance( const T& r ); + + template< class T > + typename range_size::type + size( const T& r ); + + // + // Bidirectional Range functions + // + + template< class T > + typename range_reverse_iterator::type + rbegin( T& r ); + + template< class T > + typename range_reverse_iterator::type + rbegin( const T& r ); + + template< class T > + typename range_reverse_iterator::type + rend( T& r ); + + template< class T > + typename range_reverse_iterator::type + rend( const T& r ); + + // + // Special const Range functions + // + + template< class T > + typename range_iterator::type + const_begin( const T& r ); + + template< class T > + typename range_iterator::type + const_end( const T& r ); + + template< class T > + typename range_reverse_iterator::type + const_rbegin( const T& r ); + + template< class T > + typename range_reverse_iterator::type + const_rend( const T& r ); + + // + // String utilities + // + + template< class T > + iterator_range< ... see below ... > + as_literal( T& r ); + + template< class T > + iterator_range< ... see below ... > + as_literal( const T& r ); + + template< class T > + iterator_range< typename range_iterator::type > + as_array( T& r ); + + template< class T > + iterator_range< typename range_iterator::type > + as_array( const T& r ); + +} // namespace 'boost' +`` + +[endsect] + diff --git a/libs/range/doc/reference/utilities.qbk b/libs/range/doc/reference/utilities.qbk new file mode 100644 index 00000000..a33aafa1 --- /dev/null +++ b/libs/range/doc/reference/utilities.qbk @@ -0,0 +1,417 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:utilities Utilities] + +Having an abstraction that encapsulates a pair of iterators is very useful. The standard library uses `std::pair` in some circumstances, but that class is cumbersome to use because we need to specify two template arguments, and for all range algorithm purposes we must enforce the two template arguments to be the same. Moreover, `std::pair` is hardly self-documenting whereas more domain specific class names are. Therefore these two classes are provided: + +* Class `iterator_range` +* Class `sub_range` +* Function `combine` +* Function `join` + +The `iterator_range` class is templated on an __forward_traversal_iterator__ and should be used whenever fairly general code is needed. The `sub_range` class is templated on an __forward_range__ and it is less general, but a bit easier to use since its template argument is easier to specify. The biggest difference is, however, that a `sub_range` can propagate constness because it knows what a corresponding `const_iterator` is. + +Both classes can be used as ranges since they implement the __minimal_interface__ required for this to work automatically. + +[section:iterator_range Class `iterator_range`] + +The intention of the `iterator_range` class is to encapsulate two iterators so they fulfill the __forward_range__ concept. A few other functions are also provided for convenience. + +If the template argument is not a model of __forward_traversal_iterator__, one can still use a subset of the interface. In particular, `size()` requires Random Access Traversal Iterators whereas `empty()` only requires Single Pass Iterators. + +Recall that many default constructed iterators are [*/singular/] and hence can only be assigned, but not compared or incremented or anything. However, if one creates a default constructed `iterator_range`, then one can still call all its member functions. This design decision avoids the `iterator_range` imposing limitations upon ranges of iterators that are not singular. Any singularity limitation is simply propagated from the underlying iterator type. + + +[h4 Synopsis] + +The core functionality is in the header file +`` this includes all of the functionality +except the `boost::hash_value` and `std::iostream` support. + +The `std::iostream` support is in the header `` +while the `boost::hash_value` support is in +`` + +`` +namespace boost +{ + template< class ForwardTraversalIterator > + class iterator_range + { + public: // Forward Range types + typedef ForwardTraversalIterator iterator; + typedef ForwardTraversalIterator const_iterator; + typedef iterator_difference::type difference_type; + + public: // construction, assignment + template< class ForwardTraversalIterator2 > + iterator_range( ForwardTraversalIterator2 Begin, ForwardTraversalIterator2 End ); + + template< class ForwardRange > + iterator_range( ForwardRange& r ); + + template< class ForwardRange > + iterator_range( const ForwardRange& r ); + + template< class ForwardRange > + iterator_range& operator=( ForwardRange& r ); + + template< class ForwardRange > + iterator_range& operator=( const ForwardRange& r ); + + public: // Forward Range functions + iterator begin() const; + iterator end() const; + + public: // convenience + operator unspecified_bool_type() const; + bool equal( const iterator_range& ) const; + value_type& front() const; + void drop_front(); + void drop_front(difference_type n); + bool empty() const; + + iterator_range& advance_begin(difference_type n); + iterator_range& advance_end(difference_type n); + + // for Bidirectional: + value_type& back() const; + void drop_back(); + void drop_back(difference_type n); + // for Random Access only: + reference operator[]( difference_type at ) const; + value_type operator()( difference_type at ) const; + size_type size() const; + }; + + // stream output + template< class ForwardTraversalIterator, class T, class Traits > + std::basic_ostream& + operator<<( std::basic_ostream& Os, + const iterator_range& r ); + + // comparison + template< class ForwardTraversalIterator, class ForwardTraversalIterator2 > + bool operator==( const iterator_range& l, + const iterator_range& r ); + + template< class ForwardTraversalIterator, class ForwardRange > + bool operator==( const iterator_range& l, + const ForwardRange& r ); + + template< class ForwardTraversalIterator, class ForwardRange > + bool operator==( const ForwardRange& l, + const iterator_range& r ); + + template< class ForwardTraversalIterator, class ForwardTraversalIterator2 > + bool operator!=( const iterator_range& l, + const iterator_range& r ); + + template< class ForwardTraversalIterator, class ForwardRange > + bool operator!=( const iterator_range& l, + const ForwardRange& r ); + + template< class ForwardTraversalIterator, class ForwardRange > + bool operator!=( const ForwardRange& l, + const iterator_range& r ); + + template< class ForwardTraversalIterator, class ForwardTraversalIterator2 > + bool operator<( const iterator_range& l, + const iterator_range& r ); + + template< class ForwardTraversalIterator, class ForwardRange > + bool operator<( const iterator_range& l, + const ForwardRange& r ); + + template< class ForwardTraversalIterator, class ForwardRange > + bool operator<( const ForwardRange& l, + const iterator_range& r ); + + // external construction + template< class ForwardTraversalIterator > + iterator_range< ForwardTraversalIterator > + make_iterator_range( ForwardTraversalIterator Begin, + ForwardTraversalIterator End ); + + // Make an iterator_range [first, boost::next(first, n) ) + template< class ForwardTraversalIterator, class Integer > + iterator_range< ForwardTraversalIterator > + make_iterator_range_n( ForwardTraversalIterator first, Integer n ); + + + template< class ForwardRange > + iterator_range< typename range_iterator::type > + make_iterator_range( ForwardRange& r ); + + template< class ForwardRange > + iterator_range< typename range_iterator::type > + make_iterator_range( const ForwardRange& r ); + + template< class Range > + iterator_range< typename range_iterator::type > + make_iterator_range( Range& r, + typename range_difference::type advance_begin, + typename range_difference::type advance_end ); + + template< class Range > + iterator_range< typename range_iterator::type > + make_iterator_range( const Range& r, + typename range_difference::type advance_begin, + typename range_difference::type advance_end ); + + // convenience + template< class Sequence, class ForwardRange > + Sequence copy_range( const ForwardRange& r ); + +} // namespace 'boost' +`` + +If an instance of `iterator_range` is constructed by a client with two iterators, the client must ensure that the two iterators delimit a valid closed-open range [begin,end). + +It is worth noticing that the templated constructors and assignment operators allow conversion from `iterator_range` to `iterator_range`. Similarly, since the comparison operators have two template arguments, we can compare ranges whenever the iterators are comparable; for example when we are dealing with const and non-const iterators from the same container. + +[h4 Details member functions] + +`operator unspecified_bool_type() const;` + +[:['[*Returns]] `!empty();`] + +`bool equal( iterator_range& r ) const;` + +[:['[*Returns]] `begin() == r.begin() && end() == r.end();`] + +[h4 Details functions] + +`bool operator==( const ForwardRange1& l, const ForwardRange2& r );` + +[:['[*Returns]] `size(l) != size(r) ? false : std::equal( begin(l), end(l), begin(r) );`] + +`bool operator!=( const ForwardRange1& l, const ForwardRange2& r );` + +[:['[*Returns]] `!( l == r );`] + +`bool operator<( const ForwardRange1& l, const ForwardRange2& r );` + +[:['[*Returns]] `std::lexicographical_compare( begin(l), end(l), begin(r), end(r) );`] + +`` +iterator_range make_iterator_range( Range& r, + typename range_difference::type advance_begin, + typename range_difference::type advance_end ); +`` + +[:['[*Effects:]]] + +`` + iterator new_begin = begin( r ), + iterator new_end = end( r ); + std::advance( new_begin, advance_begin ); + std::advance( new_end, advance_end ); + return make_iterator_range( new_begin, new_end ); +`` + +`Sequence copy_range( const ForwardRange& r );` + +[:['[*Returns]] `Sequence( begin(r), end(r) );`] + +[endsect] + +[section:sub_range Class `sub_range`] + +The `sub_range` class inherits all its functionality from the __iterator_range__ class. The `sub_range` class is often easier to use because one must specify the __forward_range__ template argument instead of an iterator. Moreover, the `sub_range` class can propagate constness since it knows what a corresponding `const_iterator` is. + +[h4 Synopsis] + +`` +namespace boost +{ + template< class ForwardRange > + class sub_range : public iterator_range< typename range_iterator::type > + { + public: + typedef typename range_value::type value_type; + typedef typename range_iterator::type iterator; + typedef typename range_iterator::type const_iterator; + typedef typename range_difference::type difference_type; + typedef typename range_size::type size_type; + typedef typename range_reference::type reference; + typedef typename range_reference::type const_reference; + + public: // construction, assignment + sub_range(); + + template< class ForwardTraversalIterator > + sub_range( ForwardTraversalIterator Begin, ForwardTraversalIterator End ); + + template< class ForwardRange2 > + sub_range( ForwardRange2& r ); + + template< class ForwardRange2 > + sub_range( const Range2& r ); + + template< class ForwardRange2 > + sub_range& operator=( ForwardRange2& r ); + + template< class ForwardRange2 > + sub_range& operator=( const ForwardRange2& r ); + + // iterator accessors + const_iterator begin() const; + iterator begin(); + const_iterator end() const; + iterator end(); + + reference front(); + const_reference front() const; + + sub_range& advance_begin(difference_type n); + sub_range& advance_end(difference_type n); + + // If traversal >= bidirectional: + reference back(); + const_reference back(); + + // If traversal >= random-access: + reference operator[](difference_type n); + const_reference operator[](difference_type n) const; + + public: + // rest of interface inherited from iterator_range + }; + +} // namespace 'boost' +`` + +The class should be trivial to use as seen below. Imagine that we have an algorithm that searches for a sub-string in a string. The result is an iterator_range, that delimits the match. We need to store the result from this algorithm. Here is an example of how we can do it with and without `sub_range` + +`` +std::string str("hello"); +iterator_range ir = find_first( str, "ll" ); +sub_range sub = find_first( str, "ll" ); +`` + +[endsect] + +[section:combine Function combine] + +The `combine` function is used to make one range from multiple ranges. The +`combine` function returns a `combined_range` which is an `iterator_range` of +a `zip_iterator` from the Boost.Iterator library. + +[h4 Synopsis] + +`` +namespace boost +{ + namespace range + { + +template +class combined_range + : public iterator_range > +{ +public: + combined_range(IterTuple first, IterTuple last); +}; + +template +auto combine(Ranges&&... rngs) -> + combined_range + + } // namespace range +} // namespace boost +`` + +* [*Precondition:] For each type `r` in `Ranges`, `r` is a model of +__single_pass_range__ or better. +* [*Return Type:] `combined_range::type...> >` +* [*Returned Range Category:] The minimum of the range category of every range +`r` in `Ranges`. + +[h4 Example] + +`` +#include +#include +#include +#include +#include + +int main(int, const char*[]) +{ + std::vector v; + std::list l; + for (int i = 0; i < 5; ++i) + { + v.push_back(i); + l.push_back(static_cast(i) + 'a'); + } + + int ti; + char tc; + BOOST_FOREACH(boost::tie(ti, tc), boost::combine(v, l)) + { + std::cout << '(' << ti << ',' << tc << ')' << '\n'; + } + + return 0; +} +`` + +This produces the output: +`` +(0,a) +(1,b) +(2,c) +(3,d) +(4,e) +`` + +[endsect] + +[section:join Function join] + +The intention of the `join` function is to join two ranges into one longer range. + +The resultant range will have the lowest common traversal of the two ranges supplied as parameters. + +Note that the joined range incurs a performance cost due to the need to check if the end of a range has been reached internally during traversal. + +[h4 Synopsis] + +`` +template +joined_range +join(const SinglePassRange1& rng1, const SinglePassRange2& rng2) + +template +joined_range +join(SinglePassRange1& rng1, SinglePassRange2& rng2); +`` + +For the const version: + +* [*Precondition:] The `range_value::type` must be convertible to `range_value::type`. The `range_reference::type` must be convertible to `range_reference::type`. +* [*Range Category:] Both `rng1` and `rng2` must be a model of __single_pass_range__ or better. +* [*Range Return Type:] `joined_range` which is a model of the lesser of the two range concepts passed. +* [*Returned Range Category:] The minimum of the range category of `rng1` and `rng2`. + +For the mutable version: + +* [*Precondition:] The `range_value::type` must be convertible to `range_value::type`. The `range_reference::type` must be convertible to `range_reference::type`. +* [*Range Category:] Both `rng1` and `rng2` must be a model of __single_pass_range__ or better. +* [*Range Return Type:] `joined_range` which is a model of the lesser of the two range concepts passed. +* [*Returned Range Category:] The minimum of the range category of `rng1` and `rng2`. + +[h4 Example] + +The expression `join(irange(0,5), irange(5,10))` would evaluate to a range representing an integer range `[0,10)` + + +[endsect] + +[endsect] + diff --git a/libs/range/doc/style.qbk b/libs/range/doc/style.qbk new file mode 100644 index 00000000..2074ba67 --- /dev/null +++ b/libs/range/doc/style.qbk @@ -0,0 +1,50 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:style_guide Terminology and style guidelines] + +The use of a consistent terminology is as important for __ranges__ and range-based algorithms as it is for iterators and iterator-based algorithms. If a conventional set of names are adopted, we can avoid misunderstandings and write generic function prototypes that are [*/self-documenting/]. + +Since ranges are characterized by a specific underlying iterator type, we get a type of range for each type of iterator. Hence we can speak of the following types of ranges: + +* [*/Value access/] category: + * Readable Range + * Writeable Range + * Swappable Range + * Lvalue Range +* [*/Traversal/] category: + * __single_pass_range__ + * __forward_range__ + * __bidirectional_range__ + * __random_access_range__ + +Notice how we have used the categories from the __new_style_iterators__. + +Notice that an iterator (and therefore an range) has one [*/traversal/] property and one or more properties from the [*/value access/] category. So in reality we will mostly talk about mixtures such as + +* Random Access Readable Writeable Range +* Forward Lvalue Range + +By convention, we should always specify the [*/traversal/] property first as done above. This seems reasonable since there will only be one [*/traversal/] property, but perhaps many [*/value access/] properties. + +It might, however, be reasonable to specify only one category if the other category does not matter. For example, the __iterator_range__ can be constructed from a Forward Range. This means that we do not care about what [*/value access/] properties the Range has. Similarly, a Readable Range will be one that has the lowest possible [*/traversal/] property (Single Pass). + +As another example, consider how we specify the interface of `std::sort()`. Algorithms are usually more cumbersome to specify the interface of since both [*/traversal/] and [*/value access/] properties must be exactly defined. The iterator-based version looks like this: + +`` + template< class RandomAccessTraversalReadableWritableIterator > + void sort( RandomAccessTraversalReadableWritableIterator first, + RandomAccessTraversalReadableWritableIterator last ); +`` + +For ranges the interface becomes + +`` + template< class RandomAccessReadableWritableRange > + void sort( RandomAccessReadableWritableRange& r ); +`` + +[endsect] + diff --git a/libs/range/doc/upgrade.qbk b/libs/range/doc/upgrade.qbk new file mode 100644 index 00000000..47fa8cb9 --- /dev/null +++ b/libs/range/doc/upgrade.qbk @@ -0,0 +1,67 @@ +[/ + Copyright 2010 Neil Groves + 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) +/] +[section:upgrade Upgrade version of Boost.Range] + +[section:upgrade_from_1_55 Upgrade from version 1.55] +# __iterator_range__ is now implemented by implementing the member functions +`size()`, `operator[]` via inheritance of base-classes specialized by the +traversal type of the underlying iterator. This is normally requires no +alteration of code. It does mean that types that derive from iterator_range may +need to prefix `this->` to the various member functions. Additionally it has +been noted that some calling code was relying on member functions such as +`size()` being present despite the underlying iterators not being random-access +due to `iterator_reference::type` not being a reference. The suggested +refactoring is to use `boost::size(rng)`. +# The undocumented __iterator_range__ `pop_front()` has been deprecated and is +replaced by `drop_front(). Similarly `pop_back()` has been replaced by +`drop_back()`. + +[endsect] + +[section:upgrade_from_1_49 Upgrade from version 1.49] + +# __size__ now returns the type Rng::size_type if the range has size_type; +otherwise range_size::type is used. This is the distance type promoted to +an unsigned type. + +[endsect] + +[section:upgrade_from_1_45 Upgrade from version 1.45] + +# __size__ in addition to supporting __random_access_range__ now also supports extensibility via calls to the unqualified `range_calculate_size(rng)` function. +# __range_adaptors_strided__ now in addition to working with any RandomAccessRange additionally works for any SinglePassRange for which `boost::size(rng)` is valid. +# __range_adaptors_strided__ no longer requires `distance(rng) % stride_size == 0` or `stride_size < distance(rng)` + +[endsect] + +[section:upgrade_from_1_42 Upgrade from version 1.42] + +New features: + +# __range_adaptors__ +# __range_algorithms__ + +Removed: + +# `iterator_range` no longer has a `is_singular` member function. The singularity restrictions have been removed from the `iterator_range` class since this added restrictions to ranges of iterators whose default constructors were not singular. Previously the `is_singular` member function always returned `false` in release build configurations, hence it is not anticipated that this interface change will produce difficulty in upgrading. + + +[endsect] + +[section:upgrade_from_1_34 Upgrade from version 1.34] + +Boost version 1.35 introduced some larger refactorings of the library: + +# Direct support for character arrays was abandoned in favor of uniform treatment of all arrays. Instead string algorithms can use the new function __as_literal__`()`. +# __size__ now requires a __random_access_range__. The old behavior is provided as __distance__`()`. +# `range_size::type` has been completely removed in favor of `range_difference::type` +# `boost_range_begin()` and `boost_range_end()` have been renamed `range_begin()` and `range_end()` respectively. +# `range_result_iterator::type` and `range_reverse_result_iterator::type` have been renamed `range_iterator::type` and `range_reverse_iterator::type`. +# The procedure that makes a custom type work with the library has been greatly simplified. See __extending_for_udts__ for details. + +[endsect] + +[endsect] diff --git a/libs/range/include/boost/range.hpp b/libs/range/include/boost/range.hpp new file mode 100644 index 00000000..179ae224 --- /dev/null +++ b/libs/range/include/boost/range.hpp @@ -0,0 +1,23 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_HPP_27_07_04 +#define BOOST_RANGE_HPP_27_07_04 + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include +#include + +#endif diff --git a/libs/range/include/boost/range/adaptor/adjacent_filtered.hpp b/libs/range/include/boost/range/adaptor/adjacent_filtered.hpp new file mode 100644 index 00000000..405fe7bc --- /dev/null +++ b/libs/range/include/boost/range/adaptor/adjacent_filtered.hpp @@ -0,0 +1,237 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_ADJACENT_FILTER_IMPL_HPP +#define BOOST_RANGE_ADAPTOR_ADJACENT_FILTER_IMPL_HPP + +#include +#ifdef BOOST_MSVC +#pragma warning( push ) +#pragma warning( disable : 4355 ) +#endif + +#include +#include +#include +#include +#include +#include +#include + + +namespace boost +{ + namespace range_detail + { + template< class Iter, class Pred, bool default_pass > + class skip_iterator + : public boost::iterator_adaptor< + skip_iterator, + Iter, + BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type, + boost::forward_traversal_tag, + BOOST_DEDUCED_TYPENAME std::iterator_traits::reference, + BOOST_DEDUCED_TYPENAME std::iterator_traits::difference_type + > + , private Pred + { + private: + typedef boost::iterator_adaptor< + skip_iterator, + Iter, + BOOST_DEDUCED_TYPENAME std::iterator_traits::value_type, + boost::forward_traversal_tag, + BOOST_DEDUCED_TYPENAME std::iterator_traits::reference, + BOOST_DEDUCED_TYPENAME std::iterator_traits::difference_type + > base_t; + + public: + typedef Pred pred_t; + typedef Iter iter_t; + + skip_iterator() : m_last() {} + + skip_iterator(iter_t it, iter_t last, const Pred& pred) + : base_t(it) + , pred_t(pred) + , m_last(last) + { + } + + template + skip_iterator( const skip_iterator& other ) + : base_t(other.base()) + , pred_t(other) + , m_last(other.m_last) + { + } + + void increment() + { + iter_t& it = this->base_reference(); + BOOST_ASSERT( it != m_last ); + pred_t& bi_pred = *this; + iter_t prev = it; + ++it; + if (it != m_last) + { + if (default_pass) + { + while (it != m_last && !bi_pred(*prev, *it)) + { + ++it; + ++prev; + } + } + else + { + for (; it != m_last; ++it, ++prev) + { + if (bi_pred(*prev, *it)) + { + break; + } + } + } + } + } + + iter_t m_last; + }; + + template< class P, class R, bool default_pass > + struct adjacent_filtered_range + : iterator_range< skip_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type, + P, + default_pass + > + > + { + private: + typedef skip_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type, + P, + default_pass + > + skip_iter; + + typedef iterator_range + base_range; + + typedef BOOST_DEDUCED_TYPENAME range_iterator::type raw_iterator; + + public: + adjacent_filtered_range( const P& p, R& r ) + : base_range(skip_iter(boost::begin(r), boost::end(r), p), + skip_iter(boost::end(r), boost::end(r), p)) + { + } + }; + + template< class T > + struct adjacent_holder : holder + { + adjacent_holder( T r ) : holder(r) + { } + }; + + template< class T > + struct adjacent_excl_holder : holder + { + adjacent_excl_holder( T r ) : holder(r) + { } + }; + + template< class ForwardRng, class BinPredicate > + inline adjacent_filtered_range + operator|( ForwardRng& r, + const adjacent_holder& f ) + { + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + + return adjacent_filtered_range( f.val, r ); + } + + template< class ForwardRng, class BinPredicate > + inline adjacent_filtered_range + operator|( const ForwardRng& r, + const adjacent_holder& f ) + { + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + + return adjacent_filtered_range( f.val, r ); + } + + template< class ForwardRng, class BinPredicate > + inline adjacent_filtered_range + operator|( ForwardRng& r, + const adjacent_excl_holder& f ) + { + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return adjacent_filtered_range( f.val, r ); + } + + template< class ForwardRng, class BinPredicate > + inline adjacent_filtered_range + operator|( const ForwardRng& r, + const adjacent_excl_holder& f ) + { + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return adjacent_filtered_range( f.val, r ); + } + + } // 'range_detail' + + // Bring adjacent_filter_range into the boost namespace so that users of + // this library may specify the return type of the '|' operator and + // adjacent_filter() + using range_detail::adjacent_filtered_range; + + namespace adaptors + { + namespace + { + const range_detail::forwarder + adjacent_filtered = + range_detail::forwarder(); + + const range_detail::forwarder + adjacent_filtered_excl = + range_detail::forwarder(); + } + + template + inline adjacent_filtered_range + adjacent_filter(ForwardRng& rng, BinPredicate filter_pred) + { + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return adjacent_filtered_range(filter_pred, rng); + } + + template + inline adjacent_filtered_range + adjacent_filter(const ForwardRng& rng, BinPredicate filter_pred) + { + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return adjacent_filtered_range(filter_pred, rng); + } + + } // 'adaptors' + +} + +#ifdef BOOST_MSVC +#pragma warning( pop ) +#endif + +#endif diff --git a/libs/range/include/boost/range/adaptor/argument_fwd.hpp b/libs/range/include/boost/range/adaptor/argument_fwd.hpp new file mode 100644 index 00000000..fbfd40c1 --- /dev/null +++ b/libs/range/include/boost/range/adaptor/argument_fwd.hpp @@ -0,0 +1,80 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_ARGUMENT_FWD_HPP +#define BOOST_RANGE_ADAPTOR_ARGUMENT_FWD_HPP + +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable : 4512) // assignment operator could not be generated +#endif + +namespace boost +{ + namespace range_detail + { + template< class T > + struct holder + { + T val; + holder( T t ) : val(t) + { } + }; + + template< class T > + struct holder2 + { + T val1, val2; + holder2( T t, T u ) : val1(t), val2(u) + { } + }; + + template< template class Holder > + struct forwarder + { + template< class T > + Holder operator()( T t ) const + { + return Holder(t); + } + }; + + template< template class Holder > + struct forwarder2 + { + template< class T > + Holder operator()( T t, T u ) const + { + return Holder(t,u); + } + }; + + template< template class Holder > + struct forwarder2TU + { + template< class T, class U > + Holder operator()( T t, U u ) const + { + return Holder(t, u); + } + }; + + + } + +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif diff --git a/libs/range/include/boost/range/adaptor/copied.hpp b/libs/range/include/boost/range/adaptor/copied.hpp new file mode 100644 index 00000000..f7dfbcd8 --- /dev/null +++ b/libs/range/include/boost/range/adaptor/copied.hpp @@ -0,0 +1,68 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen, Neil Groves 2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_COPIED_HPP +#define BOOST_RANGE_ADAPTOR_COPIED_HPP + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace adaptors + { + struct copied + { + copied(std::size_t t_, std::size_t u_) + : t(t_), u(u_) {} + + std::size_t t; + std::size_t u; + }; + + template + inline CopyableRandomAccessRange + operator|(const CopyableRandomAccessRange& r, const copied& f) + { + BOOST_RANGE_CONCEPT_ASSERT(( + RandomAccessRangeConcept)); + + iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator< + const CopyableRandomAccessRange + >::type + > temp(adaptors::slice(r, f.t, f.u)); + + return CopyableRandomAccessRange(temp.begin(), temp.end()); + } + + template + inline CopyableRandomAccessRange + copy(const CopyableRandomAccessRange& rng, std::size_t t, std::size_t u) + { + BOOST_RANGE_CONCEPT_ASSERT(( + RandomAccessRangeConcept)); + + iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator< + const CopyableRandomAccessRange + >::type + > temp(adaptors::slice(rng, t, u)); + + return CopyableRandomAccessRange( temp.begin(), temp.end() ); + } + } // 'adaptors' + +} + +#endif // include guard diff --git a/libs/range/include/boost/range/adaptor/define_adaptor.hpp b/libs/range/include/boost/range/adaptor/define_adaptor.hpp new file mode 100644 index 00000000..b228df38 --- /dev/null +++ b/libs/range/include/boost/range/adaptor/define_adaptor.hpp @@ -0,0 +1,109 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_DEFINE_ADAPTOR_HPP_INCLUDED +#define BOOST_RANGE_DEFINE_ADAPTOR_HPP_INCLUDED + +#include + +#define BOOST_DEFINE_RANGE_ADAPTOR( adaptor_name, range_adaptor ) \ + struct adaptor_name##_forwarder {}; \ + \ + template range_adaptor \ + operator|(Range& rng, adaptor_name##_forwarder) \ + { \ + return range_adaptor ( rng ); \ + } \ + \ + template range_adaptor \ + operator|(const Range& rng, adaptor_name##_forwarder) \ + { \ + return range_adaptor ( rng ); \ + } \ + \ + static adaptor_name##_forwarder adaptor_name = adaptor_name##_forwarder(); \ + \ + template \ + range_adaptor \ + make_##adaptor_name(Range& rng) \ + { \ + return range_adaptor (rng); \ + } \ + \ + template \ + range_adaptor \ + make_##adaptor_name(const Range& rng) \ + { \ + return range_adaptor (rng); \ + } + +#define BOOST_DEFINE_RANGE_ADAPTOR_1( adaptor_name, range_adaptor, arg1_type ) \ + struct adaptor_name \ + { \ + explicit adaptor_name (arg1_type arg1_) \ + : arg1(arg1_) {} \ + arg1_type arg1; \ + }; \ + \ + template range_adaptor \ + operator|(Range& rng, adaptor_name args) \ + { \ + return range_adaptor (rng, args.arg1); \ + } \ + \ + template range_adaptor \ + operator|(const Range& rng, adaptor_name args) \ + { \ + return range_adaptor (rng, args.arg1); \ + } \ + \ + template \ + range_adaptor \ + make_##adaptor_name(Range& rng, arg1_type arg1) \ + { \ + return range_adaptor (rng, arg1); \ + } \ + \ + template \ + range_adaptor \ + make_##adaptor_name(const Range& rng, arg1_type arg1) \ + { \ + return range_adaptor (rng, arg1); \ + } + +#define BOOST_RANGE_ADAPTOR_2( adaptor_name, range_adaptor, arg1_type, arg2_type ) \ + struct adaptor_name \ + { \ + explicit adaptor_name (arg1_type arg1_, arg2_type arg2_) \ + : arg1(arg1_), arg2(arg2_) {} \ + arg1_type arg1; \ + arg2_type arg2; \ + }; \ + \ + template range_adaptor \ + operator|(Range& rng, adaptor_name args) \ + { \ + return range_adaptor (rng, args.arg1, args.arg2); \ + } \ + template \ + range_adaptor \ + make_##adaptor_name(Range& rng, arg1_type arg1, arg2_type arg2) \ + { \ + return range_adaptor (rng, arg1, arg2); \ + } \ + template \ + range_adaptor \ + make_##adaptor_name(const Range& rng, arg1_type arg1, arg2_type arg2) \ + { \ + return range_adaptor (rng, arg1, arg2); \ + } + + +#endif // include guard diff --git a/libs/range/include/boost/range/adaptor/filtered.hpp b/libs/range/include/boost/range/adaptor/filtered.hpp new file mode 100644 index 00000000..1fb778e5 --- /dev/null +++ b/libs/range/include/boost/range/adaptor/filtered.hpp @@ -0,0 +1,121 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_FILTERED_HPP +#define BOOST_RANGE_ADAPTOR_FILTERED_HPP + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + template< class P, class R > + struct filtered_range : + boost::iterator_range< + boost::filter_iterator< + typename default_constructible_unary_fn_gen::type, + typename range_iterator::type + > + > + { + private: + typedef boost::iterator_range< + boost::filter_iterator< + typename default_constructible_unary_fn_gen::type, + typename range_iterator::type + > + > base; + public: + typedef typename default_constructible_unary_fn_gen::type + pred_t; + + filtered_range(P p, R& r) + : base(make_filter_iterator(pred_t(p), + boost::begin(r), boost::end(r)), + make_filter_iterator(pred_t(p), + boost::end(r), boost::end(r))) + { } + }; + + template< class T > + struct filter_holder : holder + { + filter_holder( T r ) : holder(r) + { } + }; + + template< class SinglePassRange, class Predicate > + inline filtered_range + operator|(SinglePassRange& r, + const filter_holder& f) + { + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + return filtered_range( f.val, r ); + } + + template< class SinglePassRange, class Predicate > + inline filtered_range + operator|(const SinglePassRange& r, + const filter_holder& f ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + return filtered_range( f.val, r ); + } + + } // 'range_detail' + + // Unusual use of 'using' is intended to bring filter_range into the boost namespace + // while leaving the mechanics of the '|' operator in range_detail and maintain + // argument dependent lookup. + // filter_range logically needs to be in the boost namespace to allow user of + // the library to define the return type for filter() + using range_detail::filtered_range; + + namespace adaptors + { + namespace + { + const range_detail::forwarder + filtered = + range_detail::forwarder(); + } + + template + inline filtered_range + filter(SinglePassRange& rng, Predicate filter_pred) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return range_detail::filtered_range< + Predicate, SinglePassRange>( filter_pred, rng ); + } + + template + inline filtered_range + filter(const SinglePassRange& rng, Predicate filter_pred) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return range_detail::filtered_range< + Predicate, const SinglePassRange>( filter_pred, rng ); + } + } // 'adaptors' + +} + +#endif diff --git a/libs/range/include/boost/range/adaptor/formatted.hpp b/libs/range/include/boost/range/adaptor/formatted.hpp new file mode 100644 index 00000000..f31f1bce --- /dev/null +++ b/libs/range/include/boost/range/adaptor/formatted.hpp @@ -0,0 +1,229 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. +// Use, modification and distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ADAPTOR_FORMATTED_HPP_INCLUDED +#define BOOST_RANGE_ADAPTOR_FORMATTED_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + +template +struct formatted_holder +{ + typedef typename boost::mpl::if_< + boost::is_array, + const typename boost::remove_extent::type*, + Sep + >::type separator_t; + + typedef typename boost::mpl::if_< + boost::is_array, + const typename boost::remove_extent::type*, + Prefix + >::type prefix_t; + + typedef typename boost::mpl::if_< + boost::is_array, + const typename boost::remove_extent::type*, + Postfix + >::type postfix_t; + + formatted_holder( + const separator_t& sep, + const prefix_t& prefix, + const postfix_t& postfix) + : m_sep(sep) + , m_prefix(prefix) + , m_postfix(postfix) + { + } + + separator_t m_sep; + prefix_t m_prefix; + postfix_t m_postfix; +}; + +template +class formatted_range + : public boost::iterator_range +{ + typedef formatted_holder holder_t; +public: + formatted_range(Iter first, Iter last, const holder_t& holder) + : boost::iterator_range(first, last) + , m_holder(holder) + { + } + + template + void write(OStream& out) const + { + Iter it(this->begin()); + out << m_holder.m_prefix; + if (it != this->end()) + { + out << *it; + for (++it; it != this->end(); ++it) + { + out << m_holder.m_sep << *it; + } + } + out << m_holder.m_postfix; + } + +private: + holder_t m_holder; +}; + +template< + typename SinglePassRange, + typename Sep, + typename Prefix, + typename Postfix +> +inline range_detail::formatted_range< + typename range_iterator::type, Sep, Prefix, Postfix +> +operator|( + const SinglePassRange& rng, + const range_detail::formatted_holder& holder +) +{ + typedef typename range_iterator::type iterator; + return range_detail::formatted_range( + boost::begin(rng), boost::end(rng), holder); +} + +template +std::basic_ostream& +operator<<( + std::basic_ostream& out, + const formatted_range& writer) +{ + writer.write(out); + return out; +} + + } // namespace range_detail + + namespace adaptors + { + +template +range_detail::formatted_holder +formatted(const Sep& sep, const Prefix& prefix, const Postfix& postfix) +{ + return range_detail::formatted_holder( + sep, prefix, postfix); +} + +template +range_detail::formatted_holder +formatted(const Sep& sep, const Prefix& prefix) +{ + return range_detail::formatted_holder(sep, prefix, '}'); +} + +template +range_detail::formatted_holder +formatted(const Sep& sep) +{ + return range_detail::formatted_holder(sep, '{', '}'); +} + +inline range_detail::formatted_holder +formatted() +{ + return range_detail::formatted_holder(',', '{', '}'); +} + +using range_detail::formatted_range; + +template +inline boost::range_detail::formatted_range< + typename boost::range_iterator::type, + Sep, Prefix, Postfix +> +format( + const SinglePassRange& rng, + const Sep& sep, + const Prefix& prefix, + const Postfix& postfix +) +{ + typedef typename boost::range_iterator::type + iterator_t; + + typedef boost::range_detail::formatted_range< + iterator_t, Sep, Prefix, Postfix> result_t; + + typedef boost::range_detail::formatted_holder + holder_t; + + return result_t(boost::begin(rng), boost::end(rng), + holder_t(sep, prefix, postfix)); +} + +template +inline boost::range_detail::formatted_range< + typename boost::range_iterator::type, + Sep, Prefix, char +> +format( + const SinglePassRange& rng, + const Sep& sep, + const Prefix& prefix) +{ + return adaptors::format(rng, sep, prefix, '}'); +} + +template +inline boost::range_detail::formatted_range< + typename boost::range_iterator::type, + Sep, char, char +> +format(const SinglePassRange& rng, const Sep& sep) +{ + return adaptors::format(rng, sep, '{', '}'); +} + +template +inline boost::range_detail::formatted_range< + typename boost::range_iterator::type, + char, char, char +> +format(const SinglePassRange& rng) +{ + return adaptors::format(rng, ',', '{', '}'); +} + + } // namespace adaptors + + namespace range + { + using boost::range_detail::formatted_range; + } // namespace range +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/adaptor/indexed.hpp b/libs/range/include/boost/range/adaptor/indexed.hpp new file mode 100644 index 00000000..8fd02890 --- /dev/null +++ b/libs/range/include/boost/range/adaptor/indexed.hpp @@ -0,0 +1,395 @@ +// Copyright 2014 Neil Groves +// +// Copyright (c) 2010 Ilya Murav'jov +// +// Use, modification and distribution is subject to 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) +// +// Credits: +// My (Neil's) first indexed adaptor was hindered by having the underlying +// iterator return the same reference as the wrapped iterator. This meant that +// to obtain the index one had to get to the index_iterator and call the +// index() function on it. Ilya politely pointed out that this was useless in +// a number of scenarios since one naturally hides the use of iterators in +// good range-based code. Ilya provided a new interface (which has remained) +// and a first implementation. Much of this original implementation has +// been simplified and now supports more compilers and platforms. +// +#ifndef BOOST_RANGE_ADAPTOR_INDEXED_HPP_INCLUDED +#define BOOST_RANGE_ADAPTOR_INDEXED_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace boost +{ + namespace adaptors + { + +struct indexed +{ + explicit indexed(std::ptrdiff_t x = 0) + : val(x) + { + } + std::ptrdiff_t val; +}; + + } // namespace adaptors + + namespace range + { + +// Why yet another "pair" class: +// - std::pair can't store references +// - no need for typing for index type (default to "std::ptrdiff_t"); this is +// useful in BOOST_FOREACH() expressions that have pitfalls with commas +// ( see http://www.boost.org/doc/libs/1_44_0/doc/html/foreach/pitfalls.html ) +// - meaningful access functions index(), value() +template +class index_value + : public tuple +{ + typedef tuple base_t; + + template + struct iv_types + { + typedef typename tuples::element::type n_type; + + typedef typename tuples::access_traits::non_const_type non_const_type; + typedef typename tuples::access_traits::const_type const_type; + }; + +public: + typedef typename iv_types<0>::non_const_type index_type; + typedef typename iv_types<0>::const_type const_index_type; + typedef typename iv_types<1>::non_const_type value_type; + typedef typename iv_types<1>::const_type const_value_type; + + index_value() + { + } + + index_value(typename tuples::access_traits::parameter_type t0, + typename tuples::access_traits::parameter_type t1) + : base_t(t0, t1) + { + } + + // member functions index(), value() (non-const and const) + index_type index() + { + return boost::tuples::get<0>(*this); + } + + const_index_type index() const + { + return boost::tuples::get<0>(*this); + } + + value_type value() + { + return boost::tuples::get<1>(*this); + } + + const_value_type value() const + { + return boost::tuples::get<1>(*this); + } +}; + + } // namespace range + +namespace range_detail +{ + +template +struct indexed_iterator_value_type +{ + typedef ::boost::range::index_value< + typename iterator_reference::type, + typename iterator_difference::type + > type; +}; + +// Meta-function to get the traversal for the range and therefore iterator +// returned by the indexed adaptor for a specified iterator type. +// +// Random access -> Random access +// Bidirectional -> Forward +// Forward -> Forward +// SinglePass -> SinglePass +// +// The rationale for demoting a Bidirectional input to Forward is that the end +// iterator cannot cheaply have an index computed for it. Therefore I chose to +// demote to forward traversal. I can maintain the ability to traverse randomly +// when the input is Random Access since the index for the end iterator is cheap +// to compute. +template +struct indexed_traversal +{ +private: + typedef typename iterator_traversal::type wrapped_traversal; + +public: + + typedef typename mpl::if_< + is_convertible, + random_access_traversal_tag, + typename mpl::if_< + is_convertible, + forward_traversal_tag, + wrapped_traversal + >::type + >::type type; +}; + +template +class indexed_iterator + : public iterator_facade< + indexed_iterator, + typename indexed_iterator_value_type::type, + typename indexed_traversal::type, + typename indexed_iterator_value_type::type, + typename iterator_difference::type + > +{ +public: + typedef Iter wrapped; + +private: + typedef iterator_facade< + indexed_iterator, + typename indexed_iterator_value_type::type, + typename indexed_traversal::type, + typename indexed_iterator_value_type::type, + typename iterator_difference::type + > base_t; + +public: + typedef typename base_t::difference_type difference_type; + typedef typename base_t::reference reference; + typedef typename base_t::difference_type index_type; + + indexed_iterator() + : m_it() + , m_index() + { + } + + template + indexed_iterator( + const indexed_iterator& other, + typename enable_if >::type* = 0 + ) + : m_it(other.get()) + , m_index(other.get_index()) + { + } + + explicit indexed_iterator(wrapped it, index_type index) + : m_it(it) + , m_index(index) + { + } + + wrapped get() const + { + return m_it; + } + + index_type get_index() const + { + return m_index; + } + + private: + friend class boost::iterator_core_access; + + reference dereference() const + { + return reference(m_index, *m_it); + } + + bool equal(const indexed_iterator& other) const + { + return m_it == other.m_it; + } + + void increment() + { + ++m_index; + ++m_it; + } + + void decrement() + { + BOOST_ASSERT_MSG(m_index > 0, "indexed Iterator out of bounds"); + --m_index; + --m_it; + } + + void advance(index_type n) + { + m_index += n; + BOOST_ASSERT_MSG(m_index >= 0, "indexed Iterator out of bounds"); + m_it += n; + } + + difference_type distance_to(const indexed_iterator& other) const + { + return other.m_it - m_it; + } + + wrapped m_it; + index_type m_index; +}; + +template +struct indexed_range + : iterator_range< + indexed_iterator< + typename range_iterator::type + > + > +{ + typedef iterator_range< + indexed_iterator< + typename range_iterator::type + > + > base_t; + + BOOST_RANGE_CONCEPT_ASSERT(( + boost::SinglePassRangeConcept)); +public: + typedef indexed_iterator< + typename range_iterator::type + > iterator; + + // Constructor for non-random access iterators. + // This sets the end iterator index to i despite this being incorrect it + // is never observable since bidirectional iterators are demoted to + // forward iterators. + indexed_range( + typename base_t::difference_type i, + SinglePassRange& r, + single_pass_traversal_tag + ) + : base_t(iterator(boost::begin(r), i), + iterator(boost::end(r), i)) + { + } + + indexed_range( + typename base_t::difference_type i, + SinglePassRange& r, + random_access_traversal_tag + ) + : base_t(iterator(boost::begin(r), i), + iterator(boost::end(r), i + boost::size(r))) + { + } +}; + + } // namespace range_detail + + using range_detail::indexed_range; + + namespace adaptors + { + +template +inline indexed_range +operator|(SinglePassRange& r, indexed e) +{ + BOOST_RANGE_CONCEPT_ASSERT(( + boost::SinglePassRangeConcept + )); + return indexed_range( + e.val, r, + typename range_traversal::type()); +} + +template +inline indexed_range +operator|(const SinglePassRange& r, indexed e) +{ + BOOST_RANGE_CONCEPT_ASSERT(( + boost::SinglePassRangeConcept + )); + return indexed_range( + e.val, r, + typename range_traversal::type()); +} + +template +inline indexed_range +index( + SinglePassRange& rng, + typename range_difference::type index_value = 0) +{ + BOOST_RANGE_CONCEPT_ASSERT(( + boost::SinglePassRangeConcept + )); + return indexed_range( + index_value, rng, + typename range_traversal::type()); +} + +template +inline indexed_range +index( + const SinglePassRange& rng, + typename range_difference::type index_value = 0) +{ + BOOST_RANGE_CONCEPT_ASSERT(( + boost::SinglePassRangeConcept + )); + return indexed_range( + index_value, rng, + typename range_traversal::type()); +} + + } // namespace adaptors +} // namespace boost + +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) + +namespace std { + +#if defined(BOOST_CLANG) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmismatched-tags" +#endif + +template +struct tuple_element>: + boost::tuples::element> {}; + +template +struct tuple_size>: + std::integral_constant {}; + +#if defined(BOOST_CLANG) +#pragma clang diagnostic pop +#endif + +} // namespace std + +#endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) + +#endif // include guard diff --git a/libs/range/include/boost/range/adaptor/indirected.hpp b/libs/range/include/boost/range/adaptor/indirected.hpp new file mode 100644 index 00000000..e741f17f --- /dev/null +++ b/libs/range/include/boost/range/adaptor/indirected.hpp @@ -0,0 +1,100 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_INDIRECTED_HPP +#define BOOST_RANGE_ADAPTOR_INDIRECTED_HPP + +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + template< class R > + struct indirected_range : + public boost::iterator_range< + boost::indirect_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type + > + > + { + private: + typedef boost::iterator_range< + boost::indirect_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type + > + > + base; + + public: + explicit indirected_range( R& r ) + : base( r ) + { } + }; + + struct indirect_forwarder {}; + + template< class SinglePassRange > + inline indirected_range + operator|( SinglePassRange& r, indirect_forwarder ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return indirected_range( r ); + } + + template< class SinglePassRange > + inline indirected_range + operator|( const SinglePassRange& r, indirect_forwarder ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return indirected_range( r ); + } + + } // 'range_detail' + + using range_detail::indirected_range; + + namespace adaptors + { + namespace + { + const range_detail::indirect_forwarder indirected = + range_detail::indirect_forwarder(); + } + + template + inline indirected_range + indirect(SinglePassRange& rng) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + return indirected_range(rng); + } + + template + inline indirected_range + indirect(const SinglePassRange& rng) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return indirected_range(rng); + } + } // 'adaptors' + +} + +#endif diff --git a/libs/range/include/boost/range/adaptor/map.hpp b/libs/range/include/boost/range/adaptor/map.hpp new file mode 100644 index 00000000..2d922ea4 --- /dev/null +++ b/libs/range/include/boost/range/adaptor/map.hpp @@ -0,0 +1,204 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_MAP_HPP +#define BOOST_RANGE_ADAPTOR_MAP_HPP + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + struct map_keys_forwarder {}; + struct map_values_forwarder {}; + + template< class Map > + struct select_first + { + typedef BOOST_DEDUCED_TYPENAME range_reference::type argument_type; + typedef const BOOST_DEDUCED_TYPENAME range_value::type::first_type& result_type; + + result_type operator()( argument_type r ) const + { + return r.first; + } + }; + + template< class Map > + struct select_second_mutable + { + typedef BOOST_DEDUCED_TYPENAME range_reference::type argument_type; + typedef BOOST_DEDUCED_TYPENAME range_value::type::second_type& result_type; + + result_type operator()( argument_type r ) const + { + return r.second; + } + }; + + template< class Map > + struct select_second_const + { + typedef BOOST_DEDUCED_TYPENAME range_reference::type argument_type; + typedef const BOOST_DEDUCED_TYPENAME range_value::type::second_type& result_type; + + result_type operator()( argument_type r ) const + { + return r.second; + } + }; + + template + class select_first_range + : public transformed_range< + select_first, + const StdPairRng> + { + typedef transformed_range, const StdPairRng> base; + public: + typedef select_first transform_fn_type; + typedef const StdPairRng source_range_type; + + select_first_range(transform_fn_type fn, source_range_type& rng) + : base(fn, rng) + { + } + + select_first_range(const base& other) : base(other) {} + }; + + template + class select_second_mutable_range + : public transformed_range< + select_second_mutable, + StdPairRng> + { + typedef transformed_range, StdPairRng> base; + public: + typedef select_second_mutable transform_fn_type; + typedef StdPairRng source_range_type; + + select_second_mutable_range(transform_fn_type fn, source_range_type& rng) + : base(fn, rng) + { + } + + select_second_mutable_range(const base& other) : base(other) {} + }; + + template + class select_second_const_range + : public transformed_range< + select_second_const, + const StdPairRng> + { + typedef transformed_range, const StdPairRng> base; + public: + typedef select_second_const transform_fn_type; + typedef const StdPairRng source_range_type; + + select_second_const_range(transform_fn_type fn, source_range_type& rng) + : base(fn, rng) + { + } + + select_second_const_range(const base& other) : base(other) {} + }; + + template< class StdPairRng > + inline select_first_range + operator|( const StdPairRng& r, map_keys_forwarder ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return operator|( r, + boost::adaptors::transformed( select_first() ) ); + } + + template< class StdPairRng > + inline select_second_mutable_range + operator|( StdPairRng& r, map_values_forwarder ) + { + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + + return operator|( r, + boost::adaptors::transformed( select_second_mutable() ) ); + } + + template< class StdPairRng > + inline select_second_const_range + operator|( const StdPairRng& r, map_values_forwarder ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return operator|( r, + boost::adaptors::transformed( select_second_const() ) ); + } + + } // 'range_detail' + + using range_detail::select_first_range; + using range_detail::select_second_mutable_range; + using range_detail::select_second_const_range; + + namespace adaptors + { + namespace + { + const range_detail::map_keys_forwarder map_keys = + range_detail::map_keys_forwarder(); + + const range_detail::map_values_forwarder map_values = + range_detail::map_values_forwarder(); + } + + template + inline select_first_range + keys(const StdPairRange& rng) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return select_first_range( + range_detail::select_first(), rng ); + } + + template + inline select_second_const_range + values(const StdPairRange& rng) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return select_second_const_range( + range_detail::select_second_const(), rng ); + } + + template + inline select_second_mutable_range + values(StdPairRange& rng) + { + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + + return select_second_mutable_range( + range_detail::select_second_mutable(), rng ); + } + } // 'adaptors' + +} + +#endif diff --git a/libs/range/include/boost/range/adaptor/ref_unwrapped.hpp b/libs/range/include/boost/range/adaptor/ref_unwrapped.hpp new file mode 100644 index 00000000..7ac51154 --- /dev/null +++ b/libs/range/include/boost/range/adaptor/ref_unwrapped.hpp @@ -0,0 +1,102 @@ +// Boost.Range library +// +// Copyright Robin Eckert 2015. +// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_REF_UNWRAPPED_HPP +#define BOOST_RANGE_ADAPTOR_REF_UNWRAPPED_HPP + +#include +#include +#include +#include +#include + +#if !defined(BOOST_NO_CXX11_DECLTYPE) + +namespace boost +{ + namespace range_detail + { + struct ref_unwrapped_forwarder {}; + + template + struct unwrap_ref + { + typedef BOOST_DEDUCED_TYPENAME + range_reference::type argument_type; + + typedef decltype( boost::declval().get() ) result_type; + + result_type operator()( argument_type &&r ) const + { + return r.get(); + } + }; + + + template + class unwrap_ref_range + : public transformed_range, + SinglePassRange> + { + typedef transformed_range, + SinglePassRange> base; + public: + typedef unwrap_ref transform_fn_type; + typedef SinglePassRange source_range_type; + + unwrap_ref_range(transform_fn_type fn, source_range_type &rng) + : base(fn, rng) + { + } + + unwrap_ref_range(const base &other) : base(other) {} + }; + + template + inline unwrap_ref_range + operator|(SinglePassRange& r, ref_unwrapped_forwarder) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return operator|( r, + boost::adaptors::transformed(unwrap_ref())); + } + + } + + using range_detail::unwrap_ref_range; + + namespace adaptors + { + namespace + { + const range_detail::ref_unwrapped_forwarder ref_unwrapped = + range_detail::ref_unwrapped_forwarder(); + } + + template + inline unwrap_ref_range + ref_unwrap(SinglePassRange& rng) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return unwrap_ref_range( + range_detail::unwrap_ref(), rng ); + } + } // 'adaptors' + +} + +#endif + +#endif diff --git a/libs/range/include/boost/range/adaptor/replaced.hpp b/libs/range/include/boost/range/adaptor/replaced.hpp new file mode 100644 index 00000000..42eb52a2 --- /dev/null +++ b/libs/range/include/boost/range/adaptor/replaced.hpp @@ -0,0 +1,159 @@ +// Boost.Range library +// +// Copyright Neil Groves 2007. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_REPLACED_IMPL_HPP_INCLUDED +#define BOOST_RANGE_ADAPTOR_REPLACED_IMPL_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + template< class Value > + class replace_value + { + public: + typedef const Value& result_type; + typedef const Value& first_argument_type; + + // Rationale: + // The default constructor is required to allow the transform + // iterator to properly model the iterator concept. + replace_value() + { + } + + replace_value(const Value& from, const Value& to) + : m_impl(data(from, to)) + { + } + + const Value& operator()(const Value& x) const + { + return (x == m_impl->m_from) ? m_impl->m_to : x; + } + + private: + struct data + { + data(const Value& from, const Value& to) + : m_from(from) + , m_to(to) + { + } + + Value m_from; + Value m_to; + }; + boost::optional m_impl; + }; + + template< class R > + class replaced_range : + public boost::iterator_range< + boost::transform_iterator< + replace_value< BOOST_DEDUCED_TYPENAME range_value::type >, + BOOST_DEDUCED_TYPENAME range_iterator::type > > + { + private: + typedef replace_value< BOOST_DEDUCED_TYPENAME range_value::type > Fn; + + typedef boost::iterator_range< + boost::transform_iterator< + replace_value< BOOST_DEDUCED_TYPENAME range_value::type >, + BOOST_DEDUCED_TYPENAME range_iterator::type > > base_t; + + public: + typedef BOOST_DEDUCED_TYPENAME range_value::type value_type; + + replaced_range( R& r, value_type from, value_type to ) + : base_t( make_transform_iterator( boost::begin(r), Fn(from, to) ), + make_transform_iterator( boost::end(r), Fn(from, to) ) ) + { } + }; + + template< class T > + class replace_holder : public holder2 + { + public: + replace_holder( const T& from, const T& to ) + : holder2(from, to) + { } + private: + // not assignable + void operator=(const replace_holder&); + }; + + template< class SinglePassRange, class Value > + inline replaced_range + operator|(SinglePassRange& r, const replace_holder& f) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return replaced_range(r, f.val1, f.val2); + } + + template< class SinglePassRange, class Value > + inline replaced_range + operator|(const SinglePassRange& r, const replace_holder& f) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return replaced_range(r, f.val1, f.val2); + } + } // 'range_detail' + + using range_detail::replaced_range; + + namespace adaptors + { + namespace + { + const range_detail::forwarder2 + replaced = + range_detail::forwarder2(); + } + + template< class SinglePassRange, class Value > + inline replaced_range + replace(SinglePassRange& rng, Value from, Value to) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return replaced_range(rng, from, to); + } + + template< class SinglePassRange, class Value > + inline replaced_range + replace(const SinglePassRange& rng, Value from, Value to) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return replaced_range(rng, from ,to); + } + + } // 'adaptors' +} // 'boost' + +#endif // include guard diff --git a/libs/range/include/boost/range/adaptor/replaced_if.hpp b/libs/range/include/boost/range/adaptor/replaced_if.hpp new file mode 100644 index 00000000..83d3ec81 --- /dev/null +++ b/libs/range/include/boost/range/adaptor/replaced_if.hpp @@ -0,0 +1,165 @@ +// Boost.Range library +// +// Copyright Neil Groves 2007. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_REPLACED_IF_IMPL_HPP_INCLUDED +#define BOOST_RANGE_ADAPTOR_REPLACED_IF_IMPL_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + template< class Pred, class Value > + class replace_value_if + { + public: + typedef const Value& result_type; + typedef const Value& first_argument_type; + + // Rationale: + // required to allow the iterator to be default constructible. + replace_value_if() + { + } + + replace_value_if(const Pred& pred, const Value& to) + : m_impl(data(pred, to)) + { + } + + const Value& operator()(const Value& x) const + { + return m_impl->m_pred(x) ? m_impl->m_to : x; + } + + private: + struct data + { + data(const Pred& p, const Value& t) + : m_pred(p), m_to(t) + { + } + + Pred m_pred; + Value m_to; + }; + boost::optional m_impl; + }; + + template< class Pred, class R > + class replaced_if_range : + public boost::iterator_range< + boost::transform_iterator< + replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value::type >, + BOOST_DEDUCED_TYPENAME range_iterator::type > > + { + private: + typedef replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value::type > Fn; + + typedef boost::iterator_range< + boost::transform_iterator< + replace_value_if< Pred, BOOST_DEDUCED_TYPENAME range_value::type >, + BOOST_DEDUCED_TYPENAME range_iterator::type > > base_t; + + public: + typedef BOOST_DEDUCED_TYPENAME range_value::type value_type; + + replaced_if_range( R& r, const Pred& pred, value_type to ) + : base_t( make_transform_iterator( boost::begin(r), Fn(pred, to) ), + make_transform_iterator( boost::end(r), Fn(pred, to) ) ) + { } + }; + + template< class Pred, class T > + class replace_if_holder + { + public: + replace_if_holder( const Pred& pred, const T& to ) + : m_pred(pred), m_to(to) + { } + + const Pred& pred() const { return m_pred; } + const T& to() const { return m_to; } + + private: + Pred m_pred; + T m_to; + }; + + template< class Pred, class SinglePassRange, class Value > + inline replaced_if_range + operator|(SinglePassRange& r, const replace_if_holder& f) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return replaced_if_range( + r, f.pred(), f.to()); + } + + template< class Pred, class SinglePassRange, class Value > + inline replaced_if_range + operator|(const SinglePassRange& r, const replace_if_holder& f) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return replaced_if_range( + r, f.pred(), f.to()); + } + } // 'range_detail' + + using range_detail::replaced_if_range; + + namespace adaptors + { + namespace + { + const range_detail::forwarder2TU + replaced_if = + range_detail::forwarder2TU(); + } + + template< class Pred, class SinglePassRange, class Value > + inline replaced_if_range + replace_if(SinglePassRange& rng, Pred pred, Value to) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return range_detail::replaced_if_range( + rng, pred, to); + } + + template< class Pred, class SinglePassRange, class Value > + inline replaced_if_range + replace_if(const SinglePassRange& rng, Pred pred, Value to) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return range_detail::replaced_if_range( + rng, pred, to); + } + } // 'adaptors' + +} // 'boost' + +#endif // include guard diff --git a/libs/range/include/boost/range/adaptor/reversed.hpp b/libs/range/include/boost/range/adaptor/reversed.hpp new file mode 100644 index 00000000..944fbffc --- /dev/null +++ b/libs/range/include/boost/range/adaptor/reversed.hpp @@ -0,0 +1,103 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_REVERSED_HPP +#define BOOST_RANGE_ADAPTOR_REVERSED_HPP + +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + template< class R > + struct reversed_range : + public boost::iterator_range< + boost::reverse_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type + > + > + { + private: + typedef boost::iterator_range< + boost::reverse_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type + > + > + base; + + public: + typedef boost::reverse_iterator::type> iterator; + + explicit reversed_range( R& r ) + : base( iterator(boost::end(r)), iterator(boost::begin(r)) ) + { } + }; + + struct reverse_forwarder {}; + + template< class BidirectionalRange > + inline reversed_range + operator|( BidirectionalRange& r, reverse_forwarder ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + BidirectionalRangeConcept)); + + return reversed_range( r ); + } + + template< class BidirectionalRange > + inline reversed_range + operator|( const BidirectionalRange& r, reverse_forwarder ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + BidirectionalRangeConcept)); + + return reversed_range( r ); + } + + } // 'range_detail' + + using range_detail::reversed_range; + + namespace adaptors + { + namespace + { + const range_detail::reverse_forwarder reversed = + range_detail::reverse_forwarder(); + } + + template + inline reversed_range + reverse(BidirectionalRange& rng) + { + BOOST_RANGE_CONCEPT_ASSERT(( + BidirectionalRangeConcept)); + + return reversed_range(rng); + } + + template + inline reversed_range + reverse(const BidirectionalRange& rng) + { + BOOST_RANGE_CONCEPT_ASSERT(( + BidirectionalRangeConcept)); + + return reversed_range(rng); + } + } // 'adaptors' + +} // 'boost' + +#endif diff --git a/libs/range/include/boost/range/adaptor/sliced.hpp b/libs/range/include/boost/range/adaptor/sliced.hpp new file mode 100644 index 00000000..f8d96124 --- /dev/null +++ b/libs/range/include/boost/range/adaptor/sliced.hpp @@ -0,0 +1,97 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_SLICED_HPP +#define BOOST_RANGE_ADAPTOR_SLICED_HPP + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace adaptors + { + struct sliced + { + sliced(std::size_t t_, std::size_t u_) + : t(t_), u(u_) {} + std::size_t t; + std::size_t u; + }; + + template< class RandomAccessRange > + class sliced_range : public boost::iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > + { + typedef boost::iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > base_t; + public: + template + sliced_range(Rng& rng, T t, U u) + : base_t(boost::next(boost::begin(rng), t), + boost::next(boost::begin(rng), u)) + { + } + }; + + template< class RandomAccessRange > + inline sliced_range + slice( RandomAccessRange& rng, std::size_t t, std::size_t u ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + RandomAccessRangeConcept)); + + BOOST_ASSERT( t <= u && "error in slice indices" ); + BOOST_ASSERT( static_cast(boost::size(rng)) >= u && + "second slice index out of bounds" ); + + return sliced_range(rng, t, u); + } + + template< class RandomAccessRange > + inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > + slice( const RandomAccessRange& rng, std::size_t t, std::size_t u ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + RandomAccessRangeConcept)); + + BOOST_ASSERT( t <= u && "error in slice indices" ); + BOOST_ASSERT( static_cast(boost::size(rng)) >= u && + "second slice index out of bounds" ); + + return sliced_range(rng, t, u); + } + + template< class RandomAccessRange > + inline sliced_range + operator|( RandomAccessRange& r, const sliced& f ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + RandomAccessRangeConcept)); + + return sliced_range( r, f.t, f.u ); + } + + template< class RandomAccessRange > + inline sliced_range + operator|( const RandomAccessRange& r, const sliced& f ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + RandomAccessRangeConcept)); + + return sliced_range( r, f.t, f.u ); + } + + } // namespace adaptors + using adaptors::sliced_range; +} // namespace boost + +#endif diff --git a/libs/range/include/boost/range/adaptor/strided.hpp b/libs/range/include/boost/range/adaptor/strided.hpp new file mode 100644 index 00000000..560b8200 --- /dev/null +++ b/libs/range/include/boost/range/adaptor/strided.hpp @@ -0,0 +1,697 @@ +// Boost.Range library +// +// Copyright Neil Groves 2007. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED +#define BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED + +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + // strided_iterator for wrapping a forward traversal iterator + template + class strided_iterator + : public iterator_facade< + strided_iterator + , typename iterator_value::type + , forward_traversal_tag + , typename iterator_reference::type + , typename iterator_difference::type + > + { + friend class ::boost::iterator_core_access; + + typedef iterator_facade< + strided_iterator + , typename iterator_value::type + , forward_traversal_tag + , typename iterator_reference::type + , typename iterator_difference::type + > super_t; + + public: + typedef typename super_t::difference_type difference_type; + typedef typename super_t::reference reference; + typedef BaseIterator base_iterator; + typedef std::forward_iterator_tag iterator_category; + + strided_iterator() + : m_it() + , m_last() + , m_stride() + { + } + + strided_iterator(base_iterator it, + base_iterator last, + difference_type stride) + : m_it(it) + , m_last(last) + , m_stride(stride) + { + } + + template + strided_iterator( + const strided_iterator& other, + typename enable_if_convertible< + OtherIterator, + base_iterator + >::type* = 0 + ) + : m_it(other.base()) + , m_last(other.base_end()) + , m_stride(other.get_stride()) + { + } + + base_iterator base() const + { + return m_it; + } + + base_iterator base_end() const + { + return m_last; + } + + difference_type get_stride() const + { + return m_stride; + } + + private: + void increment() + { + for (difference_type i = 0; + (m_it != m_last) && (i < m_stride); ++i) + { + ++m_it; + } + } + + reference dereference() const + { + return *m_it; + } + + template + bool equal( + const strided_iterator& other, + typename enable_if_convertible< + OtherIterator, + base_iterator + >::type* = 0) const + { + return m_it == other.m_it; + } + + base_iterator m_it; + base_iterator m_last; + difference_type m_stride; + }; + + // strided_iterator for wrapping a bidirectional iterator + template + class strided_iterator + : public iterator_facade< + strided_iterator + , typename iterator_value::type + , bidirectional_traversal_tag + , typename iterator_reference::type + , typename iterator_difference::type + > + { + friend class ::boost::iterator_core_access; + + typedef iterator_facade< + strided_iterator + , typename iterator_value::type + , bidirectional_traversal_tag + , typename iterator_reference::type + , typename iterator_difference::type + > super_t; + public: + typedef typename super_t::difference_type difference_type; + typedef typename super_t::reference reference; + typedef BaseIterator base_iterator; + typedef typename boost::make_unsigned::type + size_type; + typedef std::bidirectional_iterator_tag iterator_category; + + strided_iterator() + : m_it() + , m_offset() + , m_index() + , m_stride() + { + } + + strided_iterator(base_iterator it, + size_type index, + difference_type stride) + : m_it(it) + , m_offset() + , m_index(index) + , m_stride(stride) + { + if (stride && ((m_index % stride) != 0)) + m_index += (stride - (m_index % stride)); + } + + template + strided_iterator( + const strided_iterator< + OtherIterator, + bidirectional_traversal_tag + >& other, + typename enable_if_convertible< + OtherIterator, + base_iterator + >::type* = 0 + ) + : m_it(other.base()) + , m_offset(other.get_offset()) + , m_index(other.get_index()) + , m_stride(other.get_stride()) + { + } + + base_iterator base() const + { + return m_it; + } + + difference_type get_offset() const + { + return m_offset; + } + + size_type get_index() const + { + return m_index; + } + + difference_type get_stride() const + { + return m_stride; + } + + private: + void increment() + { + m_offset += m_stride; + } + + void decrement() + { + m_offset -= m_stride; + } + + reference dereference() const + { + update(); + return *m_it; + } + + void update() const + { + std::advance(m_it, m_offset); + m_index += m_offset; + m_offset = 0; + } + + template + bool equal( + const strided_iterator< + OtherIterator, + bidirectional_traversal_tag + >& other, + typename enable_if_convertible< + OtherIterator, + base_iterator + >::type* = 0) const + { + return (m_index + m_offset) == + (other.get_index() + other.get_offset()); + } + + mutable base_iterator m_it; + mutable difference_type m_offset; + mutable size_type m_index; + difference_type m_stride; + }; + + // strided_iterator implementation for wrapping a random access iterator + template + class strided_iterator + : public iterator_facade< + strided_iterator + , typename iterator_value::type + , random_access_traversal_tag + , typename iterator_reference::type + , typename iterator_difference::type + > + { + friend class ::boost::iterator_core_access; + + typedef iterator_facade< + strided_iterator + , typename iterator_value::type + , random_access_traversal_tag + , typename iterator_reference::type + , typename iterator_difference::type + > super_t; + public: + typedef typename super_t::difference_type difference_type; + typedef typename super_t::reference reference; + typedef BaseIterator base_iterator; + typedef std::random_access_iterator_tag iterator_category; + + strided_iterator() + : m_it() + , m_first() + , m_index(0) + , m_stride() + { + } + + strided_iterator( + base_iterator first, + base_iterator it, + difference_type stride + ) + : m_it(it) + , m_first(first) + , m_index(stride ? (it - first) : difference_type()) + , m_stride(stride) + { + if (stride && ((m_index % stride) != 0)) + m_index += (stride - (m_index % stride)); + } + + template + strided_iterator( + const strided_iterator< + OtherIterator, + random_access_traversal_tag + >& other, + typename enable_if_convertible< + OtherIterator, + base_iterator + >::type* = 0 + ) + : m_it(other.base()) + , m_first(other.base_begin()) + , m_index(other.get_index()) + , m_stride(other.get_stride()) + { + } + + base_iterator base_begin() const + { + return m_first; + } + + base_iterator base() const + { + return m_it; + } + + difference_type get_stride() const + { + return m_stride; + } + + difference_type get_index() const + { + return m_index; + } + + private: + void increment() + { + m_index += m_stride; + } + + void decrement() + { + m_index -= m_stride; + } + + void advance(difference_type offset) + { + m_index += (m_stride * offset); + } + + // Implementation detail: only update the actual underlying iterator + // at the point of dereference. This is done so that the increment + // and decrement can overshoot the valid sequence as is required + // by striding. Since we can do all comparisons just with the index + // simply, and all dereferences must be within the valid range. + void update() const + { + m_it = m_first + m_index; + } + + template + difference_type distance_to( + const strided_iterator< + OtherIterator, + random_access_traversal_tag + >& other, + typename enable_if_convertible< + OtherIterator, base_iterator>::type* = 0) const + { + BOOST_ASSERT((other.m_index - m_index) % m_stride == difference_type()); + return (other.m_index - m_index) / m_stride; + } + + template + bool equal( + const strided_iterator< + OtherIterator, + random_access_traversal_tag + >& other, + typename enable_if_convertible< + OtherIterator, base_iterator>::type* = 0) const + { + return m_index == other.m_index; + } + + reference dereference() const + { + update(); + return *m_it; + } + + private: + mutable base_iterator m_it; + base_iterator m_first; + difference_type m_index; + difference_type m_stride; + }; + + template inline + strided_iterator< + typename range_iterator::type, + forward_traversal_tag + > + make_begin_strided_iterator( + Rng& rng, + Difference stride, + forward_traversal_tag) + { + return strided_iterator< + typename range_iterator::type, + forward_traversal_tag + >(boost::begin(rng), boost::end(rng), stride); + } + + template inline + strided_iterator< + typename range_iterator::type, + forward_traversal_tag + > + make_begin_strided_iterator( + const Rng& rng, + Difference stride, + forward_traversal_tag) + { + return strided_iterator< + typename range_iterator::type, + forward_traversal_tag + >(boost::begin(rng), boost::end(rng), stride); + } + + template inline + strided_iterator< + typename range_iterator::type, + forward_traversal_tag + > + make_end_strided_iterator( + Rng& rng, + Difference stride, + forward_traversal_tag) + { + return strided_iterator< + typename range_iterator::type, + forward_traversal_tag + >(boost::end(rng), boost::end(rng), stride); + } + + template inline + strided_iterator< + typename range_iterator::type, + forward_traversal_tag + > + make_end_strided_iterator( + const Rng& rng, + Difference stride, + forward_traversal_tag) + { + return strided_iterator< + typename range_iterator::type, + forward_traversal_tag + >(boost::end(rng), boost::end(rng), stride); + } + + template inline + strided_iterator< + typename range_iterator::type, + bidirectional_traversal_tag + > + make_begin_strided_iterator( + Rng& rng, + Difference stride, + bidirectional_traversal_tag) + { + typedef typename range_difference::type difference_type; + + return strided_iterator< + typename range_iterator::type, + bidirectional_traversal_tag + >(boost::begin(rng), difference_type(), stride); + } + + template inline + strided_iterator< + typename range_iterator::type, + bidirectional_traversal_tag + > + make_begin_strided_iterator( + const Rng& rng, + Difference stride, + bidirectional_traversal_tag) + { + typedef typename range_difference::type difference_type; + + return strided_iterator< + typename range_iterator::type, + bidirectional_traversal_tag + >(boost::begin(rng), difference_type(), stride); + } + + template inline + strided_iterator< + typename range_iterator::type, + bidirectional_traversal_tag + > + make_end_strided_iterator( + Rng& rng, + Difference stride, + bidirectional_traversal_tag) + { + return strided_iterator< + typename range_iterator::type, + bidirectional_traversal_tag + >(boost::end(rng), boost::size(rng), stride); + } + + template inline + strided_iterator< + typename range_iterator::type, + bidirectional_traversal_tag + > + make_end_strided_iterator( + const Rng& rng, + Difference stride, + bidirectional_traversal_tag) + { + return strided_iterator< + typename range_iterator::type, + bidirectional_traversal_tag + >(boost::end(rng), boost::size(rng), stride); + } + + template inline + strided_iterator< + typename range_iterator::type, + random_access_traversal_tag + > + make_begin_strided_iterator( + Rng& rng, + Difference stride, + random_access_traversal_tag) + { + return strided_iterator< + typename range_iterator::type, + random_access_traversal_tag + >(boost::begin(rng), boost::begin(rng), stride); + } + + template inline + strided_iterator< + typename range_iterator::type, + random_access_traversal_tag + > + make_begin_strided_iterator( + const Rng& rng, + Difference stride, + random_access_traversal_tag) + { + return strided_iterator< + typename range_iterator::type, + random_access_traversal_tag + >(boost::begin(rng), boost::begin(rng), stride); + } + + template inline + strided_iterator< + typename range_iterator::type, + random_access_traversal_tag + > + make_end_strided_iterator( + Rng& rng, + Difference stride, + random_access_traversal_tag) + { + return strided_iterator< + typename range_iterator::type, + random_access_traversal_tag + >(boost::begin(rng), boost::end(rng), stride); + } + + template inline + strided_iterator< + typename range_iterator::type, + random_access_traversal_tag + > + make_end_strided_iterator( + const Rng& rng, + Difference stride, + random_access_traversal_tag) + { + return strided_iterator< + typename range_iterator::type, + random_access_traversal_tag + >(boost::begin(rng), boost::end(rng), stride); + } + + template< + class Rng, + class Category = + typename iterators::pure_iterator_traversal< + typename range_iterator::type + >::type + > + class strided_range + : public iterator_range< + range_detail::strided_iterator< + typename range_iterator::type, + Category + > + > + { + typedef range_detail::strided_iterator< + typename range_iterator::type, + Category + > iter_type; + typedef iterator_range super_t; + public: + template + strided_range(Difference stride, Rng& rng) + : super_t( + range_detail::make_begin_strided_iterator( + rng, stride, + typename iterator_traversal< + typename range_iterator::type + >::type()), + range_detail::make_end_strided_iterator( + rng, stride, + typename iterator_traversal< + typename range_iterator::type + >::type())) + { + BOOST_ASSERT( stride >= 0 ); + } + }; + + template + class strided_holder : public holder + { + public: + explicit strided_holder(Difference value) + : holder(value) + { + } + }; + + template + inline strided_range + operator|(Rng& rng, const strided_holder& stride) + { + return strided_range(stride.val, rng); + } + + template + inline strided_range + operator|(const Rng& rng, const strided_holder& stride) + { + return strided_range(stride.val, rng); + } + + } // namespace range_detail + + using range_detail::strided_range; + + namespace adaptors + { + + namespace + { + const range_detail::forwarder + strided = range_detail::forwarder< + range_detail::strided_holder>(); + } + + template + inline strided_range + stride(Range& rng, Difference step) + { + return strided_range(step, rng); + } + + template + inline strided_range + stride(const Range& rng, Difference step) + { + return strided_range(step, rng); + } + + } // namespace 'adaptors' +} // namespace 'boost' + +#endif diff --git a/libs/range/include/boost/range/adaptor/tokenized.hpp b/libs/range/include/boost/range/adaptor/tokenized.hpp new file mode 100644 index 00000000..f0aa12ee --- /dev/null +++ b/libs/range/include/boost/range/adaptor/tokenized.hpp @@ -0,0 +1,137 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen, Neil Groves 2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_TOKENIZED_HPP +#define BOOST_RANGE_ADAPTOR_TOKENIZED_HPP + +#include +#include + +namespace boost +{ + namespace range_detail + { + + template< class R > + struct tokenized_range : + public boost::iterator_range< + boost::regex_token_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type + > + > + { + private: + typedef + boost::regex_token_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type + > + regex_iter; + + typedef BOOST_DEDUCED_TYPENAME regex_iter::regex_type + regex_type; + + typedef boost::iterator_range + base; + + public: + template< class Regex, class Submatch, class Flag > + tokenized_range( R& r, const Regex& re, const Submatch& sub, Flag f ) + : base( regex_iter( boost::begin(r), boost::end(r), + regex_type(re), sub, f ), + regex_iter() ) + { } + }; + + template< class T, class U, class V > + struct regex_holder + { + T re; + U sub; + V f; + + regex_holder( const T& rex, const U& subm, V flag ) : + re(rex), sub(subm), f(flag) + { } + private: + // Not assignable + void operator=(const regex_holder&); + }; + + struct regex_forwarder + { + template< class Regex > + regex_holder + operator()( const Regex& re, + int submatch = 0, + regex_constants::match_flag_type f = + regex_constants::match_default ) const + { + return regex_holder( re, submatch, f ); + } + + template< class Regex, class Submatch > + regex_holder + operator()( const Regex& re, + const Submatch& sub, + regex_constants::match_flag_type f = + regex_constants::match_default ) const + { + return regex_holder( re, sub, f ); + } + }; + + template< class BidirectionalRng, class R, class S, class F > + inline tokenized_range + operator|( BidirectionalRng& r, + const regex_holder& f ) + { + return tokenized_range( r, f.re, f.sub, f.f ); + } + + template< class BidirectionalRng, class R, class S, class F > + inline tokenized_range + operator|( const BidirectionalRng& r, + const regex_holder& f ) + { + return tokenized_range( r, f.re, f.sub, f.f ); + } + + } // 'range_detail' + + using range_detail::tokenized_range; + + namespace adaptors + { + namespace + { + const range_detail::regex_forwarder tokenized = + range_detail::regex_forwarder(); + } + + template + inline tokenized_range + tokenize(BidirectionalRange& rng, const Regex& reg, const Submatch& sub, Flag f) + { + return tokenized_range(rng, reg, sub, f); + } + + template + inline tokenized_range + tokenize(const BidirectionalRange& rng, const Regex& reg, const Submatch& sub, Flag f) + { + return tokenized_range(rng, reg, sub, f); + } + } // 'adaptors' + +} + +#endif diff --git a/libs/range/include/boost/range/adaptor/transformed.hpp b/libs/range/include/boost/range/adaptor/transformed.hpp new file mode 100644 index 00000000..428ff4be --- /dev/null +++ b/libs/range/include/boost/range/adaptor/transformed.hpp @@ -0,0 +1,137 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_TRANSFORMED_HPP +#define BOOST_RANGE_ADAPTOR_TRANSFORMED_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + // A type generator to produce the transform_iterator type conditionally + // including a wrapped predicate as appropriate. + template + struct transform_iterator_gen + { + typedef transform_iterator< + typename default_constructible_unary_fn_gen< + P, + typename transform_iterator::reference + >::type, + It + > type; + }; + + template< class F, class R > + struct transformed_range : + public boost::iterator_range< + typename transform_iterator_gen< + F, typename range_iterator::type>::type> + { + private: + typedef typename transform_iterator_gen< + F, typename range_iterator::type>::type transform_iter_t; + + typedef boost::iterator_range base; + + public: + typedef typename default_constructible_unary_fn_gen< + F, + typename transform_iterator< + F, + typename range_iterator::type + >::reference + >::type transform_fn_type; + + typedef R source_range_type; + + transformed_range(transform_fn_type f, R& r) + : base(transform_iter_t(boost::begin(r), f), + transform_iter_t(boost::end(r), f)) + { + } + }; + + template< class T > + struct transform_holder : holder + { + transform_holder( T r ) : holder(r) + { + } + }; + + template< class SinglePassRange, class UnaryFunction > + inline transformed_range + operator|( SinglePassRange& r, + const transform_holder& f ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return transformed_range( f.val, r ); + } + + template< class SinglePassRange, class UnaryFunction > + inline transformed_range + operator|( const SinglePassRange& r, + const transform_holder& f ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return transformed_range( + f.val, r); + } + + } // 'range_detail' + + using range_detail::transformed_range; + + namespace adaptors + { + namespace + { + const range_detail::forwarder + transformed = + range_detail::forwarder(); + } + + template + inline transformed_range + transform(SinglePassRange& rng, UnaryFunction fn) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return transformed_range(fn, rng); + } + + template + inline transformed_range + transform(const SinglePassRange& rng, UnaryFunction fn) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return transformed_range( + fn, rng); + } + } // 'adaptors' + +} + +#endif diff --git a/libs/range/include/boost/range/adaptor/type_erased.hpp b/libs/range/include/boost/range/adaptor/type_erased.hpp new file mode 100644 index 00000000..ba5b1598 --- /dev/null +++ b/libs/range/include/boost/range/adaptor/type_erased.hpp @@ -0,0 +1,196 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ADAPTOR_TYPE_ERASED_HPP_INCLUDED +#define BOOST_RANGE_ADAPTOR_TYPE_ERASED_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace adaptors + { + template< + class Value = use_default + , class Traversal = use_default + , class Reference = use_default + , class Difference = use_default + , class Buffer = use_default + > + struct type_erased + { + }; + + template< + class SinglePassRange + , class Value + , class Traversal + , class Reference + , class Difference + , class Buffer + > + typename any_range_type_generator< + SinglePassRange + , Value + , Traversal + , Reference + , Difference + , Buffer + >::type + operator|(SinglePassRange& rng, + type_erased< + Value + , Traversal + , Reference + , Difference + , Buffer + >) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + typedef typename any_range_type_generator< + SinglePassRange + , Value + , Traversal + , Reference + , Difference + , Buffer + >::type range_type; + return range_type(boost::begin(rng), boost::end(rng)); + } + + template< + class SinglePassRange + , class Value + , class Traversal + , class Reference + , class Difference + , class Buffer + > + typename any_range_type_generator< + const SinglePassRange + , Value + , Traversal + , Reference + , Difference + , Buffer + >::type + operator|(const SinglePassRange& rng, + type_erased< + Value + , Traversal + , Reference + , Difference + , Buffer + >) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + typedef typename any_range_type_generator< + const SinglePassRange + , Value + , Traversal + , Reference + , Difference + , Buffer + >::type range_type; + return range_type(boost::begin(rng), boost::end(rng)); + } + + template< + class SinglePassRange + , class Value + , class Traversal + , class Reference + , class Difference + , class Buffer + > + typename any_range_type_generator< + SinglePassRange + , Value + , Traversal + , Reference + , Difference + , Buffer + >::type + type_erase(SinglePassRange& rng + , type_erased< + Value + , Traversal + , Reference + , Difference + , Buffer + > = type_erased<>() + ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + typedef typename any_range_type_generator< + SinglePassRange + , Value + , Traversal + , Reference + , Difference + , Buffer + >::type range_type; + + return range_type(boost::begin(rng), boost::end(rng)); + } + + template< + class SinglePassRange + , class Value + , class Traversal + , class Reference + , class Difference + , class Buffer + > + typename any_range_type_generator< + const SinglePassRange + , Value + , Traversal + , Reference + , Difference + , Buffer + >::type + type_erase(const SinglePassRange& rng + , type_erased< + Value + , Traversal + , Reference + , Difference + , Buffer + > = type_erased<>() + ) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + typedef typename any_range_type_generator< + const SinglePassRange + , Value + , Traversal + , Reference + , Difference + , Buffer + >::type range_type; + + return range_type(boost::begin(rng), boost::end(rng)); + } + } +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/adaptor/uniqued.hpp b/libs/range/include/boost/range/adaptor/uniqued.hpp new file mode 100644 index 00000000..29101d32 --- /dev/null +++ b/libs/range/include/boost/range/adaptor/uniqued.hpp @@ -0,0 +1,97 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_UNIQUED_IMPL_HPP +#define BOOST_RANGE_ADAPTOR_UNIQUED_IMPL_HPP + +#include +#include + +namespace boost +{ + + namespace range_detail + { + struct unique_forwarder { }; + + struct unique_not_equal_to + { + typedef bool result_type; + + template< class T > + bool operator()( const T& l, const T& r ) const + { + return !(l == r); + } + }; + + template + class uniqued_range : public adjacent_filtered_range + { + typedef adjacent_filtered_range base; + public: + explicit uniqued_range(ForwardRng& rng) + : base(unique_not_equal_to(), rng) + { + } + }; + + template< class ForwardRng > + inline uniqued_range + operator|( ForwardRng& r, + unique_forwarder ) + { + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return uniqued_range(r); + } + + template< class ForwardRng > + inline uniqued_range + operator|( const ForwardRng& r, + unique_forwarder ) + { + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return uniqued_range(r); + } + + } // 'range_detail' + + using range_detail::uniqued_range; + + namespace adaptors + { + namespace + { + const range_detail::unique_forwarder uniqued = + range_detail::unique_forwarder(); + } + + template + inline uniqued_range + unique(ForwardRange& rng) + { + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return uniqued_range(rng); + } + + template + inline uniqued_range + unique(const ForwardRange& rng) + { + BOOST_RANGE_CONCEPT_ASSERT(( + ForwardRangeConcept)); + + return uniqued_range(rng); + } + } // 'adaptors' + +} + +#endif diff --git a/libs/range/include/boost/range/adaptors.hpp b/libs/range/include/boost/range/adaptors.hpp new file mode 100644 index 00000000..0530c4d3 --- /dev/null +++ b/libs/range/include/boost/range/adaptors.hpp @@ -0,0 +1,31 @@ +// Boost.Range library +// +// Copyright Neil Groves 2007. +// Copyright Thorsten Ottosen 2006. +// Use, modification and distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTORS_HPP +#define BOOST_RANGE_ADAPTORS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/libs/range/include/boost/range/algorithm.hpp b/libs/range/include/boost/range/algorithm.hpp new file mode 100644 index 00000000..30dc5836 --- /dev/null +++ b/libs/range/include/boost/range/algorithm.hpp @@ -0,0 +1,104 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file algorithm.hpp +/// Includes the range-based versions of the algorithms in the +/// C++ standard header file +// +///////////////////////////////////////////////////////////////////////////// + +// Copyright 2009 Neil Groves. +// 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) +// +// Acknowledgements: +// This code uses combinations of ideas, techniques and code snippets +// from: Thorsten Ottosen, Eric Niebler, Jeremy Siek, +// and Vladimir Prus' +// +// The original mutating algorithms that served as the first version +// were originally written by Vladimir Prus' +// code from Boost Wiki + +#if defined(_MSC_VER) +#pragma once +#endif + +#ifndef BOOST_RANGE_ALGORITHM_HPP_INCLUDED_01012009 +#define BOOST_RANGE_ALGORITHM_HPP_INCLUDED_01012009 + +#include +#include +#include +#include +#include +#include +#include + +// Non-mutating algorithms +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Mutating algorithms +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Binary search +#include +#include +#include +#include + +// Set operations of sorted ranges +#include + +// Heap operations +#include + +// Minimum and Maximum +#include +#include + +// Permutations +#include + +#endif // include guard + diff --git a/libs/range/include/boost/range/algorithm/adjacent_find.hpp b/libs/range/include/boost/range/algorithm/adjacent_find.hpp new file mode 100644 index 00000000..1b88dae8 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/adjacent_find.hpp @@ -0,0 +1,125 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_ADJACENT_FIND_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_ADJACENT_FIND_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function adjacent_find +/// +/// range-based version of the adjacent_find std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template< typename ForwardRange > +inline typename range_iterator::type +adjacent_find(ForwardRange & rng) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return std::adjacent_find(boost::begin(rng),boost::end(rng)); +} + +/// \overload +template< typename ForwardRange > +inline typename range_iterator::type +adjacent_find(const ForwardRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return std::adjacent_find(boost::begin(rng),boost::end(rng)); +} + +/// \overload +template< typename ForwardRange, typename BinaryPredicate > +inline typename range_iterator::type +adjacent_find(ForwardRange & rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, + typename range_value::type>)); + return std::adjacent_find(boost::begin(rng),boost::end(rng),pred); +} + +/// \overload +template< typename ForwardRange, typename BinaryPredicate > +inline typename range_iterator::type +adjacent_find(const ForwardRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, + typename range_value::type>)); + return std::adjacent_find(boost::begin(rng),boost::end(rng),pred); +} + +// range_return overloads + +/// \overload +template< range_return_value re, typename ForwardRange > +inline typename range_return::type +adjacent_find(ForwardRange & rng) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return range_return:: + pack(std::adjacent_find(boost::begin(rng),boost::end(rng)), + rng); +} + +/// \overload +template< range_return_value re, typename ForwardRange > +inline typename range_return::type +adjacent_find(const ForwardRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return range_return:: + pack(std::adjacent_find(boost::begin(rng),boost::end(rng)), + rng); +} + +/// \overload +template< range_return_value re, typename ForwardRange, typename BinaryPredicate > +inline typename range_return::type +adjacent_find(ForwardRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, + typename range_value::type>)); + return range_return:: + pack(std::adjacent_find(boost::begin(rng),boost::end(rng),pred), + rng); +} + +/// \overload +template< range_return_value re, typename ForwardRange, typename BinaryPredicate > +inline typename range_return::type +adjacent_find(const ForwardRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return range_return:: + pack(std::adjacent_find(boost::begin(rng),boost::end(rng),pred), + rng); +} + + } // namespace range + using range::adjacent_find; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/binary_search.hpp b/libs/range/include/boost/range/algorithm/binary_search.hpp new file mode 100644 index 00000000..bb64ec8f --- /dev/null +++ b/libs/range/include/boost/range/algorithm/binary_search.hpp @@ -0,0 +1,49 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_BINARY_SEARCH_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_BINARY_SEARCH_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function binary_search +/// +/// range-based version of the binary_search std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline bool binary_search(const ForwardRange& rng, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::binary_search(boost::begin(rng), boost::end(rng), val); +} + +/// \overload +template +inline bool binary_search(const ForwardRange& rng, const Value& val, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::binary_search(boost::begin(rng), boost::end(rng), val, pred); +} + + } // namespace range + using range::binary_search; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/copy.hpp b/libs/range/include/boost/range/algorithm/copy.hpp new file mode 100644 index 00000000..f15b31f9 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/copy.hpp @@ -0,0 +1,41 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_COPY_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_COPY_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function copy +/// +/// range-based version of the copy std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +/// \pre OutputIterator is a model of the OutputIteratorConcept +template< class SinglePassRange, class OutputIterator > +inline OutputIterator copy(const SinglePassRange& rng, OutputIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::copy(boost::begin(rng),boost::end(rng),out); +} + + } // namespace range + using range::copy; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/copy_backward.hpp b/libs/range/include/boost/range/algorithm/copy_backward.hpp new file mode 100644 index 00000000..c95c6f1f --- /dev/null +++ b/libs/range/include/boost/range/algorithm/copy_backward.hpp @@ -0,0 +1,43 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_COPY_BACKWARD_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_COPY_BACKWARD_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function copy_backward +/// +/// range-based version of the copy_backwards std algorithm +/// +/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept +/// \pre BidirectionalTraversalWriteableIterator is a model of the BidirectionalIteratorConcept +/// \pre BidirectionalTraversalWriteableIterator is a model of the WriteableIteratorConcept +template< class BidirectionalRange, class BidirectionalTraversalWriteableIterator > +inline BidirectionalTraversalWriteableIterator +copy_backward(const BidirectionalRange& rng, + BidirectionalTraversalWriteableIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return std::copy_backward(boost::begin(rng), boost::end(rng), out); +} + + } // namespace range + using range::copy_backward; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/count.hpp b/libs/range/include/boost/range/algorithm/count.hpp new file mode 100644 index 00000000..8316ce0f --- /dev/null +++ b/libs/range/include/boost/range/algorithm/count.hpp @@ -0,0 +1,50 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_COUNT_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_COUNT_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function count +/// +/// range-based version of the count std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +template< class SinglePassRange, class Value > +inline BOOST_DEDUCED_TYPENAME range_difference::type +count(SinglePassRange& rng, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::count(boost::begin(rng), boost::end(rng), val); +} + +/// \overload +template< class SinglePassRange, class Value > +inline BOOST_DEDUCED_TYPENAME range_difference::type +count(const SinglePassRange& rng, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::count(boost::begin(rng), boost::end(rng), val); +} + + } // namespace range + using range::count; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/count_if.hpp b/libs/range/include/boost/range/algorithm/count_if.hpp new file mode 100644 index 00000000..ae17b0e3 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/count_if.hpp @@ -0,0 +1,51 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_COUNT_IF_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_COUNT_IF_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function count_if +/// +/// range-based version of the count_if std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +/// \pre UnaryPredicate is a model of the UnaryPredicateConcept +template< class SinglePassRange, class UnaryPredicate > +inline BOOST_DEDUCED_TYPENAME boost::range_difference::type +count_if(SinglePassRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::count_if(boost::begin(rng), boost::end(rng), pred); +} + +/// \overload +template< class SinglePassRange, class UnaryPredicate > +inline BOOST_DEDUCED_TYPENAME boost::range_difference::type +count_if(const SinglePassRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::count_if(boost::begin(rng), boost::end(rng), pred); +} + + } // namespace range + using range::count_if; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/equal.hpp b/libs/range/include/boost/range/algorithm/equal.hpp new file mode 100644 index 00000000..2b44f3bc --- /dev/null +++ b/libs/range/include/boost/range/algorithm/equal.hpp @@ -0,0 +1,200 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. +// Use, modification and distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_EQUAL_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_EQUAL_HPP_INCLUDED + +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + // An implementation of equality comparison that is optimized for iterator + // traversal categories less than RandomAccessTraversal. + template< class SinglePassTraversalReadableIterator1, + class SinglePassTraversalReadableIterator2, + class IteratorCategoryTag1, + class IteratorCategoryTag2 > + inline bool equal_impl( SinglePassTraversalReadableIterator1 first1, + SinglePassTraversalReadableIterator1 last1, + SinglePassTraversalReadableIterator2 first2, + SinglePassTraversalReadableIterator2 last2, + IteratorCategoryTag1, + IteratorCategoryTag2 ) + { + for (;;) + { + // If we have reached the end of the left range then this is + // the end of the loop. They are equal if and only if we have + // simultaneously reached the end of the right range. + if (first1 == last1) + return first2 == last2; + + // If we have reached the end of the right range at this line + // it indicates that the right range is shorter than the left + // and hence the result is false. + if (first2 == last2) + return false; + + // continue looping if and only if the values are equal + if (*first1 != *first2) + break; + + ++first1; + ++first2; + } + + // Reaching this line in the algorithm indicates that a value + // inequality has been detected. + return false; + } + + template< class SinglePassTraversalReadableIterator1, + class SinglePassTraversalReadableIterator2, + class IteratorCategoryTag1, + class IteratorCategoryTag2, + class BinaryPredicate > + inline bool equal_impl( SinglePassTraversalReadableIterator1 first1, + SinglePassTraversalReadableIterator1 last1, + SinglePassTraversalReadableIterator2 first2, + SinglePassTraversalReadableIterator2 last2, + BinaryPredicate pred, + IteratorCategoryTag1, + IteratorCategoryTag2 ) + { + for (;;) + { + // If we have reached the end of the left range then this is + // the end of the loop. They are equal if and only if we have + // simultaneously reached the end of the right range. + if (first1 == last1) + return first2 == last2; + + // If we have reached the end of the right range at this line + // it indicates that the right range is shorter than the left + // and hence the result is false. + if (first2 == last2) + return false; + + // continue looping if and only if the values are equal + if (!pred(*first1, *first2)) + break; + + ++first1; + ++first2; + } + + // Reaching this line in the algorithm indicates that a value + // inequality has been detected. + return false; + } + + // An implementation of equality comparison that is optimized for + // random access iterators. + template< class RandomAccessTraversalReadableIterator1, + class RandomAccessTraversalReadableIterator2 > + inline bool equal_impl( RandomAccessTraversalReadableIterator1 first1, + RandomAccessTraversalReadableIterator1 last1, + RandomAccessTraversalReadableIterator2 first2, + RandomAccessTraversalReadableIterator2 last2, + std::random_access_iterator_tag, + std::random_access_iterator_tag ) + { + return ((last1 - first1) == (last2 - first2)) + && std::equal(first1, last1, first2); + } + + template< class RandomAccessTraversalReadableIterator1, + class RandomAccessTraversalReadableIterator2, + class BinaryPredicate > + inline bool equal_impl( RandomAccessTraversalReadableIterator1 first1, + RandomAccessTraversalReadableIterator1 last1, + RandomAccessTraversalReadableIterator2 first2, + RandomAccessTraversalReadableIterator2 last2, + BinaryPredicate pred, + std::random_access_iterator_tag, + std::random_access_iterator_tag ) + { + return ((last1 - first1) == (last2 - first2)) + && std::equal(first1, last1, first2, pred); + } + + template< class SinglePassTraversalReadableIterator1, + class SinglePassTraversalReadableIterator2 > + inline bool equal( SinglePassTraversalReadableIterator1 first1, + SinglePassTraversalReadableIterator1 last1, + SinglePassTraversalReadableIterator2 first2, + SinglePassTraversalReadableIterator2 last2 ) + { + BOOST_DEDUCED_TYPENAME std::iterator_traits< SinglePassTraversalReadableIterator1 >::iterator_category tag1; + BOOST_DEDUCED_TYPENAME std::iterator_traits< SinglePassTraversalReadableIterator2 >::iterator_category tag2; + + return equal_impl(first1, last1, first2, last2, tag1, tag2); + } + + template< class SinglePassTraversalReadableIterator1, + class SinglePassTraversalReadableIterator2, + class BinaryPredicate > + inline bool equal( SinglePassTraversalReadableIterator1 first1, + SinglePassTraversalReadableIterator1 last1, + SinglePassTraversalReadableIterator2 first2, + SinglePassTraversalReadableIterator2 last2, + BinaryPredicate pred ) + { + BOOST_DEDUCED_TYPENAME std::iterator_traits< SinglePassTraversalReadableIterator1 >::iterator_category tag1; + BOOST_DEDUCED_TYPENAME std::iterator_traits< SinglePassTraversalReadableIterator2 >::iterator_category tag2; + + return equal_impl(first1, last1, first2, last2, pred, tag1, tag2); + } + + } // namespace range_detail + + namespace range + { + + /// \brief template function equal + /// + /// range-based version of the equal std algorithm + /// + /// \pre SinglePassRange1 is a model of the SinglePassRangeConcept + /// \pre SinglePassRange2 is a model of the SinglePassRangeConcept + /// \pre BinaryPredicate is a model of the BinaryPredicateConcept + template< class SinglePassRange1, class SinglePassRange2 > + inline bool equal( const SinglePassRange1& rng1, const SinglePassRange2& rng2 ) + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::equal( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2) ); + } + + /// \overload + template< class SinglePassRange1, class SinglePassRange2, class BinaryPredicate > + inline bool equal( const SinglePassRange1& rng1, const SinglePassRange2& rng2, + BinaryPredicate pred ) + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::equal( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2), + pred); + } + + } // namespace range + using ::boost::range::equal; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/equal_range.hpp b/libs/range/include/boost/range/algorithm/equal_range.hpp new file mode 100644 index 00000000..4aa4a54d --- /dev/null +++ b/libs/range/include/boost/range/algorithm/equal_range.hpp @@ -0,0 +1,80 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_EQUAL_RANGE_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_EQUAL_RANGE_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function equal_range +/// +/// range-based version of the equal_range std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +/// \pre SortPredicate is a model of the BinaryPredicateConcept +template +inline std::pair< + BOOST_DEDUCED_TYPENAME boost::range_iterator::type, + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + > +equal_range(ForwardRange& rng, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::equal_range(boost::begin(rng), boost::end(rng), val); +} + +/// \overload +template +inline std::pair< + BOOST_DEDUCED_TYPENAME boost::range_iterator::type, + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + > +equal_range(const ForwardRange& rng, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::equal_range(boost::begin(rng), boost::end(rng), val); +} + +/// \overload +template +inline std::pair< + BOOST_DEDUCED_TYPENAME boost::range_iterator::type, + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + > +equal_range(ForwardRange& rng, const Value& val, SortPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::equal_range(boost::begin(rng), boost::end(rng), val, pred); +} + +/// \overload +template +inline std::pair< + BOOST_DEDUCED_TYPENAME boost::range_iterator::type, + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + > +equal_range(const ForwardRange& rng, const Value& val, SortPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::equal_range(boost::begin(rng), boost::end(rng), val, pred); +} + + } // namespace range + using range::equal_range; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/fill.hpp b/libs/range/include/boost/range/algorithm/fill.hpp new file mode 100644 index 00000000..95231a82 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/fill.hpp @@ -0,0 +1,49 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_FILL_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_FILL_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function fill +/// +/// range-based version of the fill std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +template< class ForwardRange, class Value > +inline ForwardRange& fill(ForwardRange& rng, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + std::fill(boost::begin(rng), boost::end(rng), val); + return rng; +} + +/// \overload +template< class ForwardRange, class Value > +inline const ForwardRange& fill(const ForwardRange& rng, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + std::fill(boost::begin(rng), boost::end(rng), val); + return rng; +} + + } // namespace range + using range::fill; +} + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/fill_n.hpp b/libs/range/include/boost/range/algorithm/fill_n.hpp new file mode 100644 index 00000000..02a0c2a3 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/fill_n.hpp @@ -0,0 +1,53 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_FILL_N_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_FILL_N_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function fill_n +/// +/// range-based version of the fill_n std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +/// \pre n <= std::distance(boost::begin(rng), boost::end(rng)) +template< class ForwardRange, class Size, class Value > +inline ForwardRange& fill_n(ForwardRange& rng, Size n, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_ASSERT( static_cast(std::distance(boost::begin(rng), boost::end(rng))) >= n ); + std::fill_n(boost::begin(rng), n, val); + return rng; +} + +/// \overload +template< class ForwardRange, class Size, class Value > +inline const ForwardRange& fill_n(const ForwardRange& rng, Size n, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_ASSERT( static_cast(std::distance(boost::begin(rng), boost::end(rng))) >= n ); + std::fill_n(boost::begin(rng), n, val); + return rng; +} + + } // namespace range + using range::fill_n; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/find.hpp b/libs/range/include/boost/range/algorithm/find.hpp new file mode 100644 index 00000000..72c5cf15 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/find.hpp @@ -0,0 +1,80 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_FIND_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_FIND_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function find +/// +/// range-based version of the find std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +template< class SinglePassRange, class Value > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_iterator::type +>::type +find( SinglePassRange& rng, const Value& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::find(boost::begin(rng), boost::end(rng), val); +} + +/// \overload +template< class SinglePassRange, class Value > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +find( const SinglePassRange& rng, const Value& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::find(boost::begin(rng), boost::end(rng), val); +} + +// range_return overloads + +/// \overload +template< range_return_value re, class SinglePassRange, class Value > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_return::type +>::type +find( SinglePassRange& rng, const Value& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return range_return:: + pack(std::find(boost::begin(rng), boost::end(rng), val), + rng); +} + +/// \overload +template< range_return_value re, class SinglePassRange, class Value > +inline BOOST_DEDUCED_TYPENAME range_return::type +find( const SinglePassRange& rng, const Value& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return range_return:: + pack(std::find(boost::begin(rng), boost::end(rng), val), + rng); +} + + } // namespace range + using range::find; +} + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/find_end.hpp b/libs/range/include/boost/range/algorithm/find_end.hpp new file mode 100644 index 00000000..757e9996 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/find_end.hpp @@ -0,0 +1,152 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_FIND_END_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_FIND_END_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function find_end +/// +/// range-based version of the find_end std algorithm +/// +/// \pre ForwardRange1 is a model of the ForwardRangeConcept +/// \pre ForwardRange2 is a model of the ForwardRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template< class ForwardRange1, class ForwardRange2 > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_iterator< ForwardRange1 >::type +>::type +find_end(ForwardRange1 & rng1, const ForwardRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return std::find_end(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2)); +} + +/// \overload +template< class ForwardRange1, class ForwardRange2 > +inline BOOST_DEDUCED_TYPENAME range_iterator< const ForwardRange1 >::type +find_end(const ForwardRange1 & rng1, const ForwardRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return std::find_end(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2)); +} + +/// \overload +template< class ForwardRange1, class ForwardRange2, class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_iterator::type +>::type +find_end(ForwardRange1 & rng1, const ForwardRange2& rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return std::find_end(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2),pred); +} + +/// \overload +template< class ForwardRange1, class ForwardRange2, class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +find_end(const ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return std::find_end(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2),pred); +} + +/// \overload +template< range_return_value re, class ForwardRange1, class ForwardRange2 > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_return::type +>::type +find_end(ForwardRange1& rng1, const ForwardRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return range_return:: + pack(std::find_end(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2)), + rng1); +} + +/// \overload +template< range_return_value re, class ForwardRange1, class ForwardRange2 > +inline BOOST_DEDUCED_TYPENAME range_return::type +find_end(const ForwardRange1& rng1, const ForwardRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return range_return:: + pack(std::find_end(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2)), + rng1); +} + +/// \overload +template< range_return_value re, class ForwardRange1, class ForwardRange2, + class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_return::type +>::type +find_end(ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return range_return:: + pack(std::find_end(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), pred), + rng1); +} + +/// \overload +template< range_return_value re, class ForwardRange1, class ForwardRange2, + class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +find_end(const ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return range_return:: + pack(std::find_end(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), pred), + rng1); +} + + } // namespace range + using range::find_end; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/find_first_of.hpp b/libs/range/include/boost/range/algorithm/find_first_of.hpp new file mode 100644 index 00000000..4cb5989a --- /dev/null +++ b/libs/range/include/boost/range/algorithm/find_first_of.hpp @@ -0,0 +1,155 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_FIND_FIRST_OF_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_FIND_FIRST_OF_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function find_first_of +/// +/// range-based version of the find_first_of std algorithm +/// +/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept +/// \pre ForwardRange2 is a model of the ForwardRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template< class SinglePassRange1, class ForwardRange2 > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_iterator::type +>::type +find_first_of(SinglePassRange1 & rng1, ForwardRange2 const & rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return std::find_first_of(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2)); +} + +/// \overload +template< class SinglePassRange1, class ForwardRange2 > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +find_first_of(const SinglePassRange1& rng1, const ForwardRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return std::find_first_of(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2)); +} + +/// \overload +template< class SinglePassRange1, class ForwardRange2, class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_iterator::type +>::type +find_first_of(SinglePassRange1 & rng1, ForwardRange2 const & rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return std::find_first_of(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2),pred); +} + +/// \overload +template< class SinglePassRange1, class ForwardRange2, class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +find_first_of(const SinglePassRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return std::find_first_of(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2),pred); +} + +// range return overloads +/// \overload +template< range_return_value re, class SinglePassRange1, class ForwardRange2 > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_return::type +>::type +find_first_of(SinglePassRange1& rng1, const ForwardRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return range_return:: + pack(std::find_first_of(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2)), + rng1); +} + +/// \overload +template< range_return_value re, class SinglePassRange1, class ForwardRange2 > +inline BOOST_DEDUCED_TYPENAME range_return::type +find_first_of(const SinglePassRange1& rng1, const ForwardRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return range_return:: + pack(std::find_first_of(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2)), + rng1); +} + +/// \overload +template< range_return_value re, class SinglePassRange1, class ForwardRange2, + class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_return::type +>::type +find_first_of(SinglePassRange1 & rng1, const ForwardRange2& rng2, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return range_return:: + pack(std::find_first_of(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), pred), + rng1); +} + +/// \overload +template< range_return_value re, class SinglePassRange1, class ForwardRange2, + class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +find_first_of(const SinglePassRange1 & rng1, const ForwardRange2& rng2, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + + return range_return:: + pack(std::find_first_of(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), pred), + rng1); +} + + } // namespace range + using range::find_first_of; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/find_if.hpp b/libs/range/include/boost/range/algorithm/find_if.hpp new file mode 100644 index 00000000..2d1926da --- /dev/null +++ b/libs/range/include/boost/range/algorithm/find_if.hpp @@ -0,0 +1,81 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_FIND_IF_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_FIND_IF_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function find_if +/// +/// range-based version of the find_if std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +/// \pre UnaryPredicate is a model of the UnaryPredicateConcept +template< class SinglePassRange, class UnaryPredicate > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_iterator::type +>::type +find_if( SinglePassRange& rng, UnaryPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::find_if(boost::begin(rng), boost::end(rng), pred); +} + +/// \overload +template< class SinglePassRange, class UnaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +find_if( const SinglePassRange& rng, UnaryPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::find_if(boost::begin(rng), boost::end(rng), pred); +} + +// range_return overloads + +/// \overload +template< range_return_value re, class SinglePassRange, class UnaryPredicate > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_return::type +>::type +find_if( SinglePassRange& rng, UnaryPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return range_return:: + pack(std::find_if(boost::begin(rng), boost::end(rng), pred), + rng); +} + +/// \overload +template< range_return_value re, class SinglePassRange, class UnaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +find_if( const SinglePassRange& rng, UnaryPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return range_return:: + pack(std::find_if(boost::begin(rng), boost::end(rng), pred), + rng); +} + + } // namespace range + using range::find_if; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/for_each.hpp b/libs/range/include/boost/range/algorithm/for_each.hpp new file mode 100644 index 00000000..ea731b2f --- /dev/null +++ b/libs/range/include/boost/range/algorithm/for_each.hpp @@ -0,0 +1,110 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_FOR_EACH_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_FOR_EACH_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, == 1600) +#include +#endif + +namespace boost +{ + namespace range + { + +#if BOOST_WORKAROUND(BOOST_MSVC, == 1600) + namespace for_each_detail + { + template + inline UnaryFunction + for_each_impl(Iterator first, Iterator last, UnaryFunction fun, + typename ::boost::enable_if< + is_reference_wrapper, + void + >::type* = 0) + { + typedef typename std::_Get_unchecked_type::type + unchecked_iterator; + + unchecked_iterator unchecked_last = std::_Unchecked(last); + for (unchecked_iterator unchecked_first = std::_Unchecked(first); first != last; ++first) + fun.get()(*unchecked_first); + + return fun; + } + + template + inline UnaryFunction + for_each_impl(Iterator first, Iterator last, UnaryFunction fn, + typename disable_if< + is_reference_wrapper, + void + >::type* = 0) + { + return std::for_each(first, last, fn); + } + } +#endif + +/// \brief template function for_each +/// +/// range-based version of the for_each std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +/// \pre UnaryFunction is a model of the UnaryFunctionConcept +template< class SinglePassRange, class UnaryFunction > +inline UnaryFunction for_each(SinglePassRange & rng, UnaryFunction fun) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + +#if BOOST_WORKAROUND(BOOST_MSVC, == 1600) + return for_each_detail::for_each_impl< + typename range_iterator::type, + UnaryFunction + >(boost::begin(rng), boost::end(rng), fun); +#else + return std::for_each< + BOOST_DEDUCED_TYPENAME range_iterator::type, + UnaryFunction + >(boost::begin(rng),boost::end(rng),fun); +#endif +} + +/// \overload +template< class SinglePassRange, class UnaryFunction > +inline UnaryFunction for_each(const SinglePassRange& rng, UnaryFunction fun) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + +#if BOOST_WORKAROUND(BOOST_MSVC, == 1600) + return for_each_detail::for_each_impl< + typename range_iterator::type, + UnaryFunction + >(boost::begin(rng), boost::end(rng), fun); +#else + return std::for_each< + BOOST_DEDUCED_TYPENAME range_iterator::type, + UnaryFunction + >(boost::begin(rng), boost::end(rng), fun); +#endif +} + + } // namespace range + using range::for_each; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/generate.hpp b/libs/range/include/boost/range/algorithm/generate.hpp new file mode 100644 index 00000000..324412c4 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/generate.hpp @@ -0,0 +1,49 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_GENERATE_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_GENERATE_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { +/// \brief template function generate +/// +/// range-based version of the generate std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +/// \pre Generator is a model of the UnaryFunctionConcept +template< class ForwardRange, class Generator > +inline ForwardRange& generate( ForwardRange& rng, Generator gen ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + std::generate(boost::begin(rng), boost::end(rng), gen); + return rng; +} + +/// \overload +template< class ForwardRange, class Generator > +inline const ForwardRange& generate( const ForwardRange& rng, Generator gen ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + std::generate(boost::begin(rng), boost::end(rng), gen); + return rng; +} + + } // namespace range + using range::generate; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/heap_algorithm.hpp b/libs/range/include/boost/range/algorithm/heap_algorithm.hpp new file mode 100644 index 00000000..584920d6 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/heap_algorithm.hpp @@ -0,0 +1,194 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_HEAP_ALGORITHM_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_HEAP_ALGORITHM_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function push_heap +/// +/// range-based version of the push_heap std algorithm +/// +/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept +/// \pre Compare is a model of the BinaryPredicateConcept +template +inline RandomAccessRange& push_heap(RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::push_heap(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& push_heap(const RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::push_heap(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline RandomAccessRange& push_heap(RandomAccessRange& rng, Compare comp_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::push_heap(boost::begin(rng), boost::end(rng), comp_pred); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& push_heap(const RandomAccessRange& rng, Compare comp_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::push_heap(boost::begin(rng), boost::end(rng), comp_pred); + return rng; +} + +/// \brief template function pop_heap +/// +/// range-based version of the pop_heap std algorithm +/// +/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept +/// \pre Compare is a model of the BinaryPredicateConcept +template +inline RandomAccessRange& pop_heap(RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::pop_heap(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& pop_heap(const RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::pop_heap(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline RandomAccessRange& pop_heap(RandomAccessRange& rng, Compare comp_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::pop_heap(boost::begin(rng), boost::end(rng), comp_pred); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& pop_heap(const RandomAccessRange& rng, Compare comp_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::pop_heap(boost::begin(rng), boost::end(rng), comp_pred); + return rng; +} + +/// \brief template function make_heap +/// +/// range-based version of the make_heap std algorithm +/// +/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept +/// \pre Compare is a model of the BinaryPredicateConcept +template +inline RandomAccessRange& make_heap(RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::make_heap(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& make_heap(const RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::make_heap(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline RandomAccessRange& make_heap(RandomAccessRange& rng, Compare comp_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::make_heap(boost::begin(rng), boost::end(rng), comp_pred); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& make_heap(const RandomAccessRange& rng, Compare comp_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::make_heap(boost::begin(rng), boost::end(rng), comp_pred); + return rng; +} + +/// \brief template function sort_heap +/// +/// range-based version of the sort_heap std algorithm +/// +/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept +/// \pre Compare is a model of the BinaryPredicateConcept +template +inline RandomAccessRange& sort_heap(RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::sort_heap(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& sort_heap(const RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::sort_heap(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline RandomAccessRange& sort_heap(RandomAccessRange& rng, Compare comp_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::sort_heap(boost::begin(rng), boost::end(rng), comp_pred); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& sort_heap(const RandomAccessRange& rng, Compare comp_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::sort_heap(boost::begin(rng), boost::end(rng), comp_pred); + return rng; +} + + } // namespace range + using range::push_heap; + using range::pop_heap; + using range::make_heap; + using range::sort_heap; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/inplace_merge.hpp b/libs/range/include/boost/range/algorithm/inplace_merge.hpp new file mode 100644 index 00000000..dfadbaa6 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/inplace_merge.hpp @@ -0,0 +1,74 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_INPLACE_MERGE_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_INPLACE_MERGE_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function inplace_merge +/// +/// range-based version of the inplace_merge std algorithm +/// +/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline BidirectionalRange& inplace_merge(BidirectionalRange& rng, + BOOST_DEDUCED_TYPENAME range_iterator::type middle) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + std::inplace_merge(boost::begin(rng), middle, boost::end(rng)); + return rng; +} + +/// \overload +template +inline const BidirectionalRange& inplace_merge(const BidirectionalRange& rng, + BOOST_DEDUCED_TYPENAME boost::range_iterator::type middle) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + std::inplace_merge(boost::begin(rng), middle, boost::end(rng)); + return rng; +} + +/// \overload +template +inline BidirectionalRange& inplace_merge(BidirectionalRange& rng, + BOOST_DEDUCED_TYPENAME boost::range_iterator::type middle, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + std::inplace_merge(boost::begin(rng), middle, boost::end(rng), pred); + return rng; +} + +/// \overload +template +inline const BidirectionalRange& inplace_merge(const BidirectionalRange& rng, + BOOST_DEDUCED_TYPENAME boost::range_iterator::type middle, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + std::inplace_merge(boost::begin(rng), middle, boost::end(rng), pred); + return rng; +} + + } // namespace range + using range::inplace_merge; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/lexicographical_compare.hpp b/libs/range/include/boost/range/algorithm/lexicographical_compare.hpp new file mode 100644 index 00000000..c6e4bc8e --- /dev/null +++ b/libs/range/include/boost/range/algorithm/lexicographical_compare.hpp @@ -0,0 +1,58 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_LEXICOGRAPHICAL_COMPARE_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_LEXICOGRAPHICAL_COMPARE_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function lexicographic_compare +/// +/// range-based version of the lexicographic_compare std algorithm +/// +/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept +/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept +template +inline bool lexicographical_compare(const SinglePassRange1& rng1, + const SinglePassRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::lexicographical_compare( + boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2)); +} + +/// \overload +template +inline bool lexicographical_compare(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::lexicographical_compare( + boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), pred); +} + + } // namespace range + using range::lexicographical_compare; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/lower_bound.hpp b/libs/range/include/boost/range/algorithm/lower_bound.hpp new file mode 100644 index 00000000..23dac6cc --- /dev/null +++ b/libs/range/include/boost/range/algorithm/lower_bound.hpp @@ -0,0 +1,124 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_LOWER_BOUND_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_LOWER_BOUND_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function lower_bound +/// +/// range-based version of the lower_bound std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +template< class ForwardRange, class Value > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_iterator::type +>::type +lower_bound( ForwardRange& rng, const Value& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::lower_bound(boost::begin(rng), boost::end(rng), val); +} + +/// \overload +template< class ForwardRange, class Value > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +lower_bound( const ForwardRange& rng, const Value& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::lower_bound(boost::begin(rng), boost::end(rng), val); +} + +/// \overload +template< class ForwardRange, class Value, class SortPredicate > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_iterator::type +>::type +lower_bound( ForwardRange& rng, const Value& val, SortPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::lower_bound(boost::begin(rng), boost::end(rng), val, pred); +} + +/// \overload +template< class ForwardRange, class Value, class SortPredicate > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +lower_bound( const ForwardRange& rng, const Value& val, SortPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::lower_bound(boost::begin(rng), boost::end(rng), val, pred); +} + +/// \overload +template< range_return_value re, class ForwardRange, class Value > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_return::type +>::type +lower_bound( ForwardRange& rng, const Value& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::lower_bound(boost::begin(rng), boost::end(rng), val), + rng); +} + +/// \overload +template< range_return_value re, class ForwardRange, class Value > +inline BOOST_DEDUCED_TYPENAME range_return::type +lower_bound( const ForwardRange& rng, const Value& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::lower_bound(boost::begin(rng), boost::end(rng), val), + rng); +} + +/// \overload +template< range_return_value re, class ForwardRange, class Value, class SortPredicate > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_return::type +>::type +lower_bound( ForwardRange& rng, const Value& val, SortPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::lower_bound(boost::begin(rng), boost::end(rng), val, pred), + rng); +} + +/// \overload +template< range_return_value re, class ForwardRange, class Value, class SortPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +lower_bound( const ForwardRange& rng, const Value& val, SortPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::lower_bound(boost::begin(rng), boost::end(rng), val, pred), + rng); +} + + } // namespace range + using range::lower_bound; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/max_element.hpp b/libs/range/include/boost/range/algorithm/max_element.hpp new file mode 100644 index 00000000..50669b37 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/max_element.hpp @@ -0,0 +1,137 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// Copyright 2019 Glen Joseph Fernandes (glenjofe@gmail.com) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_MAX_ELEMENT_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_MAX_ELEMENT_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +namespace detail +{ + +template +inline Iterator +max_element(Iterator first, Iterator last, Predicate comp) +{ + if (first == last) { + return last; + } + Iterator result = first; + while (++first != last) { + if (comp(*result, *first)) { + result = first; + } + } + return result; +} + +} // namespace detail + +/// \brief template function max_element +/// +/// range-based version of the max_element std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +max_element(ForwardRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return detail::max_element(boost::begin(rng), boost::end(rng), detail::less()); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +max_element(const ForwardRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return detail::max_element(boost::begin(rng), boost::end(rng), detail::less()); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +max_element(ForwardRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return detail::max_element(boost::begin(rng), boost::end(rng), pred); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +max_element(const ForwardRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return detail::max_element(boost::begin(rng), boost::end(rng), pred); +} + +// range_return overloads + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_return::type +max_element(ForwardRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return::pack( + detail::max_element(boost::begin(rng), boost::end(rng), detail::less()), + rng); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_return::type +max_element(const ForwardRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return::pack( + detail::max_element(boost::begin(rng), boost::end(rng), detail::less()), + rng); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_return::type +max_element(ForwardRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return::pack( + detail::max_element(boost::begin(rng), boost::end(rng), pred), + rng); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_return::type +max_element(const ForwardRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return::pack( + detail::max_element(boost::begin(rng), boost::end(rng), pred), + rng); +} + + } // namespace range + using range::max_element; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/merge.hpp b/libs/range/include/boost/range/algorithm/merge.hpp new file mode 100644 index 00000000..c81b8c78 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/merge.hpp @@ -0,0 +1,61 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_MERGE_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_MERGE_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function merge +/// +/// range-based version of the merge std algorithm +/// +/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept +/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +/// +template +inline OutputIterator merge(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::merge(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), out); +} + +/// \overload +template +inline OutputIterator merge(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::merge(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), out, pred); +} + + } // namespace range + using range::merge; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/min_element.hpp b/libs/range/include/boost/range/algorithm/min_element.hpp new file mode 100644 index 00000000..764de8b2 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/min_element.hpp @@ -0,0 +1,137 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// Copyright 2019 Glen Joseph Fernandes (glenjofe@gmail.com) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_MIN_ELEMENT_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_MIN_ELEMENT_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +namespace detail +{ + +template +inline Iterator +min_element(Iterator first, Iterator last, Predicate comp) +{ + if (first == last) { + return last; + } + Iterator result = first; + while (++first != last) { + if (comp(*first, *result)) { + result = first; + } + } + return result; +} + +} // namespace detail + +/// \brief template function min_element +/// +/// range-based version of the min_element std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +min_element(ForwardRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return detail::min_element(boost::begin(rng), boost::end(rng), detail::less()); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +min_element(const ForwardRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return detail::min_element(boost::begin(rng), boost::end(rng), detail::less()); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +min_element(ForwardRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return detail::min_element(boost::begin(rng), boost::end(rng), pred); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +min_element(const ForwardRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return detail::min_element(boost::begin(rng), boost::end(rng), pred); +} + +// range_return overloads + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_return::type +min_element(ForwardRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return::pack( + detail::min_element(boost::begin(rng), boost::end(rng), detail::less()), + rng); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_return::type +min_element(const ForwardRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return::pack( + detail::min_element(boost::begin(rng), boost::end(rng), detail::less()), + rng); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_return::type +min_element(ForwardRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return::pack( + detail::min_element(boost::begin(rng), boost::end(rng), pred), + rng); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_return::type +min_element(const ForwardRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return::pack( + detail::min_element(boost::begin(rng), boost::end(rng), pred), + rng); +} + + } // namespace range + using range::min_element; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/mismatch.hpp b/libs/range/include/boost/range/algorithm/mismatch.hpp new file mode 100644 index 00000000..2819c333 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/mismatch.hpp @@ -0,0 +1,195 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_MISMATCH_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_MISMATCH_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + template< class SinglePassTraversalReadableIterator1, + class SinglePassTraversalReadableIterator2 > + inline std::pair + mismatch_impl(SinglePassTraversalReadableIterator1 first1, + SinglePassTraversalReadableIterator1 last1, + SinglePassTraversalReadableIterator2 first2, + SinglePassTraversalReadableIterator2 last2) + { + while (first1 != last1 && first2 != last2 && *first1 == *first2) + { + ++first1; + ++first2; + } + return std::pair(first1, first2); + } + + template< class SinglePassTraversalReadableIterator1, + class SinglePassTraversalReadableIterator2, + class BinaryPredicate > + inline std::pair + mismatch_impl(SinglePassTraversalReadableIterator1 first1, + SinglePassTraversalReadableIterator1 last1, + SinglePassTraversalReadableIterator2 first2, + SinglePassTraversalReadableIterator2 last2, + BinaryPredicate pred) + { + while (first1 != last1 && first2 != last2 && pred(*first1, *first2)) + { + ++first1; + ++first2; + } + return std::pair(first1, first2); + } + } // namespace range_detail + + namespace range + { +/// \brief template function mismatch +/// +/// range-based version of the mismatch std algorithm +/// +/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept +/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template< class SinglePassRange1, class SinglePassRange2 > +inline std::pair< + BOOST_DEDUCED_TYPENAME range_iterator::type, + BOOST_DEDUCED_TYPENAME range_iterator::type > +mismatch(SinglePassRange1& rng1, const SinglePassRange2 & rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::mismatch_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2)); +} + +/// \overload +template< class SinglePassRange1, class SinglePassRange2 > +inline std::pair< + BOOST_DEDUCED_TYPENAME range_iterator::type, + BOOST_DEDUCED_TYPENAME range_iterator::type > +mismatch(const SinglePassRange1& rng1, const SinglePassRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::mismatch_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2)); +} + +/// \overload +template< class SinglePassRange1, class SinglePassRange2 > +inline std::pair< + BOOST_DEDUCED_TYPENAME range_iterator::type, + BOOST_DEDUCED_TYPENAME range_iterator::type > +mismatch(SinglePassRange1& rng1, SinglePassRange2 & rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::mismatch_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2)); +} + +/// \overload +template< class SinglePassRange1, class SinglePassRange2 > +inline std::pair< + BOOST_DEDUCED_TYPENAME range_iterator::type, + BOOST_DEDUCED_TYPENAME range_iterator::type > +mismatch(const SinglePassRange1& rng1, SinglePassRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::mismatch_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2)); +} + + +/// \overload +template< class SinglePassRange1, class SinglePassRange2, class BinaryPredicate > +inline std::pair< + BOOST_DEDUCED_TYPENAME range_iterator::type, + BOOST_DEDUCED_TYPENAME range_iterator::type > +mismatch(SinglePassRange1& rng1, const SinglePassRange2& rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::mismatch_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2), pred); +} + +/// \overload +template< class SinglePassRange1, class SinglePassRange2, class BinaryPredicate > +inline std::pair< + BOOST_DEDUCED_TYPENAME range_iterator::type, + BOOST_DEDUCED_TYPENAME range_iterator::type > +mismatch(const SinglePassRange1& rng1, const SinglePassRange2& rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::mismatch_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2), pred); +} + +/// \overload +template< class SinglePassRange1, class SinglePassRange2, class BinaryPredicate > +inline std::pair< + BOOST_DEDUCED_TYPENAME range_iterator::type, + BOOST_DEDUCED_TYPENAME range_iterator::type > +mismatch(SinglePassRange1& rng1, SinglePassRange2& rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::mismatch_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2), pred); +} + +/// \overload +template< class SinglePassRange1, class SinglePassRange2, class BinaryPredicate > +inline std::pair< + BOOST_DEDUCED_TYPENAME range_iterator::type, + BOOST_DEDUCED_TYPENAME range_iterator::type > +mismatch(const SinglePassRange1& rng1, SinglePassRange2& rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::mismatch_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2), pred); +} + + } // namespace range + using range::mismatch; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/nth_element.hpp b/libs/range/include/boost/range/algorithm/nth_element.hpp new file mode 100644 index 00000000..a605595c --- /dev/null +++ b/libs/range/include/boost/range/algorithm/nth_element.hpp @@ -0,0 +1,74 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_NTH_ELEMENT_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_NTH_ELEMENT_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function nth_element +/// +/// range-based version of the nth_element std algorithm +/// +/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline RandomAccessRange& nth_element(RandomAccessRange& rng, + BOOST_DEDUCED_TYPENAME range_iterator::type nth) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::nth_element(boost::begin(rng), nth, boost::end(rng)); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& nth_element(const RandomAccessRange& rng, + BOOST_DEDUCED_TYPENAME range_iterator::type nth) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::nth_element(boost::begin(rng), nth, boost::end(rng)); + return rng; +} + +/// \overload +template +inline RandomAccessRange& nth_element(RandomAccessRange& rng, + BOOST_DEDUCED_TYPENAME range_iterator::type nth, + BinaryPredicate sort_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::nth_element(boost::begin(rng), nth, boost::end(rng), sort_pred); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& nth_element(const RandomAccessRange& rng, + BOOST_DEDUCED_TYPENAME range_iterator::type nth, + BinaryPredicate sort_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::nth_element(boost::begin(rng), nth, boost::end(rng), sort_pred); + return rng; +} + + } // namespace range + using range::nth_element; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/partial_sort.hpp b/libs/range/include/boost/range/algorithm/partial_sort.hpp new file mode 100644 index 00000000..d7044cd6 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/partial_sort.hpp @@ -0,0 +1,76 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_PARTIAL_SORT_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_PARTIAL_SORT_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function partial_sort +/// +/// range-based version of the partial_sort std algorithm +/// +/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline RandomAccessRange& partial_sort(RandomAccessRange& rng, + BOOST_DEDUCED_TYPENAME range_iterator::type middle) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::partial_sort(boost::begin(rng), middle, boost::end(rng)); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& partial_sort(const RandomAccessRange& rng, + BOOST_DEDUCED_TYPENAME range_iterator::type middle) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::partial_sort(boost::begin(rng), middle, boost::end(rng)); + return rng; +} + +/// \overload +template +inline RandomAccessRange& partial_sort(RandomAccessRange& rng, + BOOST_DEDUCED_TYPENAME range_iterator::type middle, + BinaryPredicate sort_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::partial_sort(boost::begin(rng), middle, boost::end(rng), + sort_pred); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& partial_sort(const RandomAccessRange& rng, + BOOST_DEDUCED_TYPENAME range_iterator::type middle, + BinaryPredicate sort_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::partial_sort(boost::begin(rng), middle, boost::end(rng), + sort_pred); + return rng; +} + + } // namespace range + using range::partial_sort; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/partial_sort_copy.hpp b/libs/range/include/boost/range/algorithm/partial_sort_copy.hpp new file mode 100644 index 00000000..91293890 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/partial_sort_copy.hpp @@ -0,0 +1,82 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_PARTIAL_SORT_COPY_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_PARTIAL_SORT_COPY_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function partial_sort_copy +/// +/// range-based version of the partial_sort_copy std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +/// \pre RandomAccessRange is a model of the Mutable_RandomAccessRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +partial_sort_copy(const SinglePassRange& rng1, RandomAccessRange& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + + return std::partial_sort_copy(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2)); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +partial_sort_copy(const SinglePassRange& rng1, const RandomAccessRange& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + + return std::partial_sort_copy(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2)); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +partial_sort_copy(const SinglePassRange& rng1, RandomAccessRange& rng2, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + + return std::partial_sort_copy(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), pred); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +partial_sort_copy(const SinglePassRange& rng1, const RandomAccessRange& rng2, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + + return std::partial_sort_copy(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), pred); +} + + } // namespace range + using range::partial_sort_copy; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/partition.hpp b/libs/range/include/boost/range/algorithm/partition.hpp new file mode 100644 index 00000000..b814a248 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/partition.hpp @@ -0,0 +1,74 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_PARTITION__HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_PARTITION__HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function partition +/// +/// range-based version of the partition std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +partition(ForwardRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::partition(boost::begin(rng),boost::end(rng),pred); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +partition(const ForwardRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::partition(boost::begin(rng),boost::end(rng),pred); +} + +// range_return overloads + +/// \overload +template< range_return_value re, class ForwardRange, + class UnaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +partition(ForwardRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return boost::range_return:: + pack(std::partition(boost::begin(rng), boost::end(rng), pred), rng); +} + +/// \overload +template< range_return_value re, class ForwardRange, + class UnaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +partition(const ForwardRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return boost::range_return:: + pack(std::partition(boost::begin(rng), boost::end(rng), pred), rng); +} + + } // namespace range + using range::partition; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/permutation.hpp b/libs/range/include/boost/range/algorithm/permutation.hpp new file mode 100644 index 00000000..75388cc8 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/permutation.hpp @@ -0,0 +1,108 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_PERMUTATION_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_PERMUTATION_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function next_permutation +/// +/// range-based version of the next_permutation std algorithm +/// +/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept +/// \pre Compare is a model of the BinaryPredicateConcept +template +inline bool next_permutation(BidirectionalRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return std::next_permutation(boost::begin(rng), boost::end(rng)); +} + +/// \overload +template +inline bool next_permutation(const BidirectionalRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return std::next_permutation(boost::begin(rng), boost::end(rng)); +} + +/// \overload +template +inline bool next_permutation(BidirectionalRange& rng, Compare comp_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return std::next_permutation(boost::begin(rng), boost::end(rng), + comp_pred); +} + +/// \overload +template +inline bool next_permutation(const BidirectionalRange& rng, + Compare comp_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return std::next_permutation(boost::begin(rng), boost::end(rng), + comp_pred); +} + +/// \brief template function prev_permutation +/// +/// range-based version of the prev_permutation std algorithm +/// +/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept +/// \pre Compare is a model of the BinaryPredicateConcept +template +inline bool prev_permutation(BidirectionalRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return std::prev_permutation(boost::begin(rng), boost::end(rng)); +} + +/// \overload +template +inline bool prev_permutation(const BidirectionalRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return std::prev_permutation(boost::begin(rng), boost::end(rng)); +} + +/// \overload +template +inline bool prev_permutation(BidirectionalRange& rng, Compare comp_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return std::prev_permutation(boost::begin(rng), boost::end(rng), + comp_pred); +} + +/// \overload +template +inline bool prev_permutation(const BidirectionalRange& rng, + Compare comp_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return std::prev_permutation(boost::begin(rng), boost::end(rng), + comp_pred); +} + + } // namespace range + using range::next_permutation; + using range::prev_permutation; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/random_shuffle.hpp b/libs/range/include/boost/range/algorithm/random_shuffle.hpp new file mode 100644 index 00000000..33e98e04 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/random_shuffle.hpp @@ -0,0 +1,141 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_RANDOM_SHUFFLE_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_RANDOM_SHUFFLE_HPP_INCLUDED + +#include +#include +#include +#include +#include +#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE +#include +#endif + +namespace boost +{ + namespace range + { + + namespace detail + { +#ifdef BOOST_NO_CXX98_RANDOM_SHUFFLE + +// wrap std::rand as UniformRandomBitGenerator +struct wrap_rand +{ + typedef unsigned int result_type; + + static BOOST_CONSTEXPR result_type (min)() + { + return 0; + } + + static BOOST_CONSTEXPR result_type (max)() + { + return RAND_MAX; + } + + result_type operator()() + { + return std::rand(); + } +}; + +template< class RandomIt > +inline void random_shuffle(RandomIt first, RandomIt last) +{ + std::shuffle(first, last, wrap_rand()); +} + +// wrap Generator as UniformRandomBitGenerator +template< class Generator > +struct wrap_generator +{ + typedef unsigned int result_type; + static const int max_arg = ((0u - 1u) >> 2) + 1; + Generator& g; + + wrap_generator(Generator& gen) : g(gen) {} + + static BOOST_CONSTEXPR result_type (min)() + { + return 0; + } + + static BOOST_CONSTEXPR result_type (max)() + { + return max_arg - 1; + } + + result_type operator()() + { + return static_cast(g(max_arg)); + } +}; + +template< class RandomIt, class Generator > +inline void random_shuffle(RandomIt first, RandomIt last, Generator& gen) +{ + std::shuffle(first, last, wrap_generator< Generator >(gen)); +} + +#else + +using std::random_shuffle; + +#endif + } // namespace detail + +/// \brief template function random_shuffle +/// +/// range-based version of the random_shuffle std algorithm +/// +/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept +/// \pre Generator is a model of the UnaryFunctionConcept +template +inline RandomAccessRange& random_shuffle(RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + detail::random_shuffle(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& random_shuffle(const RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + detail::random_shuffle(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline RandomAccessRange& random_shuffle(RandomAccessRange& rng, Generator& gen) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + detail::random_shuffle(boost::begin(rng), boost::end(rng), gen); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& random_shuffle(const RandomAccessRange& rng, Generator& gen) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + detail::random_shuffle(boost::begin(rng), boost::end(rng), gen); + return rng; +} + + } // namespace range + using range::random_shuffle; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/remove.hpp b/libs/range/include/boost/range/algorithm/remove.hpp new file mode 100644 index 00000000..699a7cdb --- /dev/null +++ b/libs/range/include/boost/range/algorithm/remove.hpp @@ -0,0 +1,74 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_REMOVE_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_REMOVE_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function remove +/// +/// range-based version of the remove std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +template< class ForwardRange, class Value > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +remove(ForwardRange& rng, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::remove(boost::begin(rng),boost::end(rng),val); +} + +/// \overload +template< class ForwardRange, class Value > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +remove(const ForwardRange& rng, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::remove(boost::begin(rng),boost::end(rng),val); +} + +// range_return overloads + +/// \overload +template< range_return_value re, class ForwardRange, class Value > +inline BOOST_DEDUCED_TYPENAME range_return::type +remove(ForwardRange& rng, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return::pack( + std::remove(boost::begin(rng), boost::end(rng), val), + rng); +} + +/// \overload +template< range_return_value re, class ForwardRange, class Value > +inline BOOST_DEDUCED_TYPENAME range_return::type +remove(const ForwardRange& rng, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return::pack( + std::remove(boost::begin(rng), boost::end(rng), val), + rng); +} + + } // namespace range + using range::remove; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/remove_copy.hpp b/libs/range/include/boost/range/algorithm/remove_copy.hpp new file mode 100644 index 00000000..b65747ed --- /dev/null +++ b/libs/range/include/boost/range/algorithm/remove_copy.hpp @@ -0,0 +1,44 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_REMOVE_COPY_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_REMOVE_COPY_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function remove_copy +/// +/// range-based version of the remove_copy std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +/// \pre OutputIterator is a model of the OutputIteratorConcept +/// \pre Value is a model of the EqualityComparableConcept +/// \pre Objects of type Value can be compared for equality with objects of +/// InputIterator's value type. +template< class SinglePassRange, class OutputIterator, class Value > +inline OutputIterator +remove_copy(const SinglePassRange& rng, OutputIterator out_it, const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::remove_copy(boost::begin(rng), boost::end(rng), out_it, val); +} + + } // namespace range + using range::remove_copy; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/remove_copy_if.hpp b/libs/range/include/boost/range/algorithm/remove_copy_if.hpp new file mode 100644 index 00000000..8d9c37be --- /dev/null +++ b/libs/range/include/boost/range/algorithm/remove_copy_if.hpp @@ -0,0 +1,38 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_REMOVE_COPY_IF_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_REMOVE_COPY_IF_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + /// \brief template function remove_copy_if + /// + /// range-based version of the remove_copy_if std algorithm + /// + /// \pre SinglePassRange is a model of the SinglePassRangeConcept + /// \pre OutputIterator is a model of the OutputIteratorConcept + /// \pre Predicate is a model of the PredicateConcept + /// \pre InputIterator's value type is convertible to Predicate's argument type + /// \pre out_it is not an iterator in the range rng + template< class SinglePassRange, class OutputIterator, class Predicate > + inline OutputIterator + remove_copy_if(const SinglePassRange& rng, OutputIterator out_it, Predicate pred) + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::remove_copy_if(boost::begin(rng), boost::end(rng), out_it, pred); + } +} + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/remove_if.hpp b/libs/range/include/boost/range/algorithm/remove_if.hpp new file mode 100644 index 00000000..a965df0d --- /dev/null +++ b/libs/range/include/boost/range/algorithm/remove_if.hpp @@ -0,0 +1,75 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_REMOVE_IF_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_REMOVE_IF_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function remove_if +/// +/// range-based version of the remove_if std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +/// \pre UnaryPredicate is a model of the UnaryPredicateConcept +template< class ForwardRange, class UnaryPredicate > +inline BOOST_DEDUCED_TYPENAME boost::range_iterator::type +remove_if(ForwardRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::remove_if(boost::begin(rng), boost::end(rng), pred); +} + +/// \overload +template< class ForwardRange, class UnaryPredicate > +inline BOOST_DEDUCED_TYPENAME boost::range_iterator::type +remove_if(const ForwardRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::remove_if(boost::begin(rng), boost::end(rng), pred); +} + +// range_return overloads + +/// \overload +template< range_return_value re, class ForwardRange, class UnaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +remove_if(ForwardRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return::pack( + std::remove_if(boost::begin(rng), boost::end(rng), pred), + rng); +} + +/// \overload +template< range_return_value re, class ForwardRange, class UnaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +remove_if(const ForwardRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return::pack( + std::remove_if(boost::begin(rng), boost::end(rng), pred), + rng); +} + + } // namespace range + using range::remove_if; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/replace.hpp b/libs/range/include/boost/range/algorithm/replace.hpp new file mode 100644 index 00000000..44d3e4ca --- /dev/null +++ b/libs/range/include/boost/range/algorithm/replace.hpp @@ -0,0 +1,53 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_REPLACE_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_REPLACE_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function replace +/// +/// range-based version of the replace std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +template< class ForwardRange, class Value > +inline ForwardRange& +replace(ForwardRange& rng, const Value& what, + const Value& with_what) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + std::replace(boost::begin(rng), boost::end(rng), what, with_what); + return rng; +} + +/// \overload +template< class ForwardRange, class Value > +inline const ForwardRange& +replace(const ForwardRange& rng, const Value& what, + const Value& with_what) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + std::replace(boost::begin(rng), boost::end(rng), what, with_what); + return rng; +} + + } // namespace range + using range::replace; +} // namespace boost; + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/replace_copy.hpp b/libs/range/include/boost/range/algorithm/replace_copy.hpp new file mode 100644 index 00000000..0c02005a --- /dev/null +++ b/libs/range/include/boost/range/algorithm/replace_copy.hpp @@ -0,0 +1,42 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_REPLACE_COPY_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_REPLACE_COPY_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function replace_copy +/// +/// range-based version of the replace_copy std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +template< class ForwardRange, class OutputIterator, class Value > +inline OutputIterator +replace_copy(const ForwardRange& rng, OutputIterator out_it, const Value& what, + const Value& with_what) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::replace_copy(boost::begin(rng), boost::end(rng), out_it, + what, with_what); +} + + } // namespace range + using range::replace_copy; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/replace_copy_if.hpp b/libs/range/include/boost/range/algorithm/replace_copy_if.hpp new file mode 100644 index 00000000..d3131512 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/replace_copy_if.hpp @@ -0,0 +1,46 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_REPLACE_COPY_IF_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_REPLACE_COPY_IF_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function replace_copy_if +/// +/// range-based version of the replace_copy_if std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +/// \pre Predicate is a model of the PredicateConcept +/// \pre Value is convertible to Predicate's argument type +/// \pre Value is Assignable +/// \pre Value is convertible to a type in OutputIterator's set of value types. +template< class ForwardRange, class OutputIterator, class Predicate, class Value > +inline OutputIterator +replace_copy_if(const ForwardRange& rng, OutputIterator out_it, Predicate pred, + const Value& with_what) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::replace_copy_if(boost::begin(rng), boost::end(rng), out_it, + pred, with_what); +} + + } // namespace range + using range::replace_copy_if; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/replace_if.hpp b/libs/range/include/boost/range/algorithm/replace_if.hpp new file mode 100644 index 00000000..93d5a1f7 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/replace_if.hpp @@ -0,0 +1,54 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_REPLACE_IF_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_REPLACE_IF_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function replace_if +/// +/// range-based version of the replace_if std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +/// \pre UnaryPredicate is a model of the UnaryPredicateConcept +template< class ForwardRange, class UnaryPredicate, class Value > +inline ForwardRange& + replace_if(ForwardRange& rng, UnaryPredicate pred, + const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + std::replace_if(boost::begin(rng), boost::end(rng), pred, val); + return rng; +} + +/// \overload +template< class ForwardRange, class UnaryPredicate, class Value > +inline const ForwardRange& + replace_if(const ForwardRange& rng, UnaryPredicate pred, + const Value& val) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + std::replace_if(boost::begin(rng), boost::end(rng), pred, val); + return rng; +} + + } // namespace range + using range::replace_if; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/reverse.hpp b/libs/range/include/boost/range/algorithm/reverse.hpp new file mode 100644 index 00000000..20a7eb18 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/reverse.hpp @@ -0,0 +1,50 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_REVERSE_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_REVERSE_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function reverse +/// +/// range-based version of the reverse std algorithm +/// +/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept +template +inline BidirectionalRange& reverse(BidirectionalRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + std::reverse(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline const BidirectionalRange& reverse(const BidirectionalRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + std::reverse(boost::begin(rng), boost::end(rng)); + return rng; +} + + } // namespace range + using range::reverse; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/reverse_copy.hpp b/libs/range/include/boost/range/algorithm/reverse_copy.hpp new file mode 100644 index 00000000..f1990ada --- /dev/null +++ b/libs/range/include/boost/range/algorithm/reverse_copy.hpp @@ -0,0 +1,40 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_REVERSE_COPY_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_REVERSE_COPY_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function reverse_copy +/// +/// range-based version of the reverse_copy std algorithm +/// +/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept +template +inline OutputIterator reverse_copy(const BidirectionalRange& rng, OutputIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return std::reverse_copy(boost::begin(rng), boost::end(rng), out); +} + + } // namespace range + using range::reverse_copy; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/rotate.hpp b/libs/range/include/boost/range/algorithm/rotate.hpp new file mode 100644 index 00000000..ca4b2239 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/rotate.hpp @@ -0,0 +1,51 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_ROTATE_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_ROTATE_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function rotate +/// +/// range-based version of the rotate std algorithm +/// +/// \pre Rng meets the requirements for a Forward range +template +inline ForwardRange& rotate(ForwardRange& rng, + BOOST_DEDUCED_TYPENAME range_iterator::type middle) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + std::rotate(boost::begin(rng), middle, boost::end(rng)); + return rng; +} + +/// \overload +template +inline const ForwardRange& rotate(const ForwardRange& rng, + BOOST_DEDUCED_TYPENAME range_iterator::type middle) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + std::rotate(boost::begin(rng), middle, boost::end(rng)); + return rng; +} + + } // namespace range + using range::rotate; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/rotate_copy.hpp b/libs/range/include/boost/range/algorithm/rotate_copy.hpp new file mode 100644 index 00000000..0409ac52 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/rotate_copy.hpp @@ -0,0 +1,44 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_ROTATE_COPY_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_ROTATE_COPY_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + + /// \brief template function rotate + /// + /// range-based version of the rotate std algorithm + /// + /// \pre Rng meets the requirements for a Forward range + template + inline OutputIterator rotate_copy( + const ForwardRange& rng, + BOOST_DEDUCED_TYPENAME range_iterator::type middle, + OutputIterator target + ) + { + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::rotate_copy(boost::begin(rng), middle, boost::end(rng), target); + } + + } // namespace range + using range::rotate_copy; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/search.hpp b/libs/range/include/boost/range/algorithm/search.hpp new file mode 100644 index 00000000..28cc6e62 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/search.hpp @@ -0,0 +1,134 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_SEARCH_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_SEARCH_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function search +/// +/// range-based version of the search std algorithm +/// +/// \pre ForwardRange1 is a model of the ForwardRangeConcept +/// \pre ForwardRange2 is a model of the ForwardRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template< class ForwardRange1, class ForwardRange2 > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +search(ForwardRange1& rng1, const ForwardRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::search(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2)); +} + +/// \overload +template< class ForwardRange1, class ForwardRange2 > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +search(const ForwardRange1& rng1, const ForwardRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::search(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2)); +} + +/// \overload +template< class ForwardRange1, class ForwardRange2, class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +search(ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::search(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2),pred); +} + +/// \overload +template< class ForwardRange1, class ForwardRange2, class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +search(const ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::search(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), pred); +} + +// range_return overloads + +/// \overload +template< range_return_value re, class ForwardRange1, class ForwardRange2 > +inline BOOST_DEDUCED_TYPENAME range_return::type +search(ForwardRange1& rng1, const ForwardRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::search(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2)), + rng1); +} + +/// \overload +template< range_return_value re, class ForwardRange1, class ForwardRange2 > +inline BOOST_DEDUCED_TYPENAME range_return::type +search(const ForwardRange1& rng1, const ForwardRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::search(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2)), + rng1); +} + +/// \overload +template< range_return_value re, class ForwardRange1, class ForwardRange2, + class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +search(ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::search(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2),pred), + rng1); +} + +/// \overload +template< range_return_value re, class ForwardRange1, class ForwardRange2, + class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +search(const ForwardRange1& rng1, const ForwardRange2& rng2, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::search(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2),pred), + rng1); +} + + } // namespace range + using range::search; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/search_n.hpp b/libs/range/include/boost/range/algorithm/search_n.hpp new file mode 100644 index 00000000..ccfb27ae --- /dev/null +++ b/libs/range/include/boost/range/algorithm/search_n.hpp @@ -0,0 +1,360 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_SEARCH_N_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_SEARCH_N_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + +namespace range_detail +{ + // Rationale: search_n is implemented rather than delegate to + // the standard library implementation because some standard + // library implementations are broken eg. MSVC. + + // search_n forward iterator version + template + inline ForwardIterator + search_n_impl(ForwardIterator first, ForwardIterator last, Integer count, + const Value& value, std::forward_iterator_tag) + { + first = std::find(first, last, value); + while (first != last) + { + typename std::iterator_traits::difference_type n = count; + ForwardIterator i = first; + ++i; + while (i != last && n != 1 && *i==value) + { + ++i; + --n; + } + if (n == 1) + return first; + if (i == last) + return last; + first = std::find(++i, last, value); + } + return last; + } + + // search_n random-access iterator version + template + inline RandomAccessIterator + search_n_impl(RandomAccessIterator first, RandomAccessIterator last, + Integer count, const Value& value, + std::random_access_iterator_tag) + { + typedef typename std::iterator_traits::difference_type difference_t; + + difference_t tail_size = last - first; + const difference_t pattern_size = count; + + if (tail_size < pattern_size) + return last; + + const difference_t skip_offset = pattern_size - 1; + RandomAccessIterator look_ahead = first + skip_offset; + tail_size -= pattern_size; + + while (1) + { + // look_ahead here is pointing to the last element of the + // next possible match + while (!(*look_ahead == value)) // skip loop... + { + if (tail_size < pattern_size) + return last; // no match + look_ahead += pattern_size; + tail_size -= pattern_size; + } + difference_t remainder = skip_offset; + for (RandomAccessIterator back_track = look_ahead - 1; + *back_track == value; --back_track) + { + if (--remainder == 0) + { + return look_ahead - skip_offset; // matched + } + } + if (remainder > tail_size) + return last; // no match + look_ahead += remainder; + tail_size -= remainder; + } + + return last; + } + + // search_n for forward iterators using a binary predicate + // to determine a match + template + inline ForwardIterator + search_n_pred_impl(ForwardIterator first, ForwardIterator last, + Integer count, const Value& value, + BinaryPredicate pred, std::forward_iterator_tag) + { + typedef typename std::iterator_traits::difference_type difference_t; + + while (first != last && !static_cast(pred(*first, value))) + ++first; + + while (first != last) + { + difference_t n = count; + ForwardIterator i = first; + ++i; + while (i != last && n != 1 && static_cast(pred(*i, value))) + { + ++i; + --n; + } + if (n == 1) + return first; + if (i == last) + return last; + first = ++i; + while (first != last && !static_cast(pred(*first, value))) + ++first; + } + return last; + } + + // search_n for random-access iterators using a binary predicate + // to determine a match + template + inline RandomAccessIterator + search_n_pred_impl(RandomAccessIterator first, RandomAccessIterator last, + Integer count, const Value& value, + BinaryPredicate pred, std::random_access_iterator_tag) + { + typedef typename std::iterator_traits::difference_type difference_t; + + difference_t tail_size = last - first; + const difference_t pattern_size = count; + + if (tail_size < pattern_size) + return last; + + const difference_t skip_offset = pattern_size - 1; + RandomAccessIterator look_ahead = first + skip_offset; + tail_size -= pattern_size; + + while (1) + { + // look_ahead points to the last element of the next + // possible match + while (!static_cast(pred(*look_ahead, value))) // skip loop + { + if (tail_size < pattern_size) + return last; // no match + look_ahead += pattern_size; + tail_size -= pattern_size; + } + difference_t remainder = skip_offset; + for (RandomAccessIterator back_track = look_ahead - 1; + pred(*back_track, value); --back_track) + { + if (--remainder == 0) + return look_ahead -= skip_offset; // success + } + if (remainder > tail_size) + { + return last; // no match + } + look_ahead += remainder; + tail_size -= remainder; + } + } + + template + inline ForwardIterator + search_n_impl(ForwardIterator first, ForwardIterator last, + Integer count, const Value& value) + { + BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept)); + BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept)); + BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept::value_type>)); + //BOOST_RANGE_CONCEPT_ASSERT((EqualityComparableConcept2::value_type, Value>)); + + typedef typename std::iterator_traits::iterator_category cat_t; + + if (count <= 0) + return first; + if (count == 1) + return std::find(first, last, value); + return range_detail::search_n_impl(first, last, count, value, cat_t()); + } + + template + inline ForwardIterator + search_n_pred_impl(ForwardIterator first, ForwardIterator last, + Integer count, const Value& value, + BinaryPredicate pred) + { + BOOST_RANGE_CONCEPT_ASSERT((ForwardIteratorConcept)); + BOOST_RANGE_CONCEPT_ASSERT(( + BinaryPredicateConcept< + BinaryPredicate, + typename std::iterator_traits::value_type, + Value> + )); + + typedef typename std::iterator_traits::iterator_category cat_t; + + if (count <= 0) + return first; + if (count == 1) + { + while (first != last && !static_cast(pred(*first, value))) + ++first; + return first; + } + return range_detail::search_n_pred_impl(first, last, count, + value, pred, cat_t()); + } +} // namespace range_detail + +namespace range { + +/// \brief template function search +/// +/// range-based version of the search std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +/// \pre Integer is an integral type +/// \pre Value is a model of the EqualityComparableConcept +/// \pre ForwardRange's value type is a model of the EqualityComparableConcept +/// \pre Object's of ForwardRange's value type can be compared for equality with Objects of type Value +template< class ForwardRange, class Integer, class Value > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +search_n(ForwardRange& rng, Integer count, const Value& value) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return range_detail::search_n_impl(boost::begin(rng),boost::end(rng), count, value); +} + +/// \overload +template< class ForwardRange, class Integer, class Value > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +search_n(const ForwardRange& rng, Integer count, const Value& value) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return range_detail::search_n_impl(boost::begin(rng), boost::end(rng), count, value); +} + +/// \overload +template< class ForwardRange, class Integer, class Value, + class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +search_n(ForwardRange& rng, Integer count, const Value& value, + BinaryPredicate binary_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, const Value&>)); + return range_detail::search_n_pred_impl(boost::begin(rng), boost::end(rng), + count, value, binary_pred); +} + +/// \overload +template< class ForwardRange, class Integer, class Value, + class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +search_n(const ForwardRange& rng, Integer count, const Value& value, + BinaryPredicate binary_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, const Value&>)); + return range_detail::search_n_pred_impl(boost::begin(rng), boost::end(rng), + count, value, binary_pred); +} + +// range_return overloads + +/// \overload +template< range_return_value re, class ForwardRange, class Integer, + class Value > +inline BOOST_DEDUCED_TYPENAME range_return::type +search_n(ForwardRange& rng, Integer count, const Value& value) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return range_return:: + pack(range_detail::search_n_impl(boost::begin(rng),boost::end(rng), + count, value), + rng); +} + +/// \overload +template< range_return_value re, class ForwardRange, class Integer, + class Value > +inline BOOST_DEDUCED_TYPENAME range_return::type +search_n(const ForwardRange& rng, Integer count, const Value& value) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + return range_return:: + pack(range_detail::search_n_impl(boost::begin(rng), boost::end(rng), + count, value), + rng); +} + +/// \overload +template< range_return_value re, class ForwardRange, class Integer, + class Value, class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +search_n(ForwardRange& rng, Integer count, const Value& value, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, + const Value&>)); + return range_return:: + pack(range_detail::search_n_pred_impl(boost::begin(rng), + boost::end(rng), + count, value, pred), + rng); +} + +/// \overload +template< range_return_value re, class ForwardRange, class Integer, + class Value, class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +search_n(const ForwardRange& rng, Integer count, const Value& value, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT((ForwardRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, + const Value&>)); + return range_return:: + pack(range_detail::search_n_pred_impl(boost::begin(rng), + boost::end(rng), + count, value, pred), + rng); +} + + } // namespace range + using range::search_n; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/set_algorithm.hpp b/libs/range/include/boost/range/algorithm/set_algorithm.hpp new file mode 100644 index 00000000..82ef8ecc --- /dev/null +++ b/libs/range/include/boost/range/algorithm/set_algorithm.hpp @@ -0,0 +1,198 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_SET_ALGORITHM_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_SET_ALGORITHM_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function includes +/// +/// range-based version of the includes std algorithm +/// +/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept +/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline bool includes(const SinglePassRange1& rng1, + const SinglePassRange2& rng2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::includes(boost::begin(rng1),boost::end(rng1), + boost::begin(rng2),boost::end(rng2)); +} + +/// \overload +template +inline bool includes(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::includes(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), pred); +} + +/// \brief template function set_union +/// +/// range-based version of the set_union std algorithm +/// +/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept +/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline OutputIterator set_union(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::set_union(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), out); +} + +/// \overload +template +inline OutputIterator set_union(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::set_union(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), out, pred); +} + +/// \brief template function set_intersection +/// +/// range-based version of the set_intersection std algorithm +/// +/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept +/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline OutputIterator set_intersection(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::set_intersection(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), out); +} + +/// \overload +template +inline OutputIterator set_intersection(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::set_intersection(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), + out, pred); +} + +/// \brief template function set_difference +/// +/// range-based version of the set_difference std algorithm +/// +/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept +/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline OutputIterator set_difference(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::set_difference(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), out); +} + +/// \overload +template +inline OutputIterator set_difference(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::set_difference( + boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), out, pred); +} + +/// \brief template function set_symmetric_difference +/// +/// range-based version of the set_symmetric_difference std algorithm +/// +/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept +/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline OutputIterator +set_symmetric_difference(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::set_symmetric_difference(boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), out); +} + +/// \overload +template +inline OutputIterator +set_symmetric_difference(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out, + BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::set_symmetric_difference( + boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), out, pred); +} + + } // namespace range + using range::includes; + using range::set_union; + using range::set_intersection; + using range::set_difference; + using range::set_symmetric_difference; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/sort.hpp b/libs/range/include/boost/range/algorithm/sort.hpp new file mode 100644 index 00000000..45eecde7 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/sort.hpp @@ -0,0 +1,68 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_SORT_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_SORT_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function sort +/// +/// range-based version of the sort std algorithm +/// +/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline RandomAccessRange& sort(RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::sort(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& sort(const RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::sort(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline RandomAccessRange& sort(RandomAccessRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::sort(boost::begin(rng), boost::end(rng), pred); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& sort(const RandomAccessRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::sort(boost::begin(rng), boost::end(rng), pred); + return rng; +} + + } // namespace range + using range::sort; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/stable_partition.hpp b/libs/range/include/boost/range/algorithm/stable_partition.hpp new file mode 100644 index 00000000..24febfc8 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/stable_partition.hpp @@ -0,0 +1,73 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_STABLE_PARTITION_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_STABLE_PARTITION_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function stable_partition +/// +/// range-based version of the stable_partition std algorithm +/// +/// \pre BidirectionalRange is a model of the BidirectionalRangeConcept +/// \pre UnaryPredicate is a model of the UnaryPredicateConcept +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +stable_partition(BidirectionalRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return std::stable_partition(boost::begin(rng), boost::end(rng), pred); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_iterator::type +stable_partition(const BidirectionalRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return std::stable_partition(boost::begin(rng),boost::end(rng),pred); +} + +// range_return overloads +template +inline BOOST_DEDUCED_TYPENAME range_return::type +stable_partition(BidirectionalRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return range_return::pack( + std::stable_partition(boost::begin(rng), boost::end(rng), pred), + rng); +} + +/// \overload +template +inline BOOST_DEDUCED_TYPENAME range_return::type +stable_partition(const BidirectionalRange& rng, UnaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalRangeConcept )); + return range_return::pack( + std::stable_partition(boost::begin(rng),boost::end(rng),pred), + rng); +} + + } // namespace range + using range::stable_partition; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/stable_sort.hpp b/libs/range/include/boost/range/algorithm/stable_sort.hpp new file mode 100644 index 00000000..d18da4de --- /dev/null +++ b/libs/range/include/boost/range/algorithm/stable_sort.hpp @@ -0,0 +1,68 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_STABLE_SORT_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_STABLE_SORT_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function stable_sort +/// +/// range-based version of the stable_sort std algorithm +/// +/// \pre RandomAccessRange is a model of the RandomAccessRangeConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template +inline RandomAccessRange& stable_sort(RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::stable_sort(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& stable_sort(const RandomAccessRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::stable_sort(boost::begin(rng), boost::end(rng)); + return rng; +} + +/// \overload +template +inline RandomAccessRange& stable_sort(RandomAccessRange& rng, BinaryPredicate sort_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::stable_sort(boost::begin(rng), boost::end(rng), sort_pred); + return rng; +} + +/// \overload +template +inline const RandomAccessRange& stable_sort(const RandomAccessRange& rng, BinaryPredicate sort_pred) +{ + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessRangeConcept )); + std::stable_sort(boost::begin(rng), boost::end(rng), sort_pred); + return rng; +} + + } // namespace range + using range::stable_sort; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/swap_ranges.hpp b/libs/range/include/boost/range/algorithm/swap_ranges.hpp new file mode 100644 index 00000000..52b0162e --- /dev/null +++ b/libs/range/include/boost/range/algorithm/swap_ranges.hpp @@ -0,0 +1,132 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_SWAP_RANGES_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_SWAP_RANGES_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + template + void swap_ranges_impl(Iterator1 it1, Iterator1 last1, + Iterator2 it2, Iterator2 last2, + single_pass_traversal_tag, + single_pass_traversal_tag) + { + ignore_unused_variable_warning(last2); + for (; it1 != last1; ++it1, ++it2) + { + BOOST_ASSERT( it2 != last2 ); + std::iter_swap(it1, it2); + } + } + + template + void swap_ranges_impl(Iterator1 it1, Iterator1 last1, + Iterator2 it2, Iterator2 last2, + random_access_traversal_tag, + random_access_traversal_tag) + { + ignore_unused_variable_warning(last2); + BOOST_ASSERT( last2 - it2 >= last1 - it1 ); + std::swap_ranges(it1, last1, it2); + } + + template + void swap_ranges_impl(Iterator1 first1, Iterator1 last1, + Iterator2 first2, Iterator2 last2) + { + swap_ranges_impl(first1, last1, first2, last2, + BOOST_DEDUCED_TYPENAME iterator_traversal::type(), + BOOST_DEDUCED_TYPENAME iterator_traversal::type()); + } + } // namespace range_detail + + namespace range + { + +/// \brief template function swap_ranges +/// +/// range-based version of the swap_ranges std algorithm +/// +/// \pre SinglePassRange1 is a model of the SinglePassRangeConcept +/// \pre SinglePassRange2 is a model of the SinglePassRangeConcept +template< class SinglePassRange1, class SinglePassRange2 > +inline SinglePassRange2& +swap_ranges(SinglePassRange1& range1, SinglePassRange2& range2) +{ + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + + boost::range_detail::swap_ranges_impl( + boost::begin(range1), boost::end(range1), + boost::begin(range2), boost::end(range2)); + + return range2; +} + +/// \overload +template< class SinglePassRange1, class SinglePassRange2 > +inline SinglePassRange2& +swap_ranges(const SinglePassRange1& range1, SinglePassRange2& range2) +{ + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + + boost::range_detail::swap_ranges_impl( + boost::begin(range1), boost::end(range1), + boost::begin(range2), boost::end(range2)); + + return range2; +} + +/// \overload +template< class SinglePassRange1, class SinglePassRange2 > +inline const SinglePassRange2& +swap_ranges(SinglePassRange1& range1, const SinglePassRange2& range2) +{ + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + + boost::range_detail::swap_ranges_impl( + boost::begin(range1), boost::end(range1), + boost::begin(range2), boost::end(range2)); + + return range2; +} + +/// \overload +template< class SinglePassRange1, class SinglePassRange2 > +inline const SinglePassRange2& +swap_ranges(const SinglePassRange1& range1, const SinglePassRange2& range2) +{ + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + + boost::range_detail::swap_ranges_impl( + boost::begin(range1), boost::end(range1), + boost::begin(range2), boost::end(range2)); + + return range2; +} + + } // namespace range + using range::swap_ranges; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/transform.hpp b/libs/range/include/boost/range/algorithm/transform.hpp new file mode 100644 index 00000000..ade147a9 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/transform.hpp @@ -0,0 +1,96 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_TRANSFORM_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_TRANSFORM_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + + /// \brief template function transform + /// + /// range-based version of the transform std algorithm + /// + /// \pre SinglePassRange1 is a model of the SinglePassRangeConcept + /// \pre SinglePassRange2 is a model of the SinglePassRangeConcept + /// \pre OutputIterator is a model of the OutputIteratorConcept + /// \pre UnaryOperation is a model of the UnaryFunctionConcept + /// \pre BinaryOperation is a model of the BinaryFunctionConcept + template< class SinglePassRange1, + class OutputIterator, + class UnaryOperation > + inline OutputIterator + transform(const SinglePassRange1& rng, + OutputIterator out, + UnaryOperation fun) + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::transform(boost::begin(rng),boost::end(rng),out,fun); + } + + } // namespace range + + namespace range_detail + { + template< class SinglePassTraversalReadableIterator1, + class SinglePassTraversalReadableIterator2, + class OutputIterator, + class BinaryFunction > + inline OutputIterator + transform_impl(SinglePassTraversalReadableIterator1 first1, + SinglePassTraversalReadableIterator1 last1, + SinglePassTraversalReadableIterator2 first2, + SinglePassTraversalReadableIterator2 last2, + OutputIterator out, + BinaryFunction fn) + { + for (; first1 != last1 && first2 != last2; ++first1, ++first2) + { + *out = fn(*first1, *first2); + ++out; + } + return out; + } + } + + namespace range + { + + /// \overload + template< class SinglePassRange1, + class SinglePassRange2, + class OutputIterator, + class BinaryOperation > + inline OutputIterator + transform(const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + OutputIterator out, + BinaryOperation fun) + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return boost::range_detail::transform_impl( + boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), + out, fun); + } + + } // namespace range + using range::transform; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/unique.hpp b/libs/range/include/boost/range/algorithm/unique.hpp new file mode 100644 index 00000000..8017a837 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/unique.hpp @@ -0,0 +1,107 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_UNIQUE_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_UNIQUE_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function unique +/// +/// range-based version of the unique std algorithm +/// +/// \pre Rng meets the requirements for a Forward range +template< range_return_value re, class ForwardRange > +inline BOOST_DEDUCED_TYPENAME range_return::type +unique( ForwardRange& rng ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack( std::unique( boost::begin(rng), + boost::end(rng)), rng ); +} + +/// \overload +template< range_return_value re, class ForwardRange > +inline BOOST_DEDUCED_TYPENAME range_return::type +unique( const ForwardRange& rng ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack( std::unique( boost::begin(rng), + boost::end(rng)), rng ); +} +/// \overload +template< range_return_value re, class ForwardRange, class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +unique( ForwardRange& rng, BinaryPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::unique(boost::begin(rng), boost::end(rng), pred), + rng); +} +/// \overload +template< range_return_value re, class ForwardRange, class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +unique( const ForwardRange& rng, BinaryPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::unique(boost::begin(rng), boost::end(rng), pred), + rng); +} + +/// \overload +template< class ForwardRange > +inline BOOST_DEDUCED_TYPENAME range_return::type +unique( ForwardRange& rng ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return ::boost::range::unique(rng); +} +/// \overload +template< class ForwardRange > +inline BOOST_DEDUCED_TYPENAME range_return::type +unique( const ForwardRange& rng ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return ::boost::range::unique(rng); +} +/// \overload +template< class ForwardRange, class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +unique( ForwardRange& rng, BinaryPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return ::boost::range::unique(rng, pred); +} +/// \overload +template< class ForwardRange, class BinaryPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +unique( const ForwardRange& rng, BinaryPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return ::boost::range::unique(rng, pred); +} + + } // namespace range + using range::unique; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/unique_copy.hpp b/libs/range/include/boost/range/algorithm/unique_copy.hpp new file mode 100644 index 00000000..0682d747 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/unique_copy.hpp @@ -0,0 +1,51 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_UNIQUE_COPY_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_UNIQUE_COPY_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function unique_copy +/// +/// range-based version of the unique_copy std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +/// \pre OutputIterator is a model of the OutputIteratorConcept +/// \pre BinaryPredicate is a model of the BinaryPredicateConcept +template< class SinglePassRange, class OutputIterator > +inline OutputIterator +unique_copy( const SinglePassRange& rng, OutputIterator out_it ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::unique_copy(boost::begin(rng), boost::end(rng), out_it); +} +/// \overload +template< class SinglePassRange, class OutputIterator, class BinaryPredicate > +inline OutputIterator +unique_copy( const SinglePassRange& rng, OutputIterator out_it, + BinaryPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + return std::unique_copy(boost::begin(rng), boost::end(rng), out_it, pred); +} + + } // namespace range + using range::unique_copy; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm/upper_bound.hpp b/libs/range/include/boost/range/algorithm/upper_bound.hpp new file mode 100644 index 00000000..9abf4b32 --- /dev/null +++ b/libs/range/include/boost/range/algorithm/upper_bound.hpp @@ -0,0 +1,127 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_UPPER_BOUND_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_UPPER_BOUND_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function upper_bound +/// +/// range-based version of the upper_bound std algorithm +/// +/// \pre ForwardRange is a model of the ForwardRangeConcept +template< class ForwardRange, class Value > +inline +BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_iterator::type +>::type +upper_bound( ForwardRange& rng, const Value& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::upper_bound(boost::begin(rng), boost::end(rng), val); +} + +/// \overload +template< class ForwardRange, class Value > +BOOST_DEDUCED_TYPENAME range_iterator::type +upper_bound( const ForwardRange& rng, const Value& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::upper_bound(boost::begin(rng), boost::end(rng), val); +} + +/// \overload +template< class ForwardRange, class Value, class SortPredicate > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_iterator::type +>::type +upper_bound( ForwardRange& rng, const Value& val, SortPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::upper_bound(boost::begin(rng), boost::end(rng), val, pred); +} + +/// \overload +template< class ForwardRange, class Value, class SortPredicate > +inline BOOST_DEDUCED_TYPENAME range_iterator::type +upper_bound( const ForwardRange& rng, const Value& val, SortPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return std::upper_bound(boost::begin(rng), boost::end(rng), val, pred); +} + +/// \overload +template< range_return_value re, class ForwardRange, class Value > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_return::type +>::type +upper_bound( ForwardRange& rng, const Value& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::upper_bound(boost::begin(rng), boost::end(rng), val), + rng); +} + +/// \overload +template< range_return_value re, class ForwardRange, class Value > +inline BOOST_DEDUCED_TYPENAME range_return::type +upper_bound( const ForwardRange& rng, const Value& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::upper_bound(boost::begin(rng), boost::end(rng), val), + rng); +} + +/// \overload +template< range_return_value re, class ForwardRange, class Value, + class SortPredicate > +inline BOOST_DEDUCED_TYPENAME disable_if< + is_const, + BOOST_DEDUCED_TYPENAME range_return::type +>::type +upper_bound( ForwardRange& rng, const Value& val, SortPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::upper_bound(boost::begin(rng), boost::end(rng), val, pred), + rng); +} + +/// \overload +template< range_return_value re, class ForwardRange, class Value, + class SortPredicate > +inline BOOST_DEDUCED_TYPENAME range_return::type +upper_bound( const ForwardRange& rng, const Value& val, SortPredicate pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + return range_return:: + pack(std::upper_bound(boost::begin(rng), boost::end(rng), val, pred), + rng); +} + + } // namespace range + using range::upper_bound; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm_ext.hpp b/libs/range/include/boost/range/algorithm_ext.hpp new file mode 100644 index 00000000..783d38a6 --- /dev/null +++ b/libs/range/include/boost/range/algorithm_ext.hpp @@ -0,0 +1,28 @@ +// Boost.Range library +// +// Copyright Neil Groves 2007. Use, modification and +// distribution is subject to 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) +// +// Copyright Thorsten Ottosen 2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_EXT_HPP +#define BOOST_RANGE_ALGORITHM_EXT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/libs/range/include/boost/range/algorithm_ext/copy_n.hpp b/libs/range/include/boost/range/algorithm_ext/copy_n.hpp new file mode 100644 index 00000000..f8554417 --- /dev/null +++ b/libs/range/include/boost/range/algorithm_ext/copy_n.hpp @@ -0,0 +1,53 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_COPY_N_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_COPY_N_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function copy +/// +/// range-based version of the copy std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +/// \pre OutputIterator is a model of the OutputIteratorConcept +/// \pre 0 <= n <= distance(rng) +template< class SinglePassRange, class Size, class OutputIterator > +inline OutputIterator copy_n(const SinglePassRange& rng, Size n, OutputIterator out) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_ASSERT( n <= static_cast(::boost::distance(rng)) ); + BOOST_ASSERT( n >= static_cast(0) ); + + BOOST_DEDUCED_TYPENAME range_iterator::type source = ::boost::begin(rng); + + for (Size i = 0; i < n; ++i, ++out, ++source) + *out = *source; + + return out; +} + + } // namespace range + using ::boost::range::copy_n; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm_ext/erase.hpp b/libs/range/include/boost/range/algorithm_ext/erase.hpp new file mode 100644 index 00000000..1b47f9b1 --- /dev/null +++ b/libs/range/include/boost/range/algorithm_ext/erase.hpp @@ -0,0 +1,82 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_EXT_ERASE_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_EXT_ERASE_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +template< class Container > +inline Container& erase( Container& on, + iterator_range to_erase ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + on.erase( boost::begin(to_erase), boost::end(to_erase) ); + return on; +} + +template< class Container, class T > +inline Container& remove_erase( Container& on, const T& val ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + on.erase( + std::remove(boost::begin(on), boost::end(on), val), + boost::end(on)); + return on; +} + +template< class Container, class Pred > +inline Container& remove_erase_if( Container& on, Pred pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + on.erase( + std::remove_if(boost::begin(on), boost::end(on), pred), + boost::end(on)); + return on; +} + +template< class Container > +inline Container& unique_erase( Container& on) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + on.erase( + std::unique(boost::begin(on), boost::end(on)), + boost::end(on)); + return on; +} + +template< class Container, class Pred > +inline Container& unique_erase( Container& on, Pred pred ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + on.erase( + std::unique(boost::begin(on), boost::end(on), pred), + boost::end(on)); + return on; +} + + } // namespace range + using range::erase; + using range::remove_erase; + using range::remove_erase_if; + using range::unique_erase; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm_ext/for_each.hpp b/libs/range/include/boost/range/algorithm_ext/for_each.hpp new file mode 100644 index 00000000..a470e2b7 --- /dev/null +++ b/libs/range/include/boost/range/algorithm_ext/for_each.hpp @@ -0,0 +1,86 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_EXT_FOR_EACH_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_EXT_FOR_EACH_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + template + inline Fn2 for_each_impl(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + Fn2 fn) + { + for (; first1 != last1 && first2 != last2; ++first1, ++first2) + { + fn(*first1, *first2); + } + return fn; + } + } + + namespace range + { + template + inline Fn2 for_each(const SinglePassRange1& rng1, const SinglePassRange2& rng2, Fn2 fn) + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::for_each_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2), fn); + } + + template + inline Fn2 for_each(const SinglePassRange1& rng1, SinglePassRange2& rng2, Fn2 fn) + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::for_each_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2), fn); + } + + template + inline Fn2 for_each(SinglePassRange1& rng1, const SinglePassRange2& rng2, Fn2 fn) + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::for_each_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2), fn); + } + + template + inline Fn2 for_each(SinglePassRange1& rng1, SinglePassRange2& rng2, Fn2 fn) + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return ::boost::range_detail::for_each_impl( + ::boost::begin(rng1), ::boost::end(rng1), + ::boost::begin(rng2), ::boost::end(rng2), fn); + } + } // namespace range + using range::for_each; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm_ext/insert.hpp b/libs/range/include/boost/range/algorithm_ext/insert.hpp new file mode 100644 index 00000000..51f1b8e5 --- /dev/null +++ b/libs/range/include/boost/range/algorithm_ext/insert.hpp @@ -0,0 +1,49 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_EXT_INSERT_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_EXT_INSERT_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +template< class Container, class Range > +inline Container& insert( Container& on, + BOOST_DEDUCED_TYPENAME Container::iterator before, + const Range& from ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + on.insert( before, boost::begin(from), boost::end(from) ); + return on; +} + +template< class Container, class Range > +inline Container& insert( Container& on, const Range& from ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( ForwardRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + on.insert(boost::begin(from), boost::end(from)); + return on; +} + + } // namespace range + using range::insert; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm_ext/iota.hpp b/libs/range/include/boost/range/algorithm_ext/iota.hpp new file mode 100644 index 00000000..f7af4462 --- /dev/null +++ b/libs/range/include/boost/range/algorithm_ext/iota.hpp @@ -0,0 +1,54 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_EXT_IOTA_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_EXT_IOTA_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +template< class ForwardRange, class Value > +inline ForwardRange& iota( ForwardRange& rng, Value x ) +{ + BOOST_CONCEPT_ASSERT(( ForwardRangeConcept )); + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; + + iterator_t last_target = ::boost::end(rng); + for (iterator_t target = ::boost::begin(rng); target != last_target; ++target, ++x) + *target = x; + + return rng; +} + +template< class ForwardRange, class Value > +inline const ForwardRange& iota( const ForwardRange& rng, Value x ) +{ + BOOST_CONCEPT_ASSERT(( ForwardRangeConcept )); + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; + + iterator_t last_target = ::boost::end(rng); + for (iterator_t target = ::boost::begin(rng); target != last_target; ++target, ++x) + *target = x; + + return rng; +} + + } // namespace range + using range::iota; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm_ext/is_sorted.hpp b/libs/range/include/boost/range/algorithm_ext/is_sorted.hpp new file mode 100644 index 00000000..3d007292 --- /dev/null +++ b/libs/range/include/boost/range/algorithm_ext/is_sorted.hpp @@ -0,0 +1,57 @@ +// Copyright Bryce Lelbach 2010 +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_EXT_IS_SORTED_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_EXT_IS_SORTED_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +/// \brief template function is_sorted +/// +/// range-based version of the is_sorted std algorithm +/// +/// \pre SinglePassRange is a model of the SinglePassRangeConcept +template +inline bool is_sorted(const SinglePassRange& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((LessThanComparableConcept::type>)); + return ::boost::detail::is_sorted(boost::begin(rng), boost::end(rng)); +} + +/// \overload +template +inline bool is_sorted(const SinglePassRange& rng, BinaryPredicate pred) +{ + BOOST_RANGE_CONCEPT_ASSERT((SinglePassRangeConcept)); + BOOST_RANGE_CONCEPT_ASSERT((BinaryPredicateConcept::type, + BOOST_DEDUCED_TYPENAME range_value::type>)); + return ::boost::detail::is_sorted(boost::begin(rng), boost::end(rng), pred); +} + + } // namespace range + +using range::is_sorted; + +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm_ext/overwrite.hpp b/libs/range/include/boost/range/algorithm_ext/overwrite.hpp new file mode 100644 index 00000000..f84f6eac --- /dev/null +++ b/libs/range/include/boost/range/algorithm_ext/overwrite.hpp @@ -0,0 +1,84 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_EXT_OVERWRITE_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_EXT_OVERWRITE_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +template< class SinglePassRange1, class SinglePassRange2 > +inline void overwrite( const SinglePassRange1& from, SinglePassRange2& to ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + BOOST_DEDUCED_TYPENAME range_iterator::type + i = boost::begin(from), e = boost::end(from); + + BOOST_DEDUCED_TYPENAME range_iterator::type + out = boost::begin(to); + +#ifndef NDEBUG + BOOST_DEDUCED_TYPENAME range_iterator::type + last_out = boost::end(to); +#endif + + for( ; i != e; ++out, ++i ) + { +#ifndef NDEBUG + BOOST_ASSERT( out != last_out + && "out of bounds in boost::overwrite()" ); +#endif + *out = *i; + } +} + +template< class SinglePassRange1, class SinglePassRange2 > +inline void overwrite( const SinglePassRange1& from, const SinglePassRange2& to ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + BOOST_DEDUCED_TYPENAME range_iterator::type + i = boost::begin(from), e = boost::end(from); + + BOOST_DEDUCED_TYPENAME range_iterator::type + out = boost::begin(to); + +#ifndef NDEBUG + BOOST_DEDUCED_TYPENAME range_iterator::type + last_out = boost::end(to); +#endif + + for( ; i != e; ++out, ++i ) + { +#ifndef NDEBUG + BOOST_ASSERT( out != last_out + && "out of bounds in boost::overwrite()" ); +#endif + *out = *i; + } +} + + } // namespace range + using range::overwrite; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm_ext/push_back.hpp b/libs/range/include/boost/range/algorithm_ext/push_back.hpp new file mode 100644 index 00000000..6fb9b9bf --- /dev/null +++ b/libs/range/include/boost/range/algorithm_ext/push_back.hpp @@ -0,0 +1,41 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_EXT_PUSH_BACK_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_EXT_PUSH_BACK_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +template< class Container, class Range > +inline Container& push_back( Container& on, const Range& from ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_ASSERT_MSG(!range_detail::is_same_object(on, from), + "cannot copy from a container to itself"); + on.insert( on.end(), boost::begin(from), boost::end(from) ); + return on; +} + + } // namespace range + using range::push_back; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/algorithm_ext/push_front.hpp b/libs/range/include/boost/range/algorithm_ext/push_front.hpp new file mode 100644 index 00000000..e8930980 --- /dev/null +++ b/libs/range/include/boost/range/algorithm_ext/push_front.hpp @@ -0,0 +1,41 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ALGORITHM_EXT_PUSH_FRONT_HPP_INCLUDED +#define BOOST_RANGE_ALGORITHM_EXT_PUSH_FRONT_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +template< class Container, class Range > +inline Container& push_front( Container& on, const Range& from ) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_ASSERT_MSG(!range_detail::is_same_object(on, from), + "cannot copy from a container to itself"); + on.insert( on.begin(), boost::begin(from), boost::end(from) ); + return on; +} + + } // namespace range + using range::push_front; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/any_range.hpp b/libs/range/include/boost/range/any_range.hpp new file mode 100644 index 00000000..1cb59962 --- /dev/null +++ b/libs/range/include/boost/range/any_range.hpp @@ -0,0 +1,204 @@ +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ANY_RANGE_HPP_INCLUDED +#define BOOST_RANGE_ANY_RANGE_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + // If T is use_default, return the result of Default, otherwise + // return T. + // + // This is an implementation artifact used to pick intelligent default + // values when the user specified boost::use_default as a template + // parameter. + template< + class T, + class Default + > + struct any_range_default_help + : mpl::eval_if< + is_same + , Default + , mpl::identity + > + { + }; + + template< + class WrappedRange + , class Value + , class Reference + > + struct any_range_value_type + { +# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY + typedef typename any_range_default_help< + Value + , mpl::eval_if< + is_same + , range_value< + typename remove_const + ::type> + , remove_reference + > + >::type type; +# else + typedef typename any_range_default_help< + Value + , range_value< + typename remove_const + ::type> + >::type type; +# endif + }; + + template< + class Value + , class Traversal + , class Reference = Value& + , class Difference = std::ptrdiff_t + , class Buffer = use_default + > + class any_range + : public iterator_range< + any_iterator< + Value + , Traversal + , Reference + , Difference + , typename any_range_default_help< + Buffer + , mpl::identity + >::type + > + > + { + typedef iterator_range< + any_iterator< + Value + , Traversal + , Reference + , Difference + , typename any_range_default_help< + Buffer + , mpl::identity + >::type + > + > base_type; + + struct enabler {}; + struct disabler {}; + public: + any_range() + { + } + + any_range(const any_range& other) + : base_type(other) + { + } + + template + any_range(WrappedRange& wrapped_range) + : base_type(boost::begin(wrapped_range), + boost::end(wrapped_range)) + { + } + + template + any_range(const WrappedRange& wrapped_range) + : base_type(boost::begin(wrapped_range), + boost::end(wrapped_range)) + { + } + + template< + class OtherValue + , class OtherTraversal + , class OtherReference + , class OtherDifference + > + any_range(const any_range< + OtherValue + , OtherTraversal + , OtherReference + , OtherDifference + , Buffer + >& other) + : base_type(boost::begin(other), boost::end(other)) + { + } + + template + any_range(Iterator first, Iterator last) + : base_type(first, last) + { + } + }; + + template< + class WrappedRange + , class Value = use_default + , class Traversal = use_default + , class Reference = use_default + , class Difference = use_default + , class Buffer = use_default + > + struct any_range_type_generator + { + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + typedef any_range< + typename any_range_value_type< + WrappedRange + , Value + , typename any_range_default_help< + Reference + , range_reference + >::type + >::type + , typename any_range_default_help< + Traversal + , iterator_traversal< + typename range_iterator::type + > + >::type + , typename any_range_default_help< + Reference + , range_reference + >::type + , typename any_range_default_help< + Difference + , range_difference + >::type + , typename any_range_default_help< + Buffer + , mpl::identity + >::type + > type; + }; + } // namespace range_detail + + using range_detail::any_range; + using range_detail::any_range_type_generator; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/as_array.hpp b/libs/range/include/boost/range/as_array.hpp new file mode 100644 index 00000000..134efd0c --- /dev/null +++ b/libs/range/include/boost/range/as_array.hpp @@ -0,0 +1,41 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_AS_ARRAY_HPP +#define BOOST_RANGE_AS_ARRAY_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include + +namespace boost +{ + + template< class R > + inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > + as_array( R& r ) + { + return boost::make_iterator_range( r ); + } + + template< class Range > + inline boost::iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > + as_array( const Range& r ) + { + return boost::make_iterator_range( r ); + } + +} + +#endif + diff --git a/libs/range/include/boost/range/as_literal.hpp b/libs/range/include/boost/range/as_literal.hpp new file mode 100644 index 00000000..074f1d7f --- /dev/null +++ b/libs/range/include/boost/range/as_literal.hpp @@ -0,0 +1,164 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_AS_LITERAL_HPP +#define BOOST_RANGE_AS_LITERAL_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include + +#include + +#include + +#if !defined(BOOST_NO_CXX11_CHAR16_T) || !defined(BOOST_NO_CXX11_CHAR32_T) +#include // for std::char_traits +#endif + +#ifndef BOOST_NO_CWCHAR +#include +#endif + +namespace boost +{ + namespace range_detail + { + inline std::size_t length( const char* s ) + { + return strlen( s ); + } + +#ifndef BOOST_NO_CXX11_CHAR16_T + inline std::size_t length( const char16_t* s ) + { + return std::char_traits::length( s ); + } +#endif + +#ifndef BOOST_NO_CXX11_CHAR32_T + inline std::size_t length( const char32_t* s ) + { + return std::char_traits::length( s ); + } +#endif + +#ifndef BOOST_NO_CWCHAR + inline std::size_t length( const wchar_t* s ) + { + return wcslen( s ); + } +#endif + + // + // Remark: the compiler cannot choose between T* and T[sz] + // overloads, so we must put the T* internal to the + // unconstrained version. + // + + inline bool is_char_ptr( char* ) + { + return true; + } + + inline bool is_char_ptr( const char* ) + { + return true; + } + +#ifndef BOOST_NO_CXX11_CHAR16_T + inline bool is_char_ptr( char16_t* ) + { + return true; + } + + inline bool is_char_ptr( const char16_t* ) + { + return true; + } +#endif + +#ifndef BOOST_NO_CXX11_CHAR32_T + inline bool is_char_ptr( char32_t* ) + { + return true; + } + + inline bool is_char_ptr( const char32_t* ) + { + return true; + } +#endif + +#ifndef BOOST_NO_CWCHAR + inline bool is_char_ptr( wchar_t* ) + { + return true; + } + + inline bool is_char_ptr( const wchar_t* ) + { + return true; + } +#endif + + template< class T > + inline long is_char_ptr( const T& /* r */ ) + { + return 0L; + } + + template< class T > + inline iterator_range + make_range( T* const r, bool ) + { + return iterator_range( r, r + length(r) ); + } + + template< class T > + inline iterator_range::type> + make_range( T& r, long ) + { + return boost::make_iterator_range( r ); + } + + } + + template< class Range > + inline iterator_range::type> + as_literal( Range& r ) + { + return range_detail::make_range( r, range_detail::is_char_ptr(r) ); + } + + template< class Range > + inline iterator_range::type> + as_literal( const Range& r ) + { + return range_detail::make_range( r, range_detail::is_char_ptr(r) ); + } + + template< class Char, std::size_t sz > + inline iterator_range as_literal( Char (&arr)[sz] ) + { + return range_detail::make_range( arr, range_detail::is_char_ptr(arr) ); + } + + template< class Char, std::size_t sz > + inline iterator_range as_literal( const Char (&arr)[sz] ) + { + return range_detail::make_range( arr, range_detail::is_char_ptr(arr) ); + } +} + +#endif diff --git a/libs/range/include/boost/range/atl.hpp b/libs/range/include/boost/range/atl.hpp new file mode 100644 index 00000000..e6500e58 --- /dev/null +++ b/libs/range/include/boost/range/atl.hpp @@ -0,0 +1,724 @@ +#ifndef BOOST_RANGE_ATL_HPP +#define BOOST_RANGE_ATL_HPP + + + + +// Boost.Range ATL Extension +// +// Copyright Shunsuke Sogame 2005-2006. +// 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) + + + + +// config +// + + +#include // _ATL_VER + + +#if !defined(BOOST_RANGE_ATL_NO_COLLECTIONS) + #if (_ATL_VER < 0x0700) + #define BOOST_RANGE_ATL_NO_COLLECTIONS + #endif +#endif + + +#if !defined(BOOST_RANGE_ATL_HAS_OLD_CSIMPLE_XXX) + #if (_ATL_VER < 0x0700) // dubious + #define BOOST_RANGE_ATL_HAS_OLD_CSIMPLE_XXX + #endif +#endif + + +// forward declarations +// + + +#include // IID + + +namespace ATL { + + +#if !defined(BOOST_RANGE_ATL_NO_COLLECTIONS) + + + // arrays + // + template< class E, class ETraits > + class CAtlArray; + + template< class E > + class CAutoPtrArray; + + template< class I, const IID *piid > + class CInterfaceArray; + + + // lists + // + template< class E, class ETraits > + class CAtlList; + + template< class E > + class CAutoPtrList; + + template< class E, class Allocator > + class CHeapPtrList; + + template< class I, const IID *piid > + class CInterfaceList; + + + // maps + // + template< class K, class V, class KTraits, class VTraits > + class CAtlMap; + + template< class K, class V, class KTraits, class VTraits > + class CRBTree; + + template< class K, class V, class KTraits, class VTraits > + class CRBMap; + + template< class K, class V, class KTraits, class VTraits > + class CRBMultiMap; + + + // strings + // +#if !defined(BOOST_RANGE_ATL_HAS_OLD_CSIMPLESTRING) + template< class BaseType, bool t_bMFCDLL > + class CSimpleStringT; +#else + template< class BaseType > + class CSimpleStringT; +#endif + + template< class BaseType, class StringTraits > + class CStringT; + + template< class StringType, int t_nChars > + class CFixedStringT; + + template< class BaseType, const int t_nSize > + class CStaticString; + + +#endif // !defined(BOOST_RANGE_ATL_NO_COLLECTIONS) + + + // simples + // +#if !defined(BOOST_RANGE_ATL_HAS_OLD_CSIMPLE_XXX) + + template< class T, class TEqual > + class CSimpleArray; + + template< class TKey, class TVal, class TEqual > + class CSimpleMap; + +#else + + template< class T > + class CSimpleArray; + + template< class T > + class CSimpleValArray; + + template< class TKey, class TVal > + class CSimpleMap; + +#endif // !defined(BOOST_RANGE_ATL_HAS_OLD_CSIMPLE_XXX) + + + // pointers + // + template< class E > + class CAutoPtr; + + template< class T > + class CComPtr; + + template< class T, const IID *piid > + class CComQIPtr; + + template< class E, class Allocator > + class CHeapPtr; + + template< class T > + class CAdapt; + + +} // namespace ATL + + + + +// indirect_iterator customizations +// + + +#include +#include + + +namespace boost { + + + template< class E > + struct pointee< ATL::CAutoPtr > : + mpl::identity + { }; + + template< class T > + struct pointee< ATL::CComPtr > : + mpl::identity + { }; + + template< class T, const IID *piid > + struct pointee< ATL::CComQIPtr > : + mpl::identity + { }; + + template< class E, class Allocator > + struct pointee< ATL::CHeapPtr > : + mpl::identity + { }; + + template< class T > + struct pointee< ATL::CAdapt > : + pointee + { }; + + +} // namespace boost + + + + +// extended customizations +// + + +#include +#include +#include +#include +#include // CComBSTR + + +namespace boost { namespace range_detail_microsoft { + + +#if !defined(BOOST_RANGE_ATL_NO_COLLECTIONS) + + + // arrays + // + + struct atl_array_functions : + array_functions + { + template< class Iterator, class X > + Iterator end(X& x) // redefine + { + return x.GetData() + x.GetCount(); // no 'GetSize()' + } + }; + + + template< class E, class ETraits > + struct customization< ATL::CAtlArray > : + atl_array_functions + { + template< class X > + struct meta + { + typedef E val_t; + + typedef val_t *mutable_iterator; + typedef val_t const *const_iterator; + }; + }; + + + template< class E > + struct customization< ATL::CAutoPtrArray > : + atl_array_functions + { + template< class X > + struct meta + { + // ATL::CAutoPtr/CHeapPtr is no assignable. + typedef ATL::CAutoPtr val_t; + typedef val_t *miter_t; + typedef val_t const *citer_t; + + typedef indirect_iterator mutable_iterator; + typedef indirect_iterator const_iterator; + }; + }; + + + template< class I, const IID *piid > + struct customization< ATL::CInterfaceArray > : + atl_array_functions + { + template< class X > + struct meta + { + typedef ATL::CComQIPtr val_t; + + typedef val_t *mutable_iterator; + typedef val_t const *const_iterator; + }; + }; + + + template< class E, class ETraits > + struct customization< ATL::CAtlList > : + list_functions + { + template< class X > + struct meta + { + typedef E val_t; + + typedef list_iterator mutable_iterator; + typedef list_iterator const_iterator; + }; + }; + + + struct indirected_list_functions + { + template< class Iterator, class X > + Iterator begin(X& x) + { + typedef typename Iterator::base_type base_t; // == list_iterator + return Iterator(base_t(x, x.GetHeadPosition())); + } + + template< class Iterator, class X > + Iterator end(X& x) + { + typedef typename Iterator::base_type base_t; + return Iterator(base_t(x, POSITION(0))); + } + }; + + + template< class E > + struct customization< ATL::CAutoPtrList > : + indirected_list_functions + { + template< class X > + struct meta + { + typedef ATL::CAutoPtr val_t; + typedef list_iterator miter_t; + typedef list_iterator citer_t; + + typedef indirect_iterator mutable_iterator; + typedef indirect_iterator const_iterator; + }; + }; + + + template< class E, class Allocator > + struct customization< ATL::CHeapPtrList > : + indirected_list_functions + { + template< class X > + struct meta + { + typedef ATL::CHeapPtr val_t; + typedef list_iterator miter_t; + typedef list_iterator citer_t; + + typedef indirect_iterator mutable_iterator; + typedef indirect_iterator const_iterator; + }; + }; + + + template< class I, const IID *piid > + struct customization< ATL::CInterfaceList > : + list_functions + { + template< class X > + struct meta + { + typedef ATL::CComQIPtr val_t; + + typedef list_iterator mutable_iterator; + typedef list_iterator const_iterator; + }; + }; + + + // maps + // + + struct atl_rb_tree_tag + { }; + + template< > + struct customization< atl_rb_tree_tag > : + indirected_list_functions + { + template< class X > + struct meta + { + typedef typename X::CPair val_t; + + typedef list_iterator miter_t; + typedef list_iterator citer_t; + + typedef indirect_iterator mutable_iterator; + typedef indirect_iterator const_iterator; + }; + }; + + + template< class K, class V, class KTraits, class VTraits > + struct customization< ATL::CAtlMap > : + customization< atl_rb_tree_tag > + { + template< class Iterator, class X > + Iterator begin(X& x) // redefine + { + typedef typename Iterator::base_type base_t; // == list_iterator + return Iterator(base_t(x, x.GetStartPosition())); // no 'GetHeadPosition' + } + }; + + + // strings + // + + struct atl_string_tag + { }; + + template< > + struct customization< atl_string_tag > + { + template< class X > + struct meta + { + typedef typename X::PXSTR mutable_iterator; + typedef typename X::PCXSTR const_iterator; + }; + + template< class Iterator, class X > + typename mutable_::type begin(X& x) + { + return x.GetBuffer(0); + } + + template< class Iterator, class X > + Iterator begin(X const& x) + { + return x.GetString(); + } + + template< class Iterator, class X > + Iterator end(X& x) + { + return begin(x) + x.GetLength(); + } + }; + + + template< class BaseType, const int t_nSize > + struct customization< ATL::CStaticString > + { + template< class X > + struct meta + { + typedef BaseType const *mutable_iterator; + typedef mutable_iterator const_iterator; + }; + + template< class Iterator, class X > + Iterator begin(X const& x) + { + return x; + } + + template< class Iterator, class X > + Iterator end(X const& x) + { + return begin(x) + X::GetLength(); + } + }; + + +#endif // !defined(BOOST_RANGE_ATL_NO_COLLECTIONS) + + + template< > + struct customization< ATL::CComBSTR > + { + template< class X > + struct meta + { + typedef OLECHAR *mutable_iterator; + typedef OLECHAR const *const_iterator; + }; + + template< class Iterator, class X > + Iterator begin(X& x) + { + return x.operator BSTR(); + } + + template< class Iterator, class X > + Iterator end(X& x) + { + return begin(x) + x.Length(); + } + }; + + + // simples + // + +#if !defined(BOOST_RANGE_ATL_HAS_OLD_CSIMPLE_XXX) + template< class T, class TEqual > + struct customization< ATL::CSimpleArray > : +#else + template< class T > + struct customization< ATL::CSimpleArray > : +#endif + array_functions + { + template< class X > + struct meta + { + typedef T val_t; + + typedef val_t *mutable_iterator; + typedef val_t const *const_iterator; + }; + }; + + +#if defined(BOOST_RANGE_ATL_HAS_OLD_CSIMPLE_XXX) + + template< class T > + struct customization< ATL::CSimpleValArray > : + array_functions + { + template< class X > + struct meta + { + typedef T val_t; + + typedef val_t *mutable_iterator; + typedef val_t const *const_iterator; + }; + }; + +#endif // defined(BOOST_RANGE_ATL_HAS_OLD_CSIMPLE_XXX) + + +#if !defined(BOOST_RANGE_ATL_HAS_OLD_CSIMPLE_XXX) + template< class TKey, class TVal, class TEqual > + struct customization< ATL::CSimpleMap > +#else + template< class TKey, class TVal > + struct customization< ATL::CSimpleMap > +#endif + { + template< class X > + struct meta + { + typedef TKey k_val_t; + typedef k_val_t *k_miter_t; + typedef k_val_t const *k_citer_t; + + typedef TVal v_val_t; + typedef v_val_t *v_miter_t; + typedef v_val_t const *v_citer_t; + + // Topic: + // 'std::pair' can't contain references + // because of reference to reference problem. + + typedef zip_iterator< tuple > mutable_iterator; + typedef zip_iterator< tuple > const_iterator; + }; + + template< class Iterator, class X > + Iterator begin(X& x) + { + return Iterator(boost::make_tuple(x.m_aKey, x.m_aVal)); + } + + template< class Iterator, class X > + Iterator end(X& x) + { + return Iterator(boost::make_tuple(x.m_aKey + x.GetSize(), x.m_aVal + x.GetSize())); + } + }; + + +} } // namespace boost::range_detail_microsoft + + + + +// range customizations +// + + +#if !defined(BOOST_RANGE_ATL_NO_COLLECTIONS) + + + // arrays + // + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CAtlArray, 2 + ) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CAutoPtrArray, 1 + ) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CInterfaceArray, (class)(const IID *) + ) + + + // lists + // + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CAtlList, 2 + ) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CAutoPtrList, 1 + ) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CHeapPtrList, 2 + ) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CInterfaceList, (class)(const IID *) + ) + + + //maps + // + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CAtlMap, 4 + ) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::atl_rb_tree_tag, + (ATL, BOOST_PP_NIL), CRBTree, 4 + ) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::atl_rb_tree_tag, + (ATL, BOOST_PP_NIL), CRBMap, 4 + ) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::atl_rb_tree_tag, + (ATL, BOOST_PP_NIL), CRBMultiMap, 4 + ) + + + // strings + // + #if !defined(BOOST_RANGE_ATL_HAS_OLD_CSIMPLESTRING) + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::atl_string_tag, + (ATL, BOOST_PP_NIL), CSimpleStringT, (class)(bool) + ) + #else + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::atl_string_tag, + (ATL, BOOST_PP_NIL), CSimpleStringT, 1 + ) + #endif + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::atl_string_tag, + (ATL, BOOST_PP_NIL), CStringT, 2 + ) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::atl_string_tag, + (ATL, BOOST_PP_NIL), CFixedStringT, (class)(int) + ) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CStaticString, (class)(const int) + ) + + +#endif // !defined(BOOST_RANGE_ATL_NO_COLLECTIONS) + + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CComBSTR +) + + +// simples +// +#if !defined(BOOST_RANGE_ATL_HAS_OLD_CSIMPLE_XXX) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CSimpleArray, 2 + ) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CSimpleMap, 3 + ) + +#else + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CSimpleArray, 1 + ) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CSimpleMap, 2 + ) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + (ATL, BOOST_PP_NIL), CSimpleValArray, 1 + ) + +#endif // !defined(BOOST_RANGE_ATL_HAS_OLD_CSIMPLE_XXX) + + + + +#endif diff --git a/libs/range/include/boost/range/begin.hpp b/libs/range/include/boost/range/begin.hpp new file mode 100644 index 00000000..17d9f842 --- /dev/null +++ b/libs/range/include/boost/range/begin.hpp @@ -0,0 +1,137 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_BEGIN_HPP +#define BOOST_RANGE_BEGIN_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include + +#include +#include +#include + +namespace boost +{ + +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +namespace range_detail +{ +#endif + + ////////////////////////////////////////////////////////////////////// + // primary template + ////////////////////////////////////////////////////////////////////// + + template< typename C > + BOOST_CONSTEXPR inline BOOST_DEDUCED_TYPENAME range_iterator::type + range_begin( C& c ) + { + // + // If you get a compile-error here, it is most likely because + // you have not implemented range_begin() properly in + // the namespace of C + // + return c.begin(); + } + + ////////////////////////////////////////////////////////////////////// + // pair + ////////////////////////////////////////////////////////////////////// + + template< typename Iterator > + BOOST_CONSTEXPR inline Iterator range_begin( const std::pair& p ) + { + return p.first; + } + + template< typename Iterator > + BOOST_CONSTEXPR inline Iterator range_begin( std::pair& p ) + { + return p.first; + } + + ////////////////////////////////////////////////////////////////////// + // array + ////////////////////////////////////////////////////////////////////// + + // + // May this be discarded? Or is it needed for bad compilers? + // + template< typename T, std::size_t sz > + BOOST_CONSTEXPR inline const T* range_begin( const T (&a)[sz] ) BOOST_NOEXCEPT + { + return a; + } + + template< typename T, std::size_t sz > + BOOST_CONSTEXPR inline T* range_begin( T (&a)[sz] ) BOOST_NOEXCEPT + { + return a; + } + + +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +} // namespace 'range_detail' +#endif + +// Use a ADL namespace barrier to avoid ambiguity with other unqualified +// calls. This is particularly important with C++0x encouraging +// unqualified calls to begin/end. +namespace range_adl_barrier +{ + +template< class T > +#if !BOOST_WORKAROUND(BOOST_GCC, < 40700) +BOOST_CONSTEXPR +#endif +inline BOOST_DEDUCED_TYPENAME range_iterator::type begin( T& r ) +{ +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) + using namespace range_detail; +#endif + return range_begin( r ); +} + +template< class T > +#if !BOOST_WORKAROUND(BOOST_GCC, < 40700) +BOOST_CONSTEXPR +#endif +inline BOOST_DEDUCED_TYPENAME range_iterator::type begin( const T& r ) +{ +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) + using namespace range_detail; +#endif + return range_begin( r ); +} + + } // namespace range_adl_barrier +} // namespace boost + +namespace boost +{ + namespace range_adl_barrier + { + template< class T > + inline BOOST_DEDUCED_TYPENAME range_iterator::type + const_begin( const T& r ) + { + return boost::range_adl_barrier::begin( r ); + } + } // namespace range_adl_barrier + + using namespace range_adl_barrier; +} // namespace boost + +#endif + diff --git a/libs/range/include/boost/range/category.hpp b/libs/range/include/boost/range/category.hpp new file mode 100644 index 00000000..f5431adf --- /dev/null +++ b/libs/range/include/boost/range/category.hpp @@ -0,0 +1,29 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_CATEGORY_HPP +#define BOOST_RANGE_CATEGORY_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ + template< class T > + struct range_category : iterator_category< typename range_iterator::type > + { }; +} + +#endif diff --git a/libs/range/include/boost/range/combine.hpp b/libs/range/include/boost/range/combine.hpp new file mode 100644 index 00000000..26cef9ad --- /dev/null +++ b/libs/range/include/boost/range/combine.hpp @@ -0,0 +1,45 @@ +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_COMBINE_HPP +#define BOOST_RANGE_COMBINE_HPP + +#include +#include +#include + +namespace boost +{ + namespace range + { + +template +class combined_range + : public iterator_range > +{ + typedef iterator_range > base; +public: + combined_range(IterTuple first, IterTuple last) + : base(first, last) + { + } +}; + + } // namespace range +} // namespace boost + +#if defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) || \ + defined(BOOST_NO_CXX11_DECLTYPE) || \ + defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || \ + defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +# include +#else +# include +#endif + +#endif diff --git a/libs/range/include/boost/range/concepts.hpp b/libs/range/include/boost/range/concepts.hpp new file mode 100644 index 00000000..d6235d66 --- /dev/null +++ b/libs/range/include/boost/range/concepts.hpp @@ -0,0 +1,388 @@ +// Boost.Range library concept checks +// +// Copyright Neil Groves 2009. Use, modification and distribution +// are subject to 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) +// +// Copyright Daniel Walker 2006. Use, modification and distribution +// are subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_CONCEPTS_HPP +#define BOOST_RANGE_CONCEPTS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/*! + * \file + * \brief Concept checks for the Boost Range library. + * + * The structures in this file may be used in conjunction with the + * Boost Concept Check library to insure that the type of a function + * parameter is compatible with a range concept. If not, a meaningful + * compile time error is generated. Checks are provided for the range + * concepts related to iterator traversal categories. For example, the + * following line checks that the type T models the ForwardRange + * concept. + * + * \code + * BOOST_CONCEPT_ASSERT((ForwardRangeConcept)); + * \endcode + * + * A different concept check is required to ensure writeable value + * access. For example to check for a ForwardRange that can be written + * to, the following code is required. + * + * \code + * BOOST_CONCEPT_ASSERT((WriteableForwardRangeConcept)); + * \endcode + * + * \see http://www.boost.org/libs/range/doc/range.html for details + * about range concepts. + * \see http://www.boost.org/libs/iterator/doc/iterator_concepts.html + * for details about iterator concepts. + * \see http://www.boost.org/libs/concept_check/concept_check.htm for + * details about concept checks. + */ + +namespace boost { + + namespace range_detail { + +#ifndef BOOST_RANGE_ENABLE_CONCEPT_ASSERT + +// List broken compiler versions here: +#ifndef __clang__ + #ifdef __GNUC__ + // GNUC 4.2 has strange issues correctly detecting compliance with the Concepts + // hence the least disruptive approach is to turn-off the concept checking for + // this version of the compiler. + #if __GNUC__ == 4 && __GNUC_MINOR__ == 2 + #define BOOST_RANGE_ENABLE_CONCEPT_ASSERT 0 + #endif + #endif + + #ifdef __GCCXML__ + // GCC XML, unsurprisingly, has the same issues + #if __GCCXML_GNUC__ == 4 && __GCCXML_GNUC_MINOR__ == 2 + #define BOOST_RANGE_ENABLE_CONCEPT_ASSERT 0 + #endif + #endif +#endif + + #ifdef BOOST_BORLANDC + #define BOOST_RANGE_ENABLE_CONCEPT_ASSERT 0 + #endif + + #ifdef __PATHCC__ + #define BOOST_RANGE_ENABLE_CONCEPT_ASSERT 0 + #endif + +// Default to using the concept asserts unless we have defined it off +// during the search for black listed compilers. + #ifndef BOOST_RANGE_ENABLE_CONCEPT_ASSERT + #define BOOST_RANGE_ENABLE_CONCEPT_ASSERT 1 + #endif + +#endif + +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT + #define BOOST_RANGE_CONCEPT_ASSERT( x ) BOOST_CONCEPT_ASSERT( x ) +#else + #define BOOST_RANGE_CONCEPT_ASSERT( x ) +#endif + + // Rationale for the inclusion of redefined iterator concept + // classes: + // + // The Range algorithms often do not require that the iterators are + // Assignable or default constructable, but the correct standard + // conformant iterators do require the iterators to be a model of the + // Assignable concept. + // Iterators that contains a functor that is not assignable therefore + // are not correct models of the standard iterator concepts, + // despite being adequate for most algorithms. An example of this + // use case is the combination of the boost::adaptors::filtered + // class with a boost::lambda::bind generated functor. + // Ultimately modeling the range concepts using composition + // with the Boost.Iterator concepts would render the library + // incompatible with many common Boost.Lambda expressions. + template + struct IncrementableIteratorConcept : CopyConstructible + { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT + typedef BOOST_DEDUCED_TYPENAME iterator_traversal::type traversal_category; + + BOOST_RANGE_CONCEPT_ASSERT(( + Convertible< + traversal_category, + incrementable_traversal_tag + >)); + + BOOST_CONCEPT_USAGE(IncrementableIteratorConcept) + { + ++i; + (void)i++; + } + private: + Iterator i; +#endif + }; + + template + struct SinglePassIteratorConcept + : IncrementableIteratorConcept + , EqualityComparable + { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT + BOOST_RANGE_CONCEPT_ASSERT(( + Convertible< + BOOST_DEDUCED_TYPENAME SinglePassIteratorConcept::traversal_category, + single_pass_traversal_tag + >)); + + BOOST_CONCEPT_USAGE(SinglePassIteratorConcept) + { + Iterator i2(++i); + boost::ignore_unused_variable_warning(i2); + + // deliberately we are loose with the postfix version for the single pass + // iterator due to the commonly poor adherence to the specification means that + // many algorithms would be unusable, whereas actually without the check they + // work + (void)(i++); + + BOOST_DEDUCED_TYPENAME std::iterator_traits::reference r1(*i); + boost::ignore_unused_variable_warning(r1); + + BOOST_DEDUCED_TYPENAME std::iterator_traits::reference r2(*(++i)); + boost::ignore_unused_variable_warning(r2); + } + private: + Iterator i; +#endif + }; + + template + struct ForwardIteratorConcept + : SinglePassIteratorConcept + , DefaultConstructible + { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::difference_type difference_type; + + BOOST_MPL_ASSERT((is_integral)); + BOOST_MPL_ASSERT_RELATION(std::numeric_limits::is_signed, ==, true); + + BOOST_RANGE_CONCEPT_ASSERT(( + Convertible< + BOOST_DEDUCED_TYPENAME ForwardIteratorConcept::traversal_category, + forward_traversal_tag + >)); + + BOOST_CONCEPT_USAGE(ForwardIteratorConcept) + { + // See the above note in the SinglePassIteratorConcept about the handling of the + // postfix increment. Since with forward and better iterators there is no need + // for a proxy, we can sensibly require that the dereference result + // is convertible to reference. + Iterator i2(i++); + boost::ignore_unused_variable_warning(i2); + BOOST_DEDUCED_TYPENAME std::iterator_traits::reference r(*(i++)); + boost::ignore_unused_variable_warning(r); + } + private: + Iterator i; +#endif + }; + + template + struct BidirectionalIteratorConcept + : ForwardIteratorConcept + { + #if BOOST_RANGE_ENABLE_CONCEPT_ASSERT + BOOST_RANGE_CONCEPT_ASSERT(( + Convertible< + BOOST_DEDUCED_TYPENAME BidirectionalIteratorConcept::traversal_category, + bidirectional_traversal_tag + >)); + + BOOST_CONCEPT_USAGE(BidirectionalIteratorConcept) + { + --i; + (void)i--; + } + private: + Iterator i; + #endif + }; + + template + struct RandomAccessIteratorConcept + : BidirectionalIteratorConcept + { + #if BOOST_RANGE_ENABLE_CONCEPT_ASSERT + BOOST_RANGE_CONCEPT_ASSERT(( + Convertible< + BOOST_DEDUCED_TYPENAME RandomAccessIteratorConcept::traversal_category, + random_access_traversal_tag + >)); + + BOOST_CONCEPT_USAGE(RandomAccessIteratorConcept) + { + i += n; + i = i + n; + i = n + i; + i -= n; + i = i - n; + n = i - j; + } + private: + BOOST_DEDUCED_TYPENAME BidirectionalIteratorConcept::difference_type n; + Iterator i; + Iterator j; + #endif + }; + + } // namespace range_detail + + //! Check if a type T models the SinglePassRange range concept. + template + struct SinglePassRangeConcept + { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT + // A few compilers don't like the rvalue reference T types so just + // remove it. + typedef BOOST_DEDUCED_TYPENAME remove_reference::type Rng; + + typedef BOOST_DEDUCED_TYPENAME range_iterator< + Rng const + >::type const_iterator; + + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator; + + BOOST_RANGE_CONCEPT_ASSERT(( + range_detail::SinglePassIteratorConcept)); + + BOOST_RANGE_CONCEPT_ASSERT(( + range_detail::SinglePassIteratorConcept)); + + BOOST_CONCEPT_USAGE(SinglePassRangeConcept) + { + // This has been modified from assigning to this->i + // (where i was a member variable) to improve + // compatibility with Boost.Lambda + iterator i1 = boost::begin(*m_range); + iterator i2 = boost::end(*m_range); + + boost::ignore_unused_variable_warning(i1); + boost::ignore_unused_variable_warning(i2); + + const_constraints(*m_range); + } + + private: + void const_constraints(const Rng& const_range) + { + const_iterator ci1 = boost::begin(const_range); + const_iterator ci2 = boost::end(const_range); + + boost::ignore_unused_variable_warning(ci1); + boost::ignore_unused_variable_warning(ci2); + } + + // Rationale: + // The type of m_range is T* rather than T because it allows + // T to be an abstract class. The other obvious alternative of + // T& produces a warning on some compilers. + Rng* m_range; +#endif + }; + + //! Check if a type T models the ForwardRange range concept. + template + struct ForwardRangeConcept : SinglePassRangeConcept + { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT + BOOST_RANGE_CONCEPT_ASSERT((range_detail::ForwardIteratorConcept)); + BOOST_RANGE_CONCEPT_ASSERT((range_detail::ForwardIteratorConcept)); +#endif + }; + + template + struct WriteableRangeConcept + { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator; + + BOOST_CONCEPT_USAGE(WriteableRangeConcept) + { + *i = v; + } + private: + iterator i; + BOOST_DEDUCED_TYPENAME range_value::type v; +#endif + }; + + //! Check if a type T models the WriteableForwardRange range concept. + template + struct WriteableForwardRangeConcept + : ForwardRangeConcept + , WriteableRangeConcept + { + }; + + //! Check if a type T models the BidirectionalRange range concept. + template + struct BidirectionalRangeConcept : ForwardRangeConcept + { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT + BOOST_RANGE_CONCEPT_ASSERT((range_detail::BidirectionalIteratorConcept)); + BOOST_RANGE_CONCEPT_ASSERT((range_detail::BidirectionalIteratorConcept)); +#endif + }; + + //! Check if a type T models the WriteableBidirectionalRange range concept. + template + struct WriteableBidirectionalRangeConcept + : BidirectionalRangeConcept + , WriteableRangeConcept + { + }; + + //! Check if a type T models the RandomAccessRange range concept. + template + struct RandomAccessRangeConcept : BidirectionalRangeConcept + { +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT + BOOST_RANGE_CONCEPT_ASSERT((range_detail::RandomAccessIteratorConcept)); + BOOST_RANGE_CONCEPT_ASSERT((range_detail::RandomAccessIteratorConcept)); +#endif + }; + + //! Check if a type T models the WriteableRandomAccessRange range concept. + template + struct WriteableRandomAccessRangeConcept + : RandomAccessRangeConcept + , WriteableRangeConcept + { + }; + +} // namespace boost + +#endif // BOOST_RANGE_CONCEPTS_HPP diff --git a/libs/range/include/boost/range/config.hpp b/libs/range/include/boost/range/config.hpp new file mode 100644 index 00000000..636df7be --- /dev/null +++ b/libs/range/include/boost/range/config.hpp @@ -0,0 +1,56 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_CONFIG_HPP +#define BOOST_RANGE_CONFIG_HPP + +#include + +#if defined(_MSC_VER) +# pragma once +#endif + +#include + +#ifdef BOOST_RANGE_DEDUCED_TYPENAME +#error "macro already defined!" +#endif + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# define BOOST_RANGE_DEDUCED_TYPENAME typename +#else +#define BOOST_RANGE_DEDUCED_TYPENAME BOOST_DEDUCED_TYPENAME +#endif + +#ifdef BOOST_RANGE_NO_ARRAY_SUPPORT +#error "macro already defined!" +#endif + +#if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 ) +#define BOOST_RANGE_NO_ARRAY_SUPPORT 1 +#endif + +#ifdef BOOST_RANGE_NO_ARRAY_SUPPORT +#define BOOST_RANGE_ARRAY_REF() (boost_range_array) +#define BOOST_RANGE_NO_STATIC_ASSERT +#else +#define BOOST_RANGE_ARRAY_REF() (&boost_range_array) +#endif + +#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))) +# define BOOST_RANGE_UNUSED __attribute__((unused)) +#else +# define BOOST_RANGE_UNUSED +#endif + + + +#endif + diff --git a/libs/range/include/boost/range/const_iterator.hpp b/libs/range/include/boost/range/const_iterator.hpp new file mode 100644 index 00000000..727fdad0 --- /dev/null +++ b/libs/range/include/boost/range/const_iterator.hpp @@ -0,0 +1,76 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_CONST_ITERATOR_HPP +#define BOOST_RANGE_CONST_ITERATOR_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + ////////////////////////////////////////////////////////////////////////// + // default + ////////////////////////////////////////////////////////////////////////// + + namespace range_detail + { + +BOOST_RANGE_EXTRACT_OPTIONAL_TYPE( const_iterator ) + +template< typename C > +struct range_const_iterator_helper + : extract_const_iterator +{}; + +////////////////////////////////////////////////////////////////////////// +// pair +////////////////////////////////////////////////////////////////////////// + +template< typename Iterator > +struct range_const_iterator_helper > +{ + typedef Iterator type; +}; + +////////////////////////////////////////////////////////////////////////// +// array +////////////////////////////////////////////////////////////////////////// + +template< typename T, std::size_t sz > +struct range_const_iterator_helper< T[sz] > +{ + typedef const T* type; +}; + + } // namespace range_detail + +template +struct range_const_iterator + : range_detail::range_const_iterator_helper< + BOOST_DEDUCED_TYPENAME remove_reference::type + > +{ +}; + +} // namespace boost + + +#endif diff --git a/libs/range/include/boost/range/const_reverse_iterator.hpp b/libs/range/include/boost/range/const_reverse_iterator.hpp new file mode 100644 index 00000000..a0c3de9a --- /dev/null +++ b/libs/range/include/boost/range/const_reverse_iterator.hpp @@ -0,0 +1,39 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_CONST_REVERSE_ITERATOR_HPP +#define BOOST_RANGE_CONST_REVERSE_ITERATOR_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include + +BOOST_HEADER_DEPRECATED("") + +#include +#include + +namespace boost +{ + // + // This interface is deprecated, use range_reverse_iterator + // + + template< typename C > + struct range_const_reverse_iterator + : range_reverse_iterator< + const BOOST_DEDUCED_TYPENAME remove_reference::type> + { }; + +} // namespace boost + +#endif diff --git a/libs/range/include/boost/range/counting_range.hpp b/libs/range/include/boost/range/counting_range.hpp new file mode 100644 index 00000000..d886a213 --- /dev/null +++ b/libs/range/include/boost/range/counting_range.hpp @@ -0,0 +1,76 @@ +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_COUNTING_RANGE_HPP_INCLUDED +#define BOOST_RANGE_COUNTING_RANGE_HPP_INCLUDED + +#include +#if BOOST_MSVC >= 1400 +#pragma warning(push) +#pragma warning(disable : 4244) +#endif + +#include +#include +#include +#include + +namespace boost +{ + template + inline iterator_range > + counting_range(Value first, Value last) + { + typedef counting_iterator counting_iterator_t; + typedef iterator_range result_t; + return result_t(counting_iterator_t(first), + counting_iterator_t(last)); + } + + template + inline iterator_range< + counting_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type + > + > + counting_range(const Range& rng) + { + typedef counting_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type + > counting_iterator_t; + + typedef iterator_range result_t; + + return result_t(counting_iterator_t(boost::begin(rng)), + counting_iterator_t(boost::end(rng))); + } + + template + inline iterator_range< + counting_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type + > + > + counting_range(Range& rng) + { + typedef counting_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type + > counting_iterator_t; + + typedef iterator_range result_t; + + return result_t(counting_iterator_t(boost::begin(rng)), + counting_iterator_t(boost::end(rng))); + } +} // namespace boost + +#if BOOST_MSVC >= 1400 +#pragma warning(pop) +#endif + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/any_iterator.hpp b/libs/range/include/boost/range/detail/any_iterator.hpp new file mode 100644 index 00000000..044237c5 --- /dev/null +++ b/libs/range/include/boost/range/detail/any_iterator.hpp @@ -0,0 +1,589 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_ANY_ITERATOR_HPP_INCLUDED +#define BOOST_RANGE_DETAIL_ANY_ITERATOR_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + // metafunction to determine if T is a const reference + template + struct is_const_reference + { + typedef typename mpl::and_< + typename is_reference::type, + typename is_const< + typename remove_reference::type + >::type + >::type type; + }; + + // metafunction to determine if T is a mutable reference + template + struct is_mutable_reference + { + typedef typename mpl::and_< + typename is_reference::type, + typename mpl::not_< + typename is_const< + typename remove_reference::type + >::type + >::type + >::type type; + }; + + // metafunction to evaluate if a source 'reference' can be + // converted to a target 'reference' as a value. + // + // This is true, when the target reference type is actually + // not a reference, and the source reference is convertible + // to the target type. + template + struct is_convertible_to_value_as_reference + { + typedef typename mpl::and_< + typename mpl::not_< + typename is_reference::type + >::type + , typename is_convertible< + SourceReference + , TargetReference + >::type + >::type type; + }; + + template< + class Value + , class Traversal + , class Reference + , class Difference + , class Buffer = any_iterator_default_buffer + > + class any_iterator; + + // metafunction to determine if SomeIterator is an + // any_iterator. + // + // This is the general implementation which evaluates to false. + template + struct is_any_iterator + : mpl::bool_ + { + }; + + // specialization of is_any_iterator to return true for + // any_iterator classes regardless of template parameters. + template< + class Value + , class Traversal + , class Reference + , class Difference + , class Buffer + > + struct is_any_iterator< + any_iterator< + Value + , Traversal + , Reference + , Difference + , Buffer + > + > + : mpl::bool_ + { + }; + } // namespace range_detail + + namespace iterators + { + namespace detail + { + // Rationale: + // These are specialized since the iterator_facade versions lack + // the requisite typedefs to allow wrapping to determine the types + // if a user copy constructs from a postfix increment. + + template< + class Value + , class Traversal + , class Reference + , class Difference + , class Buffer + > + class postfix_increment_proxy< + range_detail::any_iterator< + Value + , Traversal + , Reference + , Difference + , Buffer + > + > + { + typedef range_detail::any_iterator< + Value + , Traversal + , Reference + , Difference + , Buffer + > any_iterator_type; + + public: + typedef Value value_type; + typedef typename std::iterator_traits::iterator_category iterator_category; + typedef Difference difference_type; + typedef typename iterator_pointer::type pointer; + typedef Reference reference; + + explicit postfix_increment_proxy(any_iterator_type const& x) + : stored_value(*x) + {} + + value_type& + operator*() const + { + return this->stored_value; + } + private: + mutable value_type stored_value; + }; + + template< + class Value + , class Traversal + , class Reference + , class Difference + , class Buffer + > + class writable_postfix_increment_proxy< + range_detail::any_iterator< + Value + , Traversal + , Reference + , Difference + , Buffer + > + > + { + typedef range_detail::any_iterator< + Value + , Traversal + , Reference + , Difference + , Buffer + > any_iterator_type; + public: + typedef Value value_type; + typedef typename std::iterator_traits::iterator_category iterator_category; + typedef Difference difference_type; + typedef typename iterator_pointer::type pointer; + typedef Reference reference; + + explicit writable_postfix_increment_proxy(any_iterator_type const& x) + : stored_value(*x) + , stored_iterator(x) + {} + + // Dereferencing must return a proxy so that both *r++ = o and + // value_type(*r++) can work. In this case, *r is the same as + // *r++, and the conversion operator below is used to ensure + // readability. + writable_postfix_increment_proxy const& + operator*() const + { + return *this; + } + + // Provides readability of *r++ + operator value_type&() const + { + return stored_value; + } + + // Provides writability of *r++ + template + T const& operator=(T const& x) const + { + *this->stored_iterator = x; + return x; + } + + // This overload just in case only non-const objects are writable + template + T& operator=(T& x) const + { + *this->stored_iterator = x; + return x; + } + + // Provides X(r++) + operator any_iterator_type const&() const + { + return stored_iterator; + } + + private: + mutable value_type stored_value; + any_iterator_type stored_iterator; + }; + + } //namespace detail + } //namespace iterators + + namespace range_detail + { + template< + class Value + , class Traversal + , class Reference + , class Difference + , class Buffer + > + class any_iterator + : public iterator_facade< + any_iterator< + Value + , Traversal + , Reference + , Difference + , Buffer + > + , Value + , Traversal + , Reference + , Difference + > + { + template< + class OtherValue + , class OtherTraversal + , class OtherReference + , class OtherDifference + , class OtherBuffer + > + friend class any_iterator; + + struct enabler {}; + struct disabler {}; + + typedef typename any_iterator_interface_type_generator< + Traversal + , Reference + , Difference + , Buffer + >::type abstract_base_type; + + typedef iterator_facade< + any_iterator< + Value + , Traversal + , Reference + , Difference + , Buffer + > + , Value + , Traversal + , Reference + , Difference + > base_type; + + typedef Buffer buffer_type; + + public: + typedef typename base_type::value_type value_type; + typedef typename base_type::reference reference; + typedef typename base_type::difference_type difference_type; + + // Default constructor + any_iterator() + : m_impl(0) {} + + // Simple copy construction without conversion + any_iterator(const any_iterator& other) + : base_type(other) + , m_impl(other.m_impl + ? other.m_impl->clone(m_buffer) + : 0) + { + } + + // Simple assignment operator without conversion + any_iterator& operator=(const any_iterator& other) + { + if (this != &other) + { + if (m_impl) + m_impl->~abstract_base_type(); + m_buffer.deallocate(); + m_impl = 0; + if (other.m_impl) + m_impl = other.m_impl->clone(m_buffer); + } + return *this; + } + + // Implicit conversion from another any_iterator where the + // conversion is from a non-const reference to a const reference + template< + class OtherValue + , class OtherTraversal + , class OtherReference + , class OtherDifference + > + any_iterator(const any_iterator< + OtherValue, + OtherTraversal, + OtherReference, + OtherDifference, + Buffer + >& other, + typename ::boost::enable_if< + typename mpl::and_< + typename is_mutable_reference::type, + typename is_const_reference::type + >::type, + enabler + >::type* = 0 + ) + : m_impl(other.m_impl + ? other.m_impl->clone_const_ref(m_buffer) + : 0 + ) + { + } + + // Implicit conversion from another any_iterator where the + // reference types of the source and the target are references + // that are either both const, or both non-const. + template< + class OtherValue + , class OtherTraversal + , class OtherReference + , class OtherDifference + > + any_iterator(const any_iterator< + OtherValue + , OtherTraversal + , OtherReference + , OtherDifference + , Buffer + >& other, + typename ::boost::enable_if< + typename mpl::or_< + typename mpl::and_< + typename is_mutable_reference::type, + typename is_mutable_reference::type + >::type, + typename mpl::and_< + typename is_const_reference::type, + typename is_const_reference::type + >::type + >::type, + enabler + >::type* = 0 + ) + : m_impl(other.m_impl + ? other.m_impl->clone(m_buffer) + : 0 + ) + { + } + + // Implicit conversion to an any_iterator that uses a value for + // the reference type. + template< + class OtherValue + , class OtherTraversal + , class OtherReference + , class OtherDifference + > + any_iterator(const any_iterator< + OtherValue + , OtherTraversal + , OtherReference + , OtherDifference + , Buffer + >& other, + typename ::boost::enable_if< + typename is_convertible_to_value_as_reference< + OtherReference + , Reference + >::type, + enabler + >::type* = 0 + ) + : m_impl(other.m_impl + ? other.m_impl->clone_reference_as_value(m_buffer) + : 0 + ) + { + } + + any_iterator clone() const + { + any_iterator result; + if (m_impl) + result.m_impl = m_impl->clone(result.m_buffer); + return result; + } + + any_iterator< + Value + , Traversal + , typename abstract_base_type::const_reference + , Difference + , Buffer + > + clone_const_ref() const + { + typedef any_iterator< + Value + , Traversal + , typename abstract_base_type::const_reference + , Difference + , Buffer + > result_type; + + result_type result; + + if (m_impl) + result.m_impl = m_impl->clone_const_ref(result.m_buffer); + + return result; + } + + // implicit conversion and construction from type-erasure-compatible + // iterators + template + explicit any_iterator( + const WrappedIterator& wrapped_iterator, + typename disable_if< + typename is_any_iterator::type + , disabler + >::type* = 0 + ) + { + typedef typename any_iterator_wrapper_type_generator< + WrappedIterator + , Traversal + , Reference + , Difference + , Buffer + >::type wrapper_type; + + void* ptr = m_buffer.allocate(sizeof(wrapper_type)); + m_impl = new(ptr) wrapper_type(wrapped_iterator); + } + + ~any_iterator() + { + // manually run the destructor, the deallocation is automatically + // handled by the any_iterator_small_buffer base class. + if (m_impl) + m_impl->~abstract_base_type(); + } + + private: + friend class ::boost::iterator_core_access; + + Reference dereference() const + { + BOOST_ASSERT( m_impl ); + return m_impl->dereference(); + } + + bool equal(const any_iterator& other) const + { + return (m_impl == other.m_impl) + || (m_impl && other.m_impl && m_impl->equal(*other.m_impl)); + } + + void increment() + { + BOOST_ASSERT( m_impl ); + m_impl->increment(); + } + + void decrement() + { + BOOST_ASSERT( m_impl ); + m_impl->decrement(); + } + + Difference distance_to(const any_iterator& other) const + { + return m_impl && other.m_impl + ? m_impl->distance_to(*other.m_impl) + : 0; + } + + void advance(Difference offset) + { + BOOST_ASSERT( m_impl ); + m_impl->advance(offset); + } + + any_iterator& swap(any_iterator& other) + { + BOOST_ASSERT( this != &other ); + // grab a temporary copy of the other iterator + any_iterator tmp(other); + + // deallocate the other iterator, taking care to obey the + // class-invariants in-case of exceptions later + if (other.m_impl) + { + other.m_impl->~abstract_base_type(); + other.m_buffer.deallocate(); + other.m_impl = 0; + } + + // If this is a non-null iterator then we need to put + // a clone of this iterators implementation into the other + // iterator. + // We can't just swap because of the small buffer optimization. + if (m_impl) + { + other.m_impl = m_impl->clone(other.m_buffer); + m_impl->~abstract_base_type(); + m_buffer.deallocate(); + m_impl = 0; + } + + // assign to this instance a clone of the temporarily held + // tmp which represents the input other parameter at the + // start of execution of this function. + if (tmp.m_impl) + m_impl = tmp.m_impl->clone(m_buffer); + + return *this; + } + + buffer_type m_buffer; + abstract_base_type* m_impl; + }; + + } // namespace range_detail +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/any_iterator_buffer.hpp b/libs/range/include/boost/range/detail/any_iterator_buffer.hpp new file mode 100644 index 00000000..2bb5d53a --- /dev/null +++ b/libs/range/include/boost/range/detail/any_iterator_buffer.hpp @@ -0,0 +1,117 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_ANY_ITERATOR_BUFFER_HPP_INCLUDED +#define BOOST_RANGE_DETAIL_ANY_ITERATOR_BUFFER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace boost +{ + template + class any_iterator_buffer + : noncopyable + { + BOOST_STATIC_ASSERT(( StackBufferSize > 0 )); + public: + any_iterator_buffer() + : m_ptr() + { + } + + ~any_iterator_buffer() + { + delete [] m_ptr; + } + + void* allocate(std::size_t bytes) + { + BOOST_ASSERT( !m_ptr ); + if (bytes <= StackBufferSize) + return m_buffer.data(); + + m_ptr = new char[bytes]; + return m_ptr; + } + + void deallocate() + { + delete [] m_ptr; + m_ptr = 0; + } + + private: + // Rationale: + // Do not use inheritance from noncopyable because this causes + // the concepts to erroneous detect the derived any_iterator + // as noncopyable. + any_iterator_buffer(const any_iterator_buffer&); + void operator=(const any_iterator_buffer&); + + char* m_ptr; + boost::array m_buffer; + }; + + class any_iterator_heap_only_buffer + : noncopyable + { + public: + any_iterator_heap_only_buffer() + : m_ptr() + { + } + + ~any_iterator_heap_only_buffer() + { + delete [] m_ptr; + } + + void* allocate(std::size_t bytes) + { + BOOST_ASSERT( !m_ptr ); + m_ptr = new char[bytes]; + return m_ptr; + } + + void deallocate() + { + delete [] m_ptr; + m_ptr = 0; + } + + private: + char* m_ptr; + }; + + template + class any_iterator_stack_only_buffer + { + BOOST_STATIC_ASSERT(( StackBufferSize > 0 )); + public: + void* allocate(std::size_t bytes) + { + BOOST_ASSERT( bytes <= m_buffer.size() ); + return m_buffer.data(); + } + + void deallocate() + { + } + + private: + boost::array m_buffer; + }; + + typedef any_iterator_buffer<64> any_iterator_default_buffer; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/any_iterator_interface.hpp b/libs/range/include/boost/range/detail/any_iterator_interface.hpp new file mode 100644 index 00000000..15858050 --- /dev/null +++ b/libs/range/include/boost/range/detail/any_iterator_interface.hpp @@ -0,0 +1,273 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_ANY_ITERATOR_INTERFACE_HPP_INCLUDED +#define BOOST_RANGE_DETAIL_ANY_ITERATOR_INTERFACE_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + template + struct const_reference_type_generator + { + typedef typename mpl::if_< + typename is_reference::type, + typename add_const< + typename remove_reference::type + >::type&, + T + >::type type; + }; + + template + struct reference_as_value_type_generator + { + typedef typename remove_reference< + typename remove_const::type + >::type value_type; + + typedef typename mpl::if_< + typename is_convertible::type, + value_type, + T + >::type type; + }; + + template< + class Reference + , class Buffer + > + struct any_incrementable_iterator_interface + { + typedef Reference reference; + typedef typename const_reference_type_generator< + Reference + >::type const_reference; + typedef typename reference_as_value_type_generator< + Reference + >::type reference_as_value_type; + + typedef Buffer buffer_type; + + virtual ~any_incrementable_iterator_interface() {} + + virtual any_incrementable_iterator_interface* + clone(buffer_type& buffer) const = 0; + + virtual any_incrementable_iterator_interface* + clone_const_ref(buffer_type& buffer) const = 0; + + virtual any_incrementable_iterator_interface* + clone_reference_as_value(buffer_type& buffer) const = 0; + + virtual void increment() = 0; + }; + + template< + class Reference + , class Buffer + > + struct any_single_pass_iterator_interface + : any_incrementable_iterator_interface + { + typedef typename any_incrementable_iterator_interface::reference reference; + typedef typename any_incrementable_iterator_interface::const_reference const_reference; + typedef typename any_incrementable_iterator_interface::buffer_type buffer_type; + typedef typename any_incrementable_iterator_interface::reference_as_value_type reference_as_value_type; + + virtual any_single_pass_iterator_interface* + clone(buffer_type& buffer) const = 0; + + virtual any_single_pass_iterator_interface* + clone_const_ref(buffer_type& buffer) const = 0; + + virtual any_single_pass_iterator_interface* + clone_reference_as_value(buffer_type& buffer) const = 0; + + virtual reference dereference() const = 0; + + virtual bool equal(const any_single_pass_iterator_interface& other) const = 0; + }; + + template< + class Reference + , class Buffer + > + struct any_forward_iterator_interface + : any_single_pass_iterator_interface + { + typedef typename any_single_pass_iterator_interface::reference reference; + typedef typename any_single_pass_iterator_interface::const_reference const_reference; + typedef typename any_single_pass_iterator_interface::buffer_type buffer_type; + typedef typename any_single_pass_iterator_interface::reference_as_value_type reference_as_value_type; + + virtual any_forward_iterator_interface* + clone(buffer_type& buffer) const = 0; + + virtual any_forward_iterator_interface* + clone_const_ref(buffer_type& buffer) const = 0; + + virtual any_forward_iterator_interface* + clone_reference_as_value(buffer_type& buffer) const = 0; + }; + + template< + class Reference + , class Buffer + > + struct any_bidirectional_iterator_interface + : any_forward_iterator_interface + { + typedef typename any_forward_iterator_interface::reference reference; + typedef typename any_forward_iterator_interface::const_reference const_reference; + typedef typename any_forward_iterator_interface::buffer_type buffer_type; + typedef typename any_forward_iterator_interface::reference_as_value_type reference_as_value_type; + + virtual any_bidirectional_iterator_interface* + clone(buffer_type& buffer) const = 0; + + virtual any_bidirectional_iterator_interface* + clone_const_ref(buffer_type& buffer) const = 0; + + virtual any_bidirectional_iterator_interface* + clone_reference_as_value(buffer_type& buffer) const = 0; + + virtual void decrement() = 0; + }; + + template< + class Reference + , class Difference + , class Buffer + > + struct any_random_access_iterator_interface + : any_bidirectional_iterator_interface< + Reference + , Buffer + > + { + typedef typename any_bidirectional_iterator_interface::reference reference; + typedef typename any_bidirectional_iterator_interface::const_reference const_reference; + typedef typename any_bidirectional_iterator_interface::buffer_type buffer_type; + typedef typename any_bidirectional_iterator_interface::reference_as_value_type reference_as_value_type; + typedef Difference difference_type; + + virtual any_random_access_iterator_interface* + clone(buffer_type& buffer) const = 0; + + virtual any_random_access_iterator_interface* + clone_const_ref(buffer_type& buffer) const = 0; + + virtual any_random_access_iterator_interface* + clone_reference_as_value(buffer_type& buffer) const = 0; + + virtual void advance(Difference offset) = 0; + + virtual Difference distance_to(const any_random_access_iterator_interface& other) const = 0; + }; + + template< + class Traversal + , class Reference + , class Difference + , class Buffer + > + struct any_iterator_interface_type_generator; + + template< + class Reference + , class Difference + , class Buffer + > + struct any_iterator_interface_type_generator< + incrementable_traversal_tag + , Reference + , Difference + , Buffer + > + { + typedef any_incrementable_iterator_interface type; + }; + + template< + class Reference + , class Difference + , class Buffer + > + struct any_iterator_interface_type_generator< + single_pass_traversal_tag + , Reference + , Difference + , Buffer + > + { + typedef any_single_pass_iterator_interface type; + }; + + template< + class Reference + , class Difference + , class Buffer + > + struct any_iterator_interface_type_generator< + forward_traversal_tag + , Reference + , Difference + , Buffer + > + { + typedef any_forward_iterator_interface type; + }; + + template< + class Reference + , class Difference + , class Buffer + > + struct any_iterator_interface_type_generator< + bidirectional_traversal_tag + , Reference + , Difference + , Buffer + > + { + typedef any_bidirectional_iterator_interface type; + }; + + template< + class Reference + , class Difference + , class Buffer + > + struct any_iterator_interface_type_generator< + random_access_traversal_tag + , Reference + , Difference + , Buffer + > + { + typedef any_random_access_iterator_interface< + Reference + , Difference + , Buffer + > type; + }; + + } // namespace range_detail +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/any_iterator_wrapper.hpp b/libs/range/include/boost/range/detail/any_iterator_wrapper.hpp new file mode 100644 index 00000000..bcd9b7f8 --- /dev/null +++ b/libs/range/include/boost/range/detail/any_iterator_wrapper.hpp @@ -0,0 +1,640 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_ANY_ITERATOR_WRAPPER_HPP_INCLUDED +#define BOOST_RANGE_DETAIL_ANY_ITERATOR_WRAPPER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + template + TargetT& polymorphic_ref_downcast(SourceT& source) + { +#ifdef BOOST_NO_RTTI + return static_cast(source); +#else + return *boost::polymorphic_downcast(&source); +#endif + } + + template + Reference dereference_cast(T& x) + { + return static_cast(x); + } + template + Reference dereference_cast(const T& x) + { + return static_cast(const_cast(x)); + } + + template< + class WrappedIterator + , class Reference + , class Buffer + > + class any_incrementable_iterator_wrapper + : public any_incrementable_iterator_interface< + Reference + , Buffer + > + { + BOOST_RANGE_CONCEPT_ASSERT(( IncrementableIteratorConcept )); + public: + typedef WrappedIterator wrapped_type; + + BOOST_STATIC_ASSERT(( is_convertible< + typename iterator_reference::type + , Reference + >::value )); + + any_incrementable_iterator_wrapper() + : m_it() + {} + + explicit any_incrementable_iterator_wrapper(wrapped_type it) + : m_it(it) + {} + + // any_incrementable_iterator implementation + virtual any_incrementable_iterator_wrapper* clone( + typename any_incrementable_iterator_wrapper::buffer_type& buffer + ) const + { + return new (buffer.allocate(sizeof(*this))) + any_incrementable_iterator_wrapper(m_it); + } + + virtual any_incrementable_iterator_wrapper< + WrappedIterator + , typename any_incrementable_iterator_wrapper::const_reference + , Buffer + >* clone_const_ref( + typename any_incrementable_iterator_wrapper::buffer_type& buffer + ) const + { + typedef any_incrementable_iterator_wrapper< + WrappedIterator + , typename any_incrementable_iterator_wrapper::const_reference + , Buffer + > result_type; + + return new (buffer.allocate(sizeof(result_type))) + result_type(m_it); + } + + virtual any_incrementable_iterator_wrapper< + WrappedIterator + , typename any_incrementable_iterator_wrapper::reference_as_value_type + , Buffer + >* clone_reference_as_value( + typename any_incrementable_iterator_wrapper::buffer_type& buffer + ) const + { + typedef any_incrementable_iterator_wrapper< + WrappedIterator + , typename any_incrementable_iterator_wrapper::reference_as_value_type + , Buffer + > result_type; + + return new (buffer.allocate(sizeof(result_type))) + result_type(m_it); + } + + virtual void increment() + { + ++m_it; + } + + private: + wrapped_type m_it; + }; + + template< + class WrappedIterator + , class Reference + , class Buffer + > + class any_single_pass_iterator_wrapper + : public any_single_pass_iterator_interface< + Reference + , Buffer + > + { + struct disabler {}; + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassIteratorConcept )); + typedef any_single_pass_iterator_interface< + Reference, + Buffer + > base_type; + + public: + typedef typename base_type::reference reference; + + any_single_pass_iterator_wrapper() + : m_it() + {} + + explicit any_single_pass_iterator_wrapper(const WrappedIterator& it) + : m_it(it) + {} + // any_single_pass_iterator_interface implementation + virtual any_single_pass_iterator_wrapper* clone( + typename any_single_pass_iterator_wrapper::buffer_type& buffer + ) const + { + return new (buffer.allocate(sizeof(*this))) + any_single_pass_iterator_wrapper(m_it); + } + + virtual any_single_pass_iterator_wrapper< + WrappedIterator + , typename any_single_pass_iterator_wrapper::const_reference + , Buffer + >* clone_const_ref( + typename any_single_pass_iterator_wrapper::buffer_type& buffer + ) const + { + typedef any_single_pass_iterator_wrapper< + WrappedIterator + , typename any_single_pass_iterator_wrapper::const_reference + , Buffer + > result_type; + + return new (buffer.allocate(sizeof(result_type))) + result_type(m_it); + } + + virtual any_single_pass_iterator_wrapper< + WrappedIterator + , typename any_single_pass_iterator_wrapper::reference_as_value_type + , Buffer + >* clone_reference_as_value( + typename any_single_pass_iterator_wrapper::buffer_type& buffer + ) const + { + typedef any_single_pass_iterator_wrapper< + WrappedIterator + , typename any_single_pass_iterator_wrapper::reference_as_value_type + , Buffer + > result_type; + + return new (buffer.allocate(sizeof(result_type))) + result_type(m_it); + } + + virtual void increment() + { + ++m_it; + } + + virtual bool equal(const any_single_pass_iterator_interface& other) const + { + return m_it == range_detail::polymorphic_ref_downcast(other).m_it; + } + + virtual reference dereference() const + { + return dereference_cast(*m_it); + } + + private: + WrappedIterator m_it; + }; + + template< + class WrappedIterator + , class Reference + , class Buffer + > + class any_forward_iterator_wrapper + : public any_forward_iterator_interface< + Reference + , Buffer + > + { + BOOST_RANGE_CONCEPT_ASSERT(( ForwardIteratorConcept )); + typedef any_forward_iterator_interface< + Reference, + Buffer + > base_type; + + public: + typedef typename base_type::reference reference; + + any_forward_iterator_wrapper() + : m_it() + {} + + explicit any_forward_iterator_wrapper(const WrappedIterator& it) + : m_it(it) + {} + + // any_forward_iterator_interface implementation + virtual any_forward_iterator_wrapper* clone( + typename any_forward_iterator_wrapper::buffer_type& buffer + ) const + { + return new (buffer.allocate(sizeof(*this))) + any_forward_iterator_wrapper(m_it); + } + + virtual any_forward_iterator_wrapper< + WrappedIterator + , typename any_forward_iterator_wrapper::const_reference + , Buffer + >* clone_const_ref( + typename any_forward_iterator_wrapper::buffer_type& buffer + ) const + { + typedef any_forward_iterator_wrapper< + WrappedIterator + , typename any_forward_iterator_wrapper::const_reference + , Buffer + > result_type; + + return new (buffer.allocate(sizeof(result_type))) + result_type(m_it); + } + + virtual any_forward_iterator_wrapper< + WrappedIterator + , typename any_forward_iterator_wrapper::reference_as_value_type + , Buffer + >* clone_reference_as_value( + typename any_forward_iterator_wrapper::buffer_type& buffer + ) const + { + typedef any_forward_iterator_wrapper< + WrappedIterator + , typename any_forward_iterator_wrapper::reference_as_value_type + , Buffer + > result_type; + + return new (buffer.allocate(sizeof(result_type))) + result_type(m_it); + } + + virtual void increment() + { + ++m_it; + } + + virtual bool equal(const any_single_pass_iterator_interface& other) const + { + return m_it == range_detail::polymorphic_ref_downcast(other).m_it; + } + + virtual reference dereference() const + { + return dereference_cast(*m_it); + } + private: + WrappedIterator m_it; + }; + + template< + class WrappedIterator + , class Reference + , class Buffer + > + class any_bidirectional_iterator_wrapper + : public any_bidirectional_iterator_interface< + Reference + , Buffer + > + { + BOOST_RANGE_CONCEPT_ASSERT(( BidirectionalIteratorConcept )); + typedef any_bidirectional_iterator_interface< + Reference, + Buffer + > base_type; + + public: + typedef typename base_type::reference reference; + + any_bidirectional_iterator_wrapper() + : m_it() + { + } + + explicit any_bidirectional_iterator_wrapper(const WrappedIterator& it) + : m_it(it) + { + } + + virtual any_bidirectional_iterator_wrapper* clone( + typename any_bidirectional_iterator_wrapper::buffer_type& buffer + ) const + { + return new (buffer.allocate(sizeof(*this))) + any_bidirectional_iterator_wrapper(*this); + } + + virtual any_bidirectional_iterator_wrapper< + WrappedIterator + , typename any_bidirectional_iterator_wrapper::const_reference + , Buffer + >* clone_const_ref( + typename any_bidirectional_iterator_wrapper::buffer_type& buffer + ) const + { + typedef any_bidirectional_iterator_wrapper< + WrappedIterator + , typename any_bidirectional_iterator_wrapper::const_reference + , Buffer + > result_type; + + return new (buffer.allocate(sizeof(result_type))) + result_type(m_it); + } + + virtual any_bidirectional_iterator_wrapper< + WrappedIterator + , typename any_bidirectional_iterator_wrapper::reference_as_value_type + , Buffer + >* clone_reference_as_value( + typename any_bidirectional_iterator_wrapper::buffer_type& buffer + ) const + { + typedef any_bidirectional_iterator_wrapper< + WrappedIterator + , typename any_bidirectional_iterator_wrapper::reference_as_value_type + , Buffer + > result_type; + + return new (buffer.allocate(sizeof(result_type))) + result_type(m_it); + } + + virtual void increment() + { + ++m_it; + } + + virtual void decrement() + { + --m_it; + } + + virtual bool equal(const any_single_pass_iterator_interface& other) const + { + return m_it == range_detail::polymorphic_ref_downcast(other).m_it; + } + + virtual reference dereference() const + { + return dereference_cast(*m_it); + } + + private: + WrappedIterator m_it; + }; + + template< + class WrappedIterator + , class Reference + , class Difference + , class Buffer + > + class any_random_access_iterator_wrapper + : public any_random_access_iterator_interface< + Reference + , Difference + , Buffer + > + { + BOOST_RANGE_CONCEPT_ASSERT(( RandomAccessIteratorConcept )); + typedef any_random_access_iterator_interface< + Reference, + Difference, + Buffer + > base_type; + + public: + typedef typename base_type::reference reference; + typedef Difference difference_type; + + any_random_access_iterator_wrapper() + : m_it() + { + } + + explicit any_random_access_iterator_wrapper(const WrappedIterator& other) + : m_it(other) + { + } + + virtual any_random_access_iterator_wrapper* clone( + typename any_random_access_iterator_wrapper::buffer_type& buffer + ) const + { + return new (buffer.allocate(sizeof(*this))) + any_random_access_iterator_wrapper(*this); + } + + virtual any_random_access_iterator_wrapper< + WrappedIterator + , typename any_random_access_iterator_wrapper::const_reference + , Difference + , Buffer + >* clone_const_ref( + typename any_random_access_iterator_wrapper::buffer_type& buffer + ) const + { + typedef any_random_access_iterator_wrapper< + WrappedIterator + , typename any_random_access_iterator_wrapper::const_reference + , Difference + , Buffer + > result_type; + + return new (buffer.allocate(sizeof(result_type))) + result_type(m_it); + } + + virtual any_random_access_iterator_wrapper< + WrappedIterator + , typename any_random_access_iterator_wrapper::reference_as_value_type + , Difference + , Buffer + >* clone_reference_as_value( + typename any_random_access_iterator_wrapper::buffer_type& buffer + ) const + { + typedef any_random_access_iterator_wrapper< + WrappedIterator + , typename any_random_access_iterator_wrapper::reference_as_value_type + , Difference + , Buffer + > result_type; + + return new (buffer.allocate(sizeof(result_type))) + result_type(m_it); + } + + virtual void increment() + { + ++m_it; + } + + virtual bool equal(const any_single_pass_iterator_interface& other) const + { + return m_it == range_detail::polymorphic_ref_downcast(other).m_it; + } + + virtual void decrement() + { + --m_it; + } + + virtual void advance(Difference offset) + { + m_it += offset; + } + + virtual reference dereference() const + { + return dereference_cast(*m_it); + } + + virtual Difference distance_to(const any_random_access_iterator_interface& other) const + { + return range_detail::polymorphic_ref_downcast(other).m_it - m_it; + } + + private: + WrappedIterator m_it; + }; + + template< + class WrappedIterator + , class Traversal + , class Reference + , class Difference + , class Buffer + > + struct any_iterator_wrapper_type_generator; + + template< + class WrappedIterator + , class Reference + , class Difference + , class Buffer + > + struct any_iterator_wrapper_type_generator< + WrappedIterator + , incrementable_traversal_tag + , Reference + , Difference + , Buffer + > + { + typedef any_incrementable_iterator_wrapper< + WrappedIterator + , Reference + , Buffer + > type; + }; + + template< + class WrappedIterator + , class Reference + , class Difference + , class Buffer + > + struct any_iterator_wrapper_type_generator< + WrappedIterator + , single_pass_traversal_tag + , Reference + , Difference + , Buffer + > + { + typedef any_single_pass_iterator_wrapper< + WrappedIterator + , Reference + , Buffer + > type; + }; + + template< + class WrappedIterator + , class Reference + , class Difference + , class Buffer + > + struct any_iterator_wrapper_type_generator< + WrappedIterator + , forward_traversal_tag + , Reference + , Difference + , Buffer + > + { + typedef any_forward_iterator_wrapper< + WrappedIterator + , Reference + , Buffer + > type; + }; + + template< + class WrappedIterator + , class Reference + , class Difference + , class Buffer + > + struct any_iterator_wrapper_type_generator< + WrappedIterator + , bidirectional_traversal_tag + , Reference + , Difference + , Buffer + > + { + typedef any_bidirectional_iterator_wrapper< + WrappedIterator + , Reference + , Buffer + > type; + }; + + template< + class WrappedIterator + , class Reference + , class Difference + , class Buffer + > + struct any_iterator_wrapper_type_generator< + WrappedIterator + , random_access_traversal_tag + , Reference + , Difference + , Buffer + > + { + typedef any_random_access_iterator_wrapper< + WrappedIterator + , Reference + , Difference + , Buffer + > type; + }; + + } // namespace range_detail +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/collection_traits.hpp b/libs/range/include/boost/range/detail/collection_traits.hpp new file mode 100644 index 00000000..75b2b2b8 --- /dev/null +++ b/libs/range/include/boost/range/detail/collection_traits.hpp @@ -0,0 +1,237 @@ +// Boost string_algo library collection_traits.hpp header file -------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to 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) + +// (C) Copyright Thorsten Ottosen 2002-2003. Use, modification and +// distribution is subject to 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) + +// (C) Copyright Jeremy Siek 2001. Use, modification and +// distribution is subject to 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) + +// Original idea of container traits was proposed by Jeremy Siek and +// Thorsten Ottosen. This implementation is lightweighted version +// of container_traits adapter for usage with string_algo library + +#ifndef BOOST_RANGE_STRING_COLLECTION_TRAITS_HPP +#define BOOST_RANGE_STRING_COLLECTION_TRAITS_HPP + +#include +#include +#include + +// Implementation +#include + +/*! \file + Defines collection_traits class and related free-standing functions. + This facility is used to unify the access to different types of collections. + It allows the algorithms in the library to work with STL collections, c-style + array, null-terminated c-strings (and more) using the same interface. +*/ + +namespace boost { + namespace algorithm { + +// collection_traits template class -----------------------------------------// + + //! collection_traits class + /*! + Collection traits provide uniform access to different types of + collections. This functionality allows to write generic algorithms + which work with several different kinds of collections. + + Currently following collection types are supported: + - containers with STL compatible container interface ( see ContainerConcept ) + ( i.e. \c std::vector<>, \c std::list<>, \c std::string<> ... ) + - c-style array + ( \c char[10], \c int[15] ... ) + - null-terminated c-strings + ( \c char*, \c wchar_T* ) + - std::pair of iterators + ( i.e \c std::pair::iterator,vector::iterator> ) + + Collection traits provide an external collection interface operations. + All are accessible using free-standing functions. + + The following operations are supported: + - \c size() + - \c empty() + - \c begin() + - \c end() + + Container traits have somewhat limited functionality on compilers not + supporting partial template specialization and partial template ordering. + */ + template< typename T > + struct collection_traits + { + private: + typedef typename ::boost::mpl::eval_if< + ::boost::algorithm::detail::is_pair, + detail::pair_container_traits_selector, + typename ::boost::mpl::eval_if< + ::boost::is_array, + detail::array_container_traits_selector, + typename ::boost::mpl::eval_if< + ::boost::is_pointer, + detail::pointer_container_traits_selector, + detail::default_container_traits_selector + > + > + >::type container_helper_type; + public: + //! Function type + typedef container_helper_type function_type; + //! Value type + typedef typename + container_helper_type::value_type value_type; + //! Size type + typedef typename + container_helper_type::size_type size_type; + //! Iterator type + typedef typename + container_helper_type::iterator iterator; + //! Const iterator type + typedef typename + container_helper_type::const_iterator const_iterator; + //! Result iterator type ( iterator of const_iterator, depending on the constness of the container ) + typedef typename + container_helper_type::result_iterator result_iterator; + //! Difference type + typedef typename + container_helper_type::difference_type difference_type; + + }; // 'collection_traits' + +// collection_traits metafunctions -----------------------------------------// + + //! Container value_type trait + /*! + Extract the type of elements contained in a container + */ + template< typename C > + struct value_type_of + { + typedef typename collection_traits::value_type type; + }; + + //! Container difference trait + /*! + Extract the container's difference type + */ + template< typename C > + struct difference_type_of + { + typedef typename collection_traits::difference_type type; + }; + + //! Container iterator trait + /*! + Extract the container's iterator type + */ + template< typename C > + struct iterator_of + { + typedef typename collection_traits::iterator type; + }; + + //! Container const_iterator trait + /*! + Extract the container's const_iterator type + */ + template< typename C > + struct const_iterator_of + { + typedef typename collection_traits::const_iterator type; + }; + + + //! Container result_iterator + /*! + Extract the container's result_iterator type. This type maps to \c C::iterator + for mutable container and \c C::const_iterator for const containers. + */ + template< typename C > + struct result_iterator_of + { + typedef typename collection_traits::result_iterator type; + }; + +// collection_traits related functions -----------------------------------------// + + //! Free-standing size() function + /*! + Get the size of the container. Uses collection_traits. + */ + template< typename C > + inline typename collection_traits::size_type + size( const C& c ) + { + return collection_traits::function_type::size( c ); + } + + //! Free-standing empty() function + /*! + Check whether the container is empty. Uses container traits. + */ + template< typename C > + inline bool empty( const C& c ) + { + return collection_traits::function_type::empty( c ); + } + + //! Free-standing begin() function + /*! + Get the begin iterator of the container. Uses collection_traits. + */ + template< typename C > + inline typename collection_traits::iterator + begin( C& c ) + { + return collection_traits::function_type::begin( c ); + } + + //! Free-standing begin() function + /*! + \overload + */ + template< typename C > + inline typename collection_traits::const_iterator + begin( const C& c ) + { + return collection_traits::function_type::begin( c ); + } + + //! Free-standing end() function + /*! + Get the begin iterator of the container. Uses collection_traits. + */ + template< typename C > + inline typename collection_traits::iterator + end( C& c ) + { + return collection_traits::function_type::end( c ); + } + + //! Free-standing end() function + /*! + \overload + */ + template< typename C > + inline typename collection_traits::const_iterator + end( const C& c ) + { + return collection_traits::function_type::end( c ); + } + + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_COLLECTION_TRAITS_HPP diff --git a/libs/range/include/boost/range/detail/collection_traits_detail.hpp b/libs/range/include/boost/range/detail/collection_traits_detail.hpp new file mode 100644 index 00000000..5a3124b5 --- /dev/null +++ b/libs/range/include/boost/range/detail/collection_traits_detail.hpp @@ -0,0 +1,447 @@ +// Boost string_algo library collection_traits.hpp header file -----------------------// + +// Copyright Pavol Droba 2002-2003. Use, modification and +// distribution is subject to 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) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_RANGE_STRING_DETAIL_COLLECTION_TRAITS_HPP +#define BOOST_RANGE_STRING_DETAIL_COLLECTION_TRAITS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Container traits implementation --------------------------------------------------------- + +namespace boost { + namespace algorithm { + namespace detail { + +// Default collection traits ----------------------------------------------------------------- + + // Default collection helper + /* + Wraps std::container compliant containers + */ + template< typename ContainerT > + struct default_container_traits + { + typedef typename ContainerT::value_type value_type; + typedef typename ContainerT::iterator iterator; + typedef typename ContainerT::const_iterator const_iterator; + typedef typename + ::boost::mpl::if_< ::boost::is_const, + const_iterator, + iterator + >::type result_iterator; + typedef typename ContainerT::difference_type difference_type; + typedef typename ContainerT::size_type size_type; + + // static operations + template< typename C > + static size_type size( const C& c ) + { + return c.size(); + } + + template< typename C > + static bool empty( const C& c ) + { + return c.empty(); + } + + template< typename C > + static iterator begin( C& c ) + { + return c.begin(); + } + + template< typename C > + static const_iterator begin( const C& c ) + { + return c.begin(); + } + + template< typename C > + static iterator end( C& c ) + { + return c.end(); + } + + template< typename C > + static const_iterator end( const C& c ) + { + return c.end(); + } + + }; + + template + struct default_container_traits_selector + { + typedef default_container_traits type; + }; + +// Pair container traits --------------------------------------------------------------------- + + typedef double yes_type; + typedef char no_type; + + // pair selector + template< typename T, typename U > + yes_type is_pair_impl( const std::pair* ); + no_type is_pair_impl( ... ); + + template struct is_pair + { + private: + static T* t; + public: + BOOST_STATIC_CONSTANT( bool, value= + sizeof(is_pair_impl(t))==sizeof(yes_type) ); + }; + + // pair helper + template< typename PairT > + struct pair_container_traits + { + typedef typename PairT::first_type element_type; + + typedef typename + std::iterator_traits::value_type value_type; + typedef std::size_t size_type; + typedef typename + std::iterator_traits::difference_type difference_type; + + typedef element_type iterator; + typedef element_type const_iterator; + typedef element_type result_iterator; + + // static operations + template< typename P > + static size_type size( const P& p ) + { + difference_type diff = std::distance( p.first, p.second ); + if ( diff < 0 ) + return 0; + else + return diff; + } + + template< typename P > + static bool empty( const P& p ) + { + return p.first==p.second; + } + + template< typename P > + static const_iterator begin( const P& p ) + { + return p.first; + } + + template< typename P > + static const_iterator end( const P& p ) + { + return p.second; + } + }; // 'pair_container_helper' + + template + struct pair_container_traits_selector + { + typedef pair_container_traits type; + }; + +// Array container traits --------------------------------------------------------------- + + // array traits ( partial specialization ) + template< typename T > + struct array_traits; + + template< typename T, std::size_t sz > + struct array_traits + { + // typedef + typedef T* iterator; + typedef const T* const_iterator; + typedef T value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // size of the array ( static ); + BOOST_STATIC_CONSTANT( size_type, array_size = sz ); + }; + + + // array length resolving + /* + Lenght of string contained in a static array could + be different from the size of the array. + For string processing we need the length without + terminating 0. + + Therefore, the length is calculated for char and wchar_t + using char_traits, rather then simply returning + the array size. + */ + template< typename T > + struct array_length_selector + { + template< typename TraitsT > + struct array_length + { + typedef typename + TraitsT::size_type size_type; + + BOOST_STATIC_CONSTANT( + size_type, + array_size=TraitsT::array_size ); + + template< typename A > + static size_type length( const A& ) + { + return array_size; + } + + template< typename A > + static bool empty( const A& ) + { + return array_size==0; + } + }; + }; + + // specialization for char + template<> + struct array_length_selector + { + template< typename TraitsT > + struct array_length + { + typedef typename + TraitsT::size_type size_type; + + template< typename A > + static size_type length( const A& a ) + { + if ( a==0 ) + return 0; + else + return std::char_traits::length(a); + } + + template< typename A > + static bool empty( const A& a ) + { + return a==0 || a[0]==0; + } + }; + }; + + // specialization for wchar_t + template<> + struct array_length_selector + { + template< typename TraitsT > + struct array_length + { + typedef typename + TraitsT::size_type size_type; + + template< typename A > + static size_type length( const A& a ) + { + if ( a==0 ) + return 0; + else + return std::char_traits::length(a); + } + + template< typename A > + static bool empty( const A& a ) + { + return a==0 || a[0]==0; + } + }; + }; + + template< typename T > + struct array_container_traits + { + private: + // resolve array traits + typedef array_traits traits_type; + + public: + typedef typename + traits_type::value_type value_type; + typedef typename + traits_type::iterator iterator; + typedef typename + traits_type::const_iterator const_iterator; + typedef typename + traits_type::size_type size_type; + typedef typename + traits_type::difference_type difference_type; + + typedef typename + ::boost::mpl::if_< ::boost::is_const, + const_iterator, + iterator + >::type result_iterator; + + private: + // resolve array size + typedef typename + ::boost::remove_cv::type char_type; + typedef typename + array_length_selector:: + BOOST_NESTED_TEMPLATE array_length array_length_type; + + public: + BOOST_STATIC_CONSTANT( size_type, array_size = traits_type::array_size ); + + // static operations + template< typename A > + static size_type size( const A& a ) + { + return array_length_type::length(a); + } + + template< typename A > + static bool empty( const A& a ) + { + return array_length_type::empty(a); + } + + + template< typename A > + static iterator begin( A& a ) + { + return a; + } + + template< typename A > + static const_iterator begin( const A& a ) + { + return a; + } + + template< typename A > + static iterator end( A& a ) + { + return a+array_length_type::length(a); + } + + template< typename A > + static const_iterator end( const A& a ) + { + return a+array_length_type::length(a); + } + + }; + + template + struct array_container_traits_selector + { + typedef array_container_traits type; + }; + +// Pointer container traits --------------------------------------------------------------- + + template + struct pointer_container_traits + { + typedef typename + ::boost::remove_pointer::type value_type; + + typedef typename + ::boost::remove_cv::type char_type; + typedef ::std::char_traits char_traits; + + typedef value_type* iterator; + typedef const value_type* const_iterator; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + + typedef typename + ::boost::mpl::if_< ::boost::is_const, + const_iterator, + iterator + >::type result_iterator; + + // static operations + template< typename P > + static size_type size( const P& p ) + { + if ( p==0 ) + return 0; + else + return char_traits::length(p); + } + + template< typename P > + static bool empty( const P& p ) + { + return p==0 || p[0]==0; + } + + template< typename P > + static iterator begin( P& p ) + { + return p; + } + + template< typename P > + static const_iterator begin( const P& p ) + { + return p; + } + + template< typename P > + static iterator end( P& p ) + { + if ( p==0 ) + return p; + else + return p+char_traits::length(p); + } + + template< typename P > + static const_iterator end( const P& p ) + { + if ( p==0 ) + return p; + else + return p+char_traits::length(p); + } + + }; + + template + struct pointer_container_traits_selector + { + typedef pointer_container_traits type; + }; + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_DETAIL_COLLECTION_HPP diff --git a/libs/range/include/boost/range/detail/combine_cxx03.hpp b/libs/range/include/boost/range/detail/combine_cxx03.hpp new file mode 100644 index 00000000..c0b2a27a --- /dev/null +++ b/libs/range/include/boost/range/detail/combine_cxx03.hpp @@ -0,0 +1,79 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_COMBINE_CXX03_HPP +#define BOOST_RANGE_DETAIL_COMBINE_CXX03_HPP + +#ifndef BOOST_RANGE_MIN_COMBINE_ARGS +#define BOOST_RANGE_MIN_COMBINE_ARGS 2 +#endif + +#ifndef BOOST_RANGE_MAX_COMBINE_ARGS +#define BOOST_RANGE_MAX_COMBINE_ARGS 5 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + +namespace range +{ + +#define BOOST_RANGE_combined_seq(z, n, data) boost::data(BOOST_PP_CAT(r,n)) + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + +#include + +#else // by using rvalue references we avoid requiring 2^n overloads. + +#include + +#endif + +#define BOOST_PP_LOCAL_MACRO(n) BOOST_RANGE_combine(~,n,~) +#define BOOST_PP_LOCAL_LIMITS (BOOST_RANGE_MIN_COMBINE_ARGS, \ + BOOST_RANGE_MAX_COMBINE_ARGS) +#include BOOST_PP_LOCAL_ITERATE() + + } // namespace range + + using boost::range::combine; + +} // namespace boost + +#endif // include guard + +#undef BOOST_RANGE_combined_seq +#undef BOOST_RANGE_combined_exp_pred +#undef BOOST_RANGE_combined_exp_op +#undef BOOST_RANGE_combined_exp +#undef BOOST_RANGE_combined_bitset_pred +#undef BOOST_RANGE_combined_bitset_op +#undef BOOST_RANGE_combined_bitset +#undef BOOST_RANGE_combined_range_iterator +#undef BOOST_RANGE_combined_args +#undef BOOST_RANGE_combine_impl +#undef BOOST_RANGE_combine diff --git a/libs/range/include/boost/range/detail/combine_cxx11.hpp b/libs/range/include/boost/range/detail/combine_cxx11.hpp new file mode 100644 index 00000000..f4bcf80b --- /dev/null +++ b/libs/range/include/boost/range/detail/combine_cxx11.hpp @@ -0,0 +1,38 @@ +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_COMBINE_CXX11_HPP +#define BOOST_RANGE_DETAIL_COMBINE_CXX11_HPP + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + +template +auto combine(Ranges&&... rngs) -> + combined_range +{ + return combined_range( + boost::make_tuple(boost::begin(rngs)...), + boost::make_tuple(boost::end(rngs)...)); +} + + } // namespace range + +using range::combine; + +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/combine_no_rvalue.hpp b/libs/range/include/boost/range/detail/combine_no_rvalue.hpp new file mode 100644 index 00000000..bdb3950d --- /dev/null +++ b/libs/range/include/boost/range/detail/combine_no_rvalue.hpp @@ -0,0 +1,73 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#define BOOST_RANGE_combined_exp_pred(d, data) BOOST_PP_TUPLE_ELEM(3, 0, data) + +#define BOOST_RANGE_combined_exp_op(d, data) \ + ( \ + BOOST_PP_DEC( \ + BOOST_PP_TUPLE_ELEM(3, 0, data) \ + ), \ + BOOST_PP_TUPLE_ELEM(3, 1, data), \ + BOOST_PP_MUL_D( \ + d, \ + BOOST_PP_TUPLE_ELEM(3, 2, data), \ + BOOST_PP_TUPLE_ELEM(3, 1, data) \ + ) \ + ) + +#define BOOST_RANGE_combined_exp(x, n) \ + BOOST_PP_TUPLE_ELEM(3, 2, \ + BOOST_PP_WHILE(BOOST_RANGE_combined_exp_pred, \ + BOOST_RANGE_combined_exp_op, (n, x, 1))) + +#define BOOST_RANGE_combined_bitset_pred(n, state) \ + BOOST_PP_TUPLE_ELEM(2,1,state) + +#define BOOST_RANGE_combined_bitset_op(d, state) \ + (BOOST_PP_DIV_D(d, BOOST_PP_TUPLE_ELEM(2,0,state), 2), \ + BOOST_PP_DEC(BOOST_PP_TUPLE_ELEM(2,1,state))) + +#define BOOST_RANGE_combined_bitset(i, n) \ +BOOST_PP_MOD(BOOST_PP_TUPLE_ELEM(2, 0, \ + BOOST_PP_WHILE(BOOST_RANGE_combined_bitset_pred, \ + BOOST_RANGE_combined_bitset_op, (i,n))), 2) + +#define BOOST_RANGE_combined_range_iterator(z, n, i) \ + typename range_iterator< \ + BOOST_PP_CAT(R,n) \ + BOOST_PP_IF( \ + BOOST_RANGE_combined_bitset(i,n), \ + BOOST_PP_IDENTITY(const), \ + BOOST_PP_EMPTY)() \ + >::type + +#define BOOST_RANGE_combined_args(z, n, i) \ + BOOST_PP_CAT(R, n) \ + BOOST_PP_IF(BOOST_RANGE_combined_bitset(i,n), const&, &) \ + BOOST_PP_CAT(r, n) + +#define BOOST_RANGE_combine_impl(z, i, n)\ + template \ + inline range::combined_range< \ + boost::tuple \ + > \ + combine(BOOST_PP_ENUM(n, BOOST_RANGE_combined_args, i)) \ + { \ + typedef tuple< \ + BOOST_PP_ENUM(n, BOOST_RANGE_combined_range_iterator, i) \ + > rng_tuple_t; \ + return range::combined_range( \ + rng_tuple_t(BOOST_PP_ENUM(n, BOOST_RANGE_combined_seq, begin)), \ + rng_tuple_t(BOOST_PP_ENUM(n, BOOST_RANGE_combined_seq, end))); \ + } + + +#define BOOST_RANGE_combine(z, n, data) \ + BOOST_PP_REPEAT(BOOST_RANGE_combined_exp(2,n), BOOST_RANGE_combine_impl, n) diff --git a/libs/range/include/boost/range/detail/combine_rvalue.hpp b/libs/range/include/boost/range/detail/combine_rvalue.hpp new file mode 100644 index 00000000..2e323b75 --- /dev/null +++ b/libs/range/include/boost/range/detail/combine_rvalue.hpp @@ -0,0 +1,32 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#define BOOST_RANGE_combined_args(z, n, i) \ + BOOST_PP_CAT(R, n)&& BOOST_PP_CAT(r, n) + +#define BOOST_RANGE_combined_range_iterator(z, n, i) \ + typename range_iterator< \ + typename remove_reference::type \ + >::type + + +#define BOOST_RANGE_combine(z, n, data) \ + template \ + inline range::combined_range< \ + tuple \ + > \ + combine(BOOST_PP_ENUM(n, BOOST_RANGE_combined_args, ~)) \ + { \ + typedef tuple< \ + BOOST_PP_ENUM(n, BOOST_RANGE_combined_range_iterator, ~) \ + > rng_tuple_t; \ + return range::combined_range( \ + rng_tuple_t(BOOST_PP_ENUM(n, BOOST_RANGE_combined_seq, begin)), \ + rng_tuple_t(BOOST_PP_ENUM(n, BOOST_RANGE_combined_seq, end))); \ + } diff --git a/libs/range/include/boost/range/detail/common.hpp b/libs/range/include/boost/range/detail/common.hpp new file mode 100644 index 00000000..2cbc5541 --- /dev/null +++ b/libs/range/include/boost/range/detail/common.hpp @@ -0,0 +1,116 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_DETAIL_COMMON_HPP +#define BOOST_RANGE_DETAIL_COMMON_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////////////// +// missing partial specialization workaround. +////////////////////////////////////////////////////////////////////////////// + +namespace boost +{ + namespace range_detail + { + // 1 = std containers + // 2 = std::pair + // 3 = const std::pair + // 4 = array + // 5 = const array + // 6 = char array + // 7 = wchar_t array + // 8 = char* + // 9 = const char* + // 10 = whar_t* + // 11 = const wchar_t* + // 12 = string + + typedef mpl::int_<1>::type std_container_; + typedef mpl::int_<2>::type std_pair_; + typedef mpl::int_<3>::type const_std_pair_; + typedef mpl::int_<4>::type array_; + typedef mpl::int_<5>::type const_array_; + typedef mpl::int_<6>::type char_array_; + typedef mpl::int_<7>::type wchar_t_array_; + typedef mpl::int_<8>::type char_ptr_; + typedef mpl::int_<9>::type const_char_ptr_; + typedef mpl::int_<10>::type wchar_t_ptr_; + typedef mpl::int_<11>::type const_wchar_t_ptr_; + typedef mpl::int_<12>::type string_; + + template< typename C > + struct range_helper + { + static C* c; + static C ptr; + + BOOST_STATIC_CONSTANT( bool, is_pair_ = sizeof( boost::range_detail::is_pair_impl( c ) ) == sizeof( yes_type ) ); + BOOST_STATIC_CONSTANT( bool, is_char_ptr_ = sizeof( boost::range_detail::is_char_ptr_impl( ptr ) ) == sizeof( yes_type ) ); + BOOST_STATIC_CONSTANT( bool, is_const_char_ptr_ = sizeof( boost::range_detail::is_const_char_ptr_impl( ptr ) ) == sizeof( yes_type ) ); + BOOST_STATIC_CONSTANT( bool, is_wchar_t_ptr_ = sizeof( boost::range_detail::is_wchar_t_ptr_impl( ptr ) ) == sizeof( yes_type ) ); + BOOST_STATIC_CONSTANT( bool, is_const_wchar_t_ptr_ = sizeof( boost::range_detail::is_const_wchar_t_ptr_impl( ptr ) ) == sizeof( yes_type ) ); + BOOST_STATIC_CONSTANT( bool, is_char_array_ = sizeof( boost::range_detail::is_char_array_impl( ptr ) ) == sizeof( yes_type ) ); + BOOST_STATIC_CONSTANT( bool, is_wchar_t_array_ = sizeof( boost::range_detail::is_wchar_t_array_impl( ptr ) ) == sizeof( yes_type ) ); + BOOST_STATIC_CONSTANT( bool, is_string_ = (is_const_char_ptr_ || is_const_wchar_t_ptr_)); + BOOST_STATIC_CONSTANT( bool, is_array_ = boost::is_array::value ); + + }; + + template< typename C > + class range + { + typedef BOOST_RANGE_DEDUCED_TYPENAME boost::mpl::if_c< ::boost::range_detail::range_helper::is_pair_, + boost::range_detail::std_pair_, + void >::type pair_t; + typedef BOOST_RANGE_DEDUCED_TYPENAME boost::mpl::if_c< ::boost::range_detail::range_helper::is_array_, + boost::range_detail::array_, + pair_t >::type array_t; + typedef BOOST_RANGE_DEDUCED_TYPENAME boost::mpl::if_c< ::boost::range_detail::range_helper::is_string_, + boost::range_detail::string_, + array_t >::type string_t; + typedef BOOST_RANGE_DEDUCED_TYPENAME boost::mpl::if_c< ::boost::range_detail::range_helper::is_const_char_ptr_, + boost::range_detail::const_char_ptr_, + string_t >::type const_char_ptr_t; + typedef BOOST_RANGE_DEDUCED_TYPENAME boost::mpl::if_c< ::boost::range_detail::range_helper::is_char_ptr_, + boost::range_detail::char_ptr_, + const_char_ptr_t >::type char_ptr_t; + typedef BOOST_RANGE_DEDUCED_TYPENAME boost::mpl::if_c< ::boost::range_detail::range_helper::is_const_wchar_t_ptr_, + boost::range_detail::const_wchar_t_ptr_, + char_ptr_t >::type const_wchar_ptr_t; + typedef BOOST_RANGE_DEDUCED_TYPENAME boost::mpl::if_c< ::boost::range_detail::range_helper::is_wchar_t_ptr_, + boost::range_detail::wchar_t_ptr_, + const_wchar_ptr_t >::type wchar_ptr_t; + typedef BOOST_RANGE_DEDUCED_TYPENAME boost::mpl::if_c< ::boost::range_detail::range_helper::is_wchar_t_array_, + boost::range_detail::wchar_t_array_, + wchar_ptr_t >::type wchar_array_t; + typedef BOOST_RANGE_DEDUCED_TYPENAME boost::mpl::if_c< ::boost::range_detail::range_helper::is_char_array_, + boost::range_detail::char_array_, + wchar_array_t >::type char_array_t; + public: + typedef BOOST_RANGE_DEDUCED_TYPENAME boost::mpl::if_c< ::boost::is_void::value, + boost::range_detail::std_container_, + char_array_t >::type type; + }; // class 'range' + } +} + +#endif + diff --git a/libs/range/include/boost/range/detail/default_constructible_unary_fn.hpp b/libs/range/include/boost/range/detail/default_constructible_unary_fn.hpp new file mode 100644 index 00000000..9729e3cb --- /dev/null +++ b/libs/range/include/boost/range/detail/default_constructible_unary_fn.hpp @@ -0,0 +1,81 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_DEFAULT_CONSTRUCTIBLE_UNARY_FN_HPP_INCLUDED +#define BOOST_RANGE_DETAIL_DEFAULT_CONSTRUCTIBLE_UNARY_FN_HPP_INCLUDED + +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + +template +class default_constructible_unary_fn_wrapper +{ +public: + typedef R result_type; + + default_constructible_unary_fn_wrapper() + { + } + default_constructible_unary_fn_wrapper(const F& source) + : m_impl(source) + { + } + default_constructible_unary_fn_wrapper(const default_constructible_unary_fn_wrapper& source) + : m_impl(source.m_impl) + { + } + default_constructible_unary_fn_wrapper& operator=(const default_constructible_unary_fn_wrapper& source) + { + if (source.m_impl) + { + // Lambda are not copy/move assignable. + m_impl.emplace(*source.m_impl); + } + else + { + m_impl.reset(); + } + return *this; + } + template + R operator()(const Arg& arg) const + { + BOOST_ASSERT(m_impl); + return (*m_impl)(arg); + } + template + R operator()(Arg& arg) const + { + BOOST_ASSERT(m_impl); + return (*m_impl)(arg); + } +private: + boost::optional m_impl; +}; + +template +struct default_constructible_unary_fn_gen +{ + typedef typename boost::mpl::if_< + boost::has_trivial_default_constructor, + F, + default_constructible_unary_fn_wrapper + >::type type; +}; + + } // namespace range_detail +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/demote_iterator_traversal_tag.hpp b/libs/range/include/boost/range/detail/demote_iterator_traversal_tag.hpp new file mode 100644 index 00000000..6d65720a --- /dev/null +++ b/libs/range/include/boost/range/detail/demote_iterator_traversal_tag.hpp @@ -0,0 +1,91 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// Acknowledgements: +// aschoedl supplied a fix to supply the level of interoperability I had +// originally intended, but failed to implement. +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_DEMOTE_ITERATOR_TRAVERSAL_TAG_HPP_INCLUDED +#define BOOST_RANGE_DETAIL_DEMOTE_ITERATOR_TRAVERSAL_TAG_HPP_INCLUDED + +#include + +namespace boost +{ + namespace range_detail + { + +template +struct inner_demote_iterator_traversal_tag +{ +}; + +#define BOOST_DEMOTE_TRAVERSAL_TAG( Tag1, Tag2, ResultTag ) \ +template<> struct inner_demote_iterator_traversal_tag< Tag1 , Tag2 > \ +{ \ + typedef ResultTag type; \ +}; + +BOOST_DEMOTE_TRAVERSAL_TAG( no_traversal_tag, no_traversal_tag, no_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( no_traversal_tag, incrementable_traversal_tag, no_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( no_traversal_tag, single_pass_traversal_tag, no_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( no_traversal_tag, forward_traversal_tag, no_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( no_traversal_tag, bidirectional_traversal_tag, no_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( no_traversal_tag, random_access_traversal_tag, no_traversal_tag ) + +BOOST_DEMOTE_TRAVERSAL_TAG( incrementable_traversal_tag, no_traversal_tag, no_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( incrementable_traversal_tag, incrementable_traversal_tag, incrementable_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( incrementable_traversal_tag, single_pass_traversal_tag, incrementable_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( incrementable_traversal_tag, forward_traversal_tag, incrementable_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( incrementable_traversal_tag, bidirectional_traversal_tag, incrementable_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( incrementable_traversal_tag, random_access_traversal_tag, incrementable_traversal_tag ) + +BOOST_DEMOTE_TRAVERSAL_TAG( single_pass_traversal_tag, no_traversal_tag, no_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( single_pass_traversal_tag, incrementable_traversal_tag, incrementable_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( single_pass_traversal_tag, single_pass_traversal_tag, single_pass_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( single_pass_traversal_tag, forward_traversal_tag, single_pass_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( single_pass_traversal_tag, bidirectional_traversal_tag, single_pass_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( single_pass_traversal_tag, random_access_traversal_tag, single_pass_traversal_tag ) + +BOOST_DEMOTE_TRAVERSAL_TAG( forward_traversal_tag, no_traversal_tag, no_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( forward_traversal_tag, incrementable_traversal_tag, incrementable_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( forward_traversal_tag, single_pass_traversal_tag, single_pass_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( forward_traversal_tag, forward_traversal_tag, forward_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( forward_traversal_tag, bidirectional_traversal_tag, forward_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( forward_traversal_tag, random_access_traversal_tag, forward_traversal_tag ) + +BOOST_DEMOTE_TRAVERSAL_TAG( bidirectional_traversal_tag, no_traversal_tag, no_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( bidirectional_traversal_tag, incrementable_traversal_tag, incrementable_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( bidirectional_traversal_tag, single_pass_traversal_tag, single_pass_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( bidirectional_traversal_tag, forward_traversal_tag, forward_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( bidirectional_traversal_tag, bidirectional_traversal_tag, bidirectional_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( bidirectional_traversal_tag, random_access_traversal_tag, bidirectional_traversal_tag ) + +BOOST_DEMOTE_TRAVERSAL_TAG( random_access_traversal_tag, no_traversal_tag, no_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( random_access_traversal_tag, incrementable_traversal_tag, incrementable_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( random_access_traversal_tag, single_pass_traversal_tag, single_pass_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( random_access_traversal_tag, forward_traversal_tag, forward_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( random_access_traversal_tag, bidirectional_traversal_tag, bidirectional_traversal_tag ) +BOOST_DEMOTE_TRAVERSAL_TAG( random_access_traversal_tag, random_access_traversal_tag, random_access_traversal_tag ) + +#undef BOOST_DEMOTE_TRAVERSAL_TAG + +template +struct demote_iterator_traversal_tag + : inner_demote_iterator_traversal_tag< + typename boost::iterators::pure_traversal_tag< IteratorTraversalTag1 >::type, + typename boost::iterators::pure_traversal_tag< IteratorTraversalTag2 >::type + > +{ +}; + + } // namespace range_detail +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/difference_type.hpp b/libs/range/include/boost/range/detail/difference_type.hpp new file mode 100644 index 00000000..c6415160 --- /dev/null +++ b/libs/range/include/boost/range/detail/difference_type.hpp @@ -0,0 +1,121 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_DETAIL_DIFFERENCE_TYPE_HPP +#define BOOST_RANGE_DETAIL_DIFFERENCE_TYPE_HPP + +#include +#include + +////////////////////////////////////////////////////////////////////////////// +// missing partial specialization workaround. +////////////////////////////////////////////////////////////////////////////// + +namespace boost +{ + namespace range_detail + { + template< typename T > + struct range_difference_type_; + + template<> + struct range_difference_type_ + { + template< typename C > + struct pts + { + typedef BOOST_DEDUCED_TYPENAME C::difference_type type; + }; + }; + + template<> + struct range_difference_type_ + { + template< typename P > + struct pts + { + typedef BOOST_RANGE_DEDUCED_TYPENAME boost::iterator_difference< BOOST_DEDUCED_TYPENAME P::first_type>::type type; + }; + }; + + template<> + struct range_difference_type_ + { + template< typename A > + struct pts + { + typedef std::ptrdiff_t type; + }; + }; + + template<> + struct range_difference_type_ + { + template< typename A > + struct pts + { + typedef std::ptrdiff_t type; + }; + }; + + template<> + struct range_difference_type_ + { + template< typename S > + struct pts + { + typedef std::ptrdiff_t type; + }; + }; + + template<> + struct range_difference_type_ + { + template< typename S > + struct pts + { + typedef std::ptrdiff_t type; + }; + }; + + template<> + struct range_difference_type_ + { + template< typename S > + struct pts + { + typedef std::ptrdiff_t type; + }; + }; + + template<> + struct range_difference_type_ + { + template< typename S > + struct pts + { + typedef std::ptrdiff_t type; + }; + }; + + } + + template< typename C > + class range_difference + { + typedef BOOST_RANGE_DEDUCED_TYPENAME range_detail::range::type c_type; + public: + typedef BOOST_RANGE_DEDUCED_TYPENAME range_detail::range_difference_type_::BOOST_NESTED_TEMPLATE pts::type type; + }; + +} + +#endif + diff --git a/libs/range/include/boost/range/detail/empty.hpp b/libs/range/include/boost/range/detail/empty.hpp new file mode 100644 index 00000000..b098705d --- /dev/null +++ b/libs/range/include/boost/range/detail/empty.hpp @@ -0,0 +1,120 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_DETAIL_EMPTY_HPP +#define BOOST_RANGE_DETAIL_EMPTY_HPP + +#include + +namespace boost +{ + namespace range_detail + { + template< typename T > + struct range_empty; + + ////////////////////////////////////////////////////////////////////// + // default + ////////////////////////////////////////////////////////////////////// + + template<> + struct range_empty + { + template< typename C > + static bool fun( C& c ) + { + return c.empty(); + }; + }; + + ////////////////////////////////////////////////////////////////////// + // pair + ////////////////////////////////////////////////////////////////////// + + template<> + struct range_empty + { + template< typename P > + static bool fun( const P& p ) + { + return p.first == p.second; + } + }; + + ////////////////////////////////////////////////////////////////////// + // array + ////////////////////////////////////////////////////////////////////// + + template<> + struct range_empty + { + template< typename T, std::size_t sz > + static bool fun( T BOOST_ARRAY_REF[sz] ) + { + if( boost_range_array == 0 ) + return true; + return false; + } + }; + + ////////////////////////////////////////////////////////////////////// + // string + ////////////////////////////////////////////////////////////////////// + + template<> + struct range_empty + { + static bool fun( const char* s ) + { + return s == 0 || s[0] == 0; + } + }; + + template<> + struct range_empty + { + static bool fun( const char* s ) + { + return s == 0 || s[0] == 0; + } + }; + + template<> + struct range_empty + { + static bool fun( const wchar_t* s ) + { + return s == 0 || s[0] == 0; + } + }; + + template<> + struct range_empty + { + static bool fun( const wchar_t* s ) + { + return s == 0 || s[0] == 0; + } + }; + + } // namespace 'range_detail' + + + template< typename C > + inline bool + empty( const C& c ) + { + return range_detail::range_empty< BOOST_RANGE_DEDUCED_TYPENAME range_detail::range::type >::fun( c ); + } + +} // namespace 'boost' + + +#endif diff --git a/libs/range/include/boost/range/detail/extract_optional_type.hpp b/libs/range/include/boost/range/detail/extract_optional_type.hpp new file mode 100644 index 00000000..0381434a --- /dev/null +++ b/libs/range/include/boost/range/detail/extract_optional_type.hpp @@ -0,0 +1,48 @@ +// Boost.Range library +// +// Copyright Arno Schoedl & Neil Groves 2009. +// Use, modification and distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_EXTRACT_OPTIONAL_TYPE_HPP_INCLUDED +#define BOOST_RANGE_DETAIL_EXTRACT_OPTIONAL_TYPE_HPP_INCLUDED + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include + +#if !defined(BOOST_MPL_CFG_NO_HAS_XXX) + +// Defines extract_some_typedef which exposes T::some_typedef as +// extract_some_typedef::type if T::some_typedef exists. Otherwise +// extract_some_typedef is empty. +#define BOOST_RANGE_EXTRACT_OPTIONAL_TYPE( a_typedef ) \ + BOOST_MPL_HAS_XXX_TRAIT_DEF(a_typedef) \ + template< typename C, bool B = BOOST_PP_CAT(has_, a_typedef)::value > \ + struct BOOST_PP_CAT(extract_, a_typedef) \ + {}; \ + template< typename C > \ + struct BOOST_PP_CAT(extract_, a_typedef)< C, true > \ + { \ + typedef BOOST_DEDUCED_TYPENAME C::a_typedef type; \ + }; + +#else + +#define BOOST_RANGE_EXTRACT_OPTIONAL_TYPE( a_typedef ) \ + template< typename C > \ + struct BOOST_PP_CAT(extract_, a_typedef) \ + { \ + typedef BOOST_DEDUCED_TYPENAME C::a_typedef type; \ + }; + +#endif + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/has_member_size.hpp b/libs/range/include/boost/range/detail/has_member_size.hpp new file mode 100644 index 00000000..0c639aa8 --- /dev/null +++ b/libs/range/include/boost/range/detail/has_member_size.hpp @@ -0,0 +1,66 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. +// +// Use, modification and distribution are subject to 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). +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_HAS_MEMBER_SIZE_HPP +#define BOOST_RANGE_DETAIL_HAS_MEMBER_SIZE_HPP + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + +template +class has_member_size_impl +{ +private: + template + class check + { + }; + + template + static boost::uint8_t f(check*); + + template + static boost::uint16_t f(...); + +public: + static const bool value = + (sizeof(f(0)) == sizeof(boost::uint8_t)); + + typedef typename mpl::if_c< + (sizeof(f(0)) == sizeof(boost::uint8_t)), + mpl::true_, + mpl::false_ + >::type type; +}; + +template +struct has_member_size +{ + typedef typename mpl::and_< + typename is_class::type, + typename has_member_size_impl::type + >::type type; + + static const bool value = + is_class::value && has_member_size_impl::value; +}; + + } // namespace range_detail +}// namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/implementation_help.hpp b/libs/range/include/boost/range/detail/implementation_help.hpp new file mode 100644 index 00000000..59a3ade8 --- /dev/null +++ b/libs/range/include/boost/range/detail/implementation_help.hpp @@ -0,0 +1,114 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_DETAIL_IMPLEMENTATION_HELP_HPP +#define BOOST_RANGE_DETAIL_IMPLEMENTATION_HELP_HPP + +#include +#include +#include +#include +#include + +#ifndef BOOST_NO_CWCHAR +#include +#endif + +namespace boost +{ + namespace range_detail + { + template + inline void boost_range_silence_warning( const T& ) { } + + ///////////////////////////////////////////////////////////////////// + // end() help + ///////////////////////////////////////////////////////////////////// + + inline const char* str_end( const char* s, const char* ) + { + return s + strlen( s ); + } + +#ifndef BOOST_NO_CWCHAR + inline const wchar_t* str_end( const wchar_t* s, const wchar_t* ) + { + return s + wcslen( s ); + } +#else + inline const wchar_t* str_end( const wchar_t* s, const wchar_t* ) + { + if( s == 0 || s[0] == 0 ) + return s; + while( *++s != 0 ) + ; + return s; + } +#endif + + template< class Char > + inline Char* str_end( Char* s ) + { + return const_cast( str_end( s, s ) ); + } + + template< class T, std::size_t sz > + BOOST_CONSTEXPR inline T* array_end( T BOOST_RANGE_ARRAY_REF()[sz] ) BOOST_NOEXCEPT + { + return boost_range_array + sz; + } + + template< class T, std::size_t sz > + BOOST_CONSTEXPR inline const T* array_end( const T BOOST_RANGE_ARRAY_REF()[sz] ) BOOST_NOEXCEPT + { + return boost_range_array + sz; + } + + ///////////////////////////////////////////////////////////////////// + // size() help + ///////////////////////////////////////////////////////////////////// + + template< class Char > + inline std::size_t str_size( const Char* const& s ) + { + return str_end( s ) - s; + } + + template< class T, std::size_t sz > + inline std::size_t array_size( T BOOST_RANGE_ARRAY_REF()[sz] ) + { + boost_range_silence_warning( boost_range_array ); + return sz; + } + + template< class T, std::size_t sz > + inline std::size_t array_size( const T BOOST_RANGE_ARRAY_REF()[sz] ) + { + boost_range_silence_warning( boost_range_array ); + return sz; + } + + inline bool is_same_address(const void* l, const void* r) + { + return l == r; + } + + template + inline bool is_same_object(const T1& l, const T2& r) + { + return range_detail::is_same_address(&l, &r); + } + + } // namespace 'range_detail' + +} // namespace 'boost' + + +#endif diff --git a/libs/range/include/boost/range/detail/join_iterator.hpp b/libs/range/include/boost/range/detail/join_iterator.hpp new file mode 100644 index 00000000..0f47f58e --- /dev/null +++ b/libs/range/include/boost/range/detail/join_iterator.hpp @@ -0,0 +1,358 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// Acknowledgements: +// aschoedl contributed an improvement to the determination +// of the Reference type parameter. +// +// Leonid Gershanovich reported Trac ticket 7376 about the dereference operator +// requiring identical reference types due to using the ternary if. +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_JOIN_ITERATOR_HPP_INCLUDED +#define BOOST_RANGE_DETAIL_JOIN_ITERATOR_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + +template +struct join_iterator_link +{ +public: + join_iterator_link(Iterator1 last1, Iterator2 first2) + : last1(last1) + , first2(first2) + { + } + + Iterator1 last1; + Iterator2 first2; + +private: + join_iterator_link() /* = delete */ ; +}; + +class join_iterator_begin_tag {}; +class join_iterator_end_tag {}; + +template +class join_iterator_union +{ +public: + typedef Iterator1 iterator1_t; + typedef Iterator2 iterator2_t; + + join_iterator_union() {} + join_iterator_union(unsigned int /*selected*/, const iterator1_t& it1, const iterator2_t& it2) : m_it1(it1), m_it2(it2) {} + + iterator1_t& it1() { return m_it1; } + const iterator1_t& it1() const { return m_it1; } + + iterator2_t& it2() { return m_it2; } + const iterator2_t& it2() const { return m_it2; } + + Reference dereference(unsigned int selected) const + { + if (selected) + return *m_it2; + return *m_it1; + } + + bool equal(const join_iterator_union& other, unsigned int selected) const + { + return selected + ? m_it2 == other.m_it2 + : m_it1 == other.m_it1; + } + +private: + iterator1_t m_it1; + iterator2_t m_it2; +}; + +template +class join_iterator_union +{ +public: + typedef Iterator iterator1_t; + typedef Iterator iterator2_t; + + join_iterator_union() {} + + join_iterator_union(unsigned int selected, const iterator1_t& it1, const iterator2_t& it2) + : m_it(selected ? it2 : it1) + { + } + + iterator1_t& it1() { return m_it; } + const iterator1_t& it1() const { return m_it; } + + iterator2_t& it2() { return m_it; } + const iterator2_t& it2() const { return m_it; } + + Reference dereference(unsigned int) const + { + return *m_it; + } + + bool equal(const join_iterator_union& other, + unsigned int /*selected*/) const + { + return m_it == other.m_it; + } + +private: + iterator1_t m_it; +}; + +template::type + // find least demanding, commonly supported reference type, in the order &, const&, and by-value: + , typename Reference = typename mpl::if_c< + !is_reference::type>::value + || !is_reference::type>::value, + typename remove_const< + typename remove_reference< + typename iterator_reference::type + >::type + >::type, + typename mpl::if_c< + is_const< + typename remove_reference< + typename iterator_reference::type + >::type + >::value + || is_const< + typename remove_reference< + typename iterator_reference::type + >::type + >::value, + typename add_reference< + typename add_const< + typename remove_reference< + typename iterator_reference::type + >::type + >::type + >::type, + typename iterator_reference::type + >::type + >::type + , typename Traversal = typename demote_iterator_traversal_tag< + typename iterator_traversal::type + , typename iterator_traversal::type>::type +> +class join_iterator + : public iterator_facade, ValueType, Traversal, Reference> +{ + typedef join_iterator_link link_t; + typedef join_iterator_union iterator_union; +public: + typedef Iterator1 iterator1_t; + typedef Iterator2 iterator2_t; + + join_iterator() + : m_section(0u) + , m_it(0u, iterator1_t(), iterator2_t()) + , m_link(link_t(iterator1_t(), iterator2_t())) + {} + + join_iterator(unsigned int section, Iterator1 current1, Iterator1 last1, Iterator2 first2, Iterator2 current2) + : m_section(section) + , m_it(section, current1, current2) + , m_link(link_t(last1, first2)) + { + } + + template + join_iterator(Range1& r1, Range2& r2, join_iterator_begin_tag) + : m_section(boost::empty(r1) ? 1u : 0u) + , m_it(boost::empty(r1) ? 1u : 0u, boost::begin(r1), boost::begin(r2)) + , m_link(link_t(boost::end(r1), boost::begin(r2))) + { + } + + template + join_iterator(const Range1& r1, const Range2& r2, join_iterator_begin_tag) + : m_section(boost::empty(r1) ? 1u : 0u) + , m_it(boost::empty(r1) ? 1u : 0u, boost::const_begin(r1), boost::const_begin(r2)) + , m_link(link_t(boost::const_end(r1), boost::const_begin(r2))) + { + } + + template + join_iterator(Range1& r1, Range2& r2, join_iterator_end_tag) + : m_section(1u) + , m_it(1u, boost::end(r1), boost::end(r2)) + , m_link(link_t(boost::end(r1), boost::begin(r2))) + { + } + + template + join_iterator(const Range1& r1, const Range2& r2, join_iterator_end_tag) + : m_section(1u) + , m_it(1u, boost::const_end(r1), boost::const_end(r2)) + , m_link(link_t(boost::const_end(r1), boost::const_begin(r2))) + { + } + +private: + void increment() + { + if (m_section) + ++m_it.it2(); + else + { + ++m_it.it1(); + if (m_it.it1() == m_link.last1) + { + m_it.it2() = m_link.first2; + m_section = 1u; + } + } + } + + void decrement() + { + if (m_section) + { + if (m_it.it2() == m_link.first2) + { + m_it.it1() = boost::prior(m_link.last1); + m_section = 0u; + } + else + --m_it.it2(); + } + else + --m_it.it1(); + } + + typename join_iterator::reference dereference() const + { + return m_it.dereference(m_section); + } + + bool equal(const join_iterator& other) const + { + return m_section == other.m_section + && m_it.equal(other.m_it, m_section); + } + + void advance(typename join_iterator::difference_type offset) + { + if (m_section) + advance_from_range2(offset); + else + advance_from_range1(offset); + } + + typename join_iterator::difference_type distance_to(const join_iterator& other) const + { + typename join_iterator::difference_type result; + if (m_section) + { + if (other.m_section) + result = other.m_it.it2() - m_it.it2(); + else + { + result = (m_link.first2 - m_it.it2()) + + (other.m_it.it1() - m_link.last1); + + BOOST_ASSERT( result <= 0 ); + } + } + else + { + if (other.m_section) + { + result = (m_link.last1 - m_it.it1()) + + (other.m_it.it2() - m_link.first2); + } + else + result = other.m_it.it1() - m_it.it1(); + } + return result; + } + + void advance_from_range2(typename join_iterator::difference_type offset) + { + typedef typename join_iterator::difference_type difference_t; + BOOST_ASSERT( m_section == 1u ); + if (offset < 0) + { + difference_t r2_dist = m_link.first2 - m_it.it2(); + BOOST_ASSERT( r2_dist <= 0 ); + if (offset >= r2_dist) + std::advance(m_it.it2(), offset); + else + { + difference_t r1_dist = offset - r2_dist; + BOOST_ASSERT( r1_dist <= 0 ); + m_it.it1() = m_link.last1 + r1_dist; + m_section = 0u; + } + } + else + std::advance(m_it.it2(), offset); + } + + void advance_from_range1(typename join_iterator::difference_type offset) + { + typedef typename join_iterator::difference_type difference_t; + BOOST_ASSERT( m_section == 0u ); + if (offset > 0) + { + difference_t r1_dist = m_link.last1 - m_it.it1(); + BOOST_ASSERT( r1_dist >= 0 ); + if (offset < r1_dist) + std::advance(m_it.it1(), offset); + else + { + difference_t r2_dist = offset - r1_dist; + BOOST_ASSERT( r2_dist >= 0 ); + m_it.it2() = m_link.first2 + r2_dist; + m_section = 1u; + } + } + else + std::advance(m_it.it1(), offset); + } + + unsigned int m_section; + iterator_union m_it; + link_t m_link; + + friend class ::boost::iterator_core_access; +}; + + } // namespace range_detail + +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/less.hpp b/libs/range/include/boost/range/detail/less.hpp new file mode 100644 index 00000000..957c5b6f --- /dev/null +++ b/libs/range/include/boost/range/detail/less.hpp @@ -0,0 +1,26 @@ +/* +Copyright 2019 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_RANGE_DETAIL_LESS +#define BOOST_RANGE_DETAIL_LESS + +namespace boost { +namespace range { +namespace detail { + +struct less { + template + bool operator()(const T& lhs, const U& rhs) const { + return lhs < rhs; + } +}; + +} /* detail */ +} /* range */ +} /* boost */ + +#endif diff --git a/libs/range/include/boost/range/detail/microsoft.hpp b/libs/range/include/boost/range/detail/microsoft.hpp new file mode 100644 index 00000000..d04575c3 --- /dev/null +++ b/libs/range/include/boost/range/detail/microsoft.hpp @@ -0,0 +1,932 @@ +#ifndef BOOST_RANGE_DETAIL_MICROSOFT_HPP +#define BOOST_RANGE_DETAIL_MICROSOFT_HPP + +// Boost.Range MFC/ATL Extension +// +// Copyright Shunsuke Sogame 2005-2006. +// 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) + + + + +// config +// + + +#include + + +#define BOOST_RANGE_DETAIL_MICROSOFT_RANGE_VERSION_1 1 + + +#if !defined(BOOST_RANGE_DETAIL_MICROSOFT_RANGE_VERSION_1) + #define BOOST_RANGE_DETAIL_MICROSOFT_range_mutable_iterator range_mutable_iterator + #define BOOST_RANGE_DETAIL_MICROSOFT_range_begin range_begin + #define BOOST_RANGE_DETAIL_MICROSOFT_range_end range_end +#else + #define BOOST_RANGE_DETAIL_MICROSOFT_range_mutable_iterator range_mutable_iterator + #define BOOST_RANGE_DETAIL_MICROSOFT_range_begin range_begin + #define BOOST_RANGE_DETAIL_MICROSOFT_range_end range_end +#endif + + + + +// yet another customization way +// + + +#include // iterator_difference +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // disable_if +#include + +#if !defined(BOOST_RANGE_DETAIL_MICROSOFT_RANGE_VERSION_1) + #include +#else + #include // distance + #include + #include + #include +#endif + + +namespace boost { namespace range_detail_microsoft { + + + // customization point + // + + template< class Tag > + struct customization; + + + template< class T > + struct customization_tag; + + + struct using_type_as_tag + { }; + + + // Topic: + // In fact, it is unnecessary for VC++. + // VC++'s behavior seems conforming, while GCC fails without this. + template< class Iterator, class T > + struct mutable_ : + disable_if< is_const, Iterator > + { }; + + + // helpers + // + + template< class Tag, class T > + struct customization_tag_of + { + typedef typename mpl::if_< is_same, + T, + Tag + >::type type; + }; + + + template< class T > + struct customization_of + { + typedef typename remove_cv::type bare_t; + typedef typename customization_tag::type tag_t; + typedef customization type; + }; + + + template< class T > + struct mutable_iterator_of + { + typedef typename remove_cv::type bare_t; + typedef typename customization_of::type cust_t; + typedef typename cust_t::template meta::mutable_iterator type; + }; + + + template< class T > + struct const_iterator_of + { + typedef typename remove_cv::type bare_t; + typedef typename customization_of::type cust_t; + typedef typename cust_t::template meta::const_iterator type; + }; + + + template< class T > + struct size_type_of + { + typedef typename range_detail_microsoft::mutable_iterator_of::type miter_t; + typedef typename iterator_difference::type type; + }; + + + template< class T > inline + typename mutable_iterator_of::type + begin_of(T& x) + { + typedef typename customization_of::type cust_t; + return cust_t().template begin::type>(x); + } + + + template< class T > inline + typename const_iterator_of::type + begin_of(T const& x) + { + typedef typename customization_of::type cust_t; + return cust_t().template begin::type>(x); + } + + + template< class T > inline + typename mutable_iterator_of::type + end_of(T& x) + { + typedef typename customization_of::type cust_t; + return cust_t().template end::type>(x); + } + + + template< class T > inline + typename const_iterator_of::type + end_of(T const& x) + { + typedef typename customization_of::type cust_t; + return cust_t().template end::type>(x); + } + + +#if defined(BOOST_RANGE_DETAIL_MICROSOFT_RANGE_VERSION_1) + + template< class T > inline + typename size_type_of::type + size_of(T const& x) + { + return std::distance(boost::begin(x), boost::end(x)); + } + +#endif + + + template< class Range > + struct compatible_mutable_iterator : + BOOST_RANGE_DETAIL_MICROSOFT_range_mutable_iterator + { }; + + +} } // namespace boost::range_detail_microsoft + + +#define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_namespace_open(NamespaceList) \ + BOOST_PP_LIST_FOR_EACH(BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_namespace_open_op, ~, NamespaceList) \ +/**/ + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_namespace_open_op(r, data, elem) \ + namespace elem { \ + /**/ + + +#define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_namespace_close(NamespaceList) \ + BOOST_PP_LIST_FOR_EACH(BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_namespace_close_op, ~, NamespaceList) \ +/**/ + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_namespace_close_op(r, data, elem) \ + } \ + /**/ + + +#define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_namespace_expand_op(r, data, elem) \ + :: elem \ +/**/ + + +#define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE(Tag, NamespaceList, Name) \ + namespace boost { namespace range_detail_microsoft { \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_tag(Tag, BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_fullname(NamespaceList, Name)) \ + } } \ + \ + namespace boost { \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_mutable_iterator(BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_fullname(NamespaceList, Name)) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_const_iterator(BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_fullname(NamespaceList, Name)) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_size_type(BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_fullname(NamespaceList, Name)) \ + } \ + \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_namespace_open(NamespaceList) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_begin(BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_fullname(NamespaceList, Name)) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_begin_const(BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_fullname(NamespaceList, Name)) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_end(BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_fullname(NamespaceList, Name)) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_end_const(BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_fullname(NamespaceList, Name)) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_size(BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_fullname(NamespaceList, Name)) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_namespace_close(NamespaceList) \ +/**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_fullname(NamespaceList, Name) \ + BOOST_PP_LIST_FOR_EACH(BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_namespace_expand_op, ~, NamespaceList) :: Name \ + /**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_tag(Tag, Fullname) \ + template< > \ + struct customization_tag< Fullname > : \ + customization_tag_of< Tag, Fullname > \ + { }; \ + /**/ + + + // metafunctions + // + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_mutable_iterator(Fullname) \ + template< > \ + struct BOOST_RANGE_DETAIL_MICROSOFT_range_mutable_iterator< Fullname > : \ + range_detail_microsoft::mutable_iterator_of< Fullname > \ + { }; \ + /**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_const_iterator(Fullname) \ + template< > \ + struct range_const_iterator< Fullname > : \ + range_detail_microsoft::const_iterator_of< Fullname > \ + { }; \ + /**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_size_type(Fullname) \ + template< > \ + struct range_size< Fullname > : \ + range_detail_microsoft::size_type_of< Fullname > \ + { }; \ + /**/ + + + // functions + // + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_begin(Fullname) \ + inline \ + boost::range_detail_microsoft::mutable_iterator_of< Fullname >::type \ + BOOST_RANGE_DETAIL_MICROSOFT_range_begin(Fullname& x) \ + { \ + return boost::range_detail_microsoft::begin_of(x); \ + } \ + /**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_begin_const(Fullname) \ + inline \ + boost::range_detail_microsoft::const_iterator_of< Fullname >::type \ + BOOST_RANGE_DETAIL_MICROSOFT_range_begin(Fullname const& x) \ + { \ + return boost::range_detail_microsoft::begin_of(x); \ + } \ + /**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_end(Fullname) \ + inline \ + boost::range_detail_microsoft::mutable_iterator_of< Fullname >::type \ + BOOST_RANGE_DETAIL_MICROSOFT_range_end(Fullname& x) \ + { \ + return boost::range_detail_microsoft::end_of(x); \ + } \ + /**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_end_const(Fullname) \ + inline \ + boost::range_detail_microsoft::const_iterator_of< Fullname >::type \ + BOOST_RANGE_DETAIL_MICROSOFT_range_end(Fullname const& x) \ + { \ + return boost::range_detail_microsoft::end_of(x); \ + } \ + /**/ + + + #if !defined(BOOST_RANGE_DETAIL_MICROSOFT_RANGE_VERSION_1) + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_size(Fullname) \ + /**/ + + #else + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE_size(Fullname) \ + inline \ + boost::range_detail_microsoft::size_type_of< Fullname >::type \ + boost_range_size(Fullname const& x) \ + { \ + return boost::range_detail_microsoft::size_of(x); \ + } \ + /**/ + + #endif + + +#define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE(Tag, NamespaceList, Name, ParamSeqOrCount) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_impl( \ + Tag, NamespaceList, Name, \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_to_param_seq(ParamSeqOrCount) \ + ) \ +/**/ + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_to_param_seq(ParamSeqOrCount) \ + BOOST_PP_IIF(BOOST_PP_IS_UNARY(ParamSeqOrCount), \ + ParamSeqOrCount BOOST_PP_TUPLE_EAT(3), \ + BOOST_PP_REPEAT \ + )(ParamSeqOrCount, BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_to_param_seq_op, ~) \ + /**/ + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_to_param_seq_op(z, n, _) \ + (class) \ + /**/ + + +#define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_impl(Tag, NamespaceList, Name, ParamSeq) \ + namespace boost { namespace range_detail_microsoft { \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_tag( \ + Tag, \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_params(ParamSeq), \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_fullname(NamespaceList, Name, ParamSeq) \ + ) \ + } } \ + \ + namespace boost { \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_mutable_iterator( \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_params(ParamSeq), \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_fullname(NamespaceList, Name, ParamSeq) \ + ) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_const_iterator( \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_params(ParamSeq), \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_fullname(NamespaceList, Name, ParamSeq) \ + ) \ + \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_size_type( \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_params(ParamSeq), \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_fullname(NamespaceList, Name, ParamSeq) \ + ) \ + } \ + \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_namespace_open(NamespaceList) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_begin( \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_params(ParamSeq), \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_fullname(NamespaceList, Name, ParamSeq) \ + ) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_begin_const( \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_params(ParamSeq), \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_fullname(NamespaceList, Name, ParamSeq) \ + ) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_end( \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_params(ParamSeq), \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_fullname(NamespaceList, Name, ParamSeq) \ + ) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_end_const( \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_params(ParamSeq), \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_fullname(NamespaceList, Name, ParamSeq) \ + ) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_size( \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_params(ParamSeq), \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_fullname(NamespaceList, Name, ParamSeq) \ + ) \ + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_namespace_close(NamespaceList) \ +/**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_params(ParamSeq) \ + BOOST_PP_SEQ_FOR_EACH_I(BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_params_op, ~, ParamSeq) \ + /**/ + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_params_op(r, data, i, elem) \ + BOOST_PP_COMMA_IF(i) elem BOOST_PP_CAT(T, i) \ + /**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_fullname(NamespaceList, Name, ParamSeq) \ + BOOST_PP_LIST_FOR_EACH(BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_namespace_expand_op, ~, NamespaceList) \ + :: Name < BOOST_PP_ENUM_PARAMS(BOOST_PP_SEQ_SIZE(ParamSeq), T) > \ + /**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_tag(Tag, Params, Fullname) \ + template< Params > \ + struct customization_tag< Fullname > : \ + customization_tag_of< Tag, Fullname > \ + { }; \ + /**/ + + + // metafunctions + // + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_mutable_iterator(Params, Fullname) \ + template< Params > \ + struct BOOST_RANGE_DETAIL_MICROSOFT_range_mutable_iterator< Fullname > : \ + range_detail_microsoft::mutable_iterator_of< Fullname > \ + { }; \ + /**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_const_iterator(Params, Fullname) \ + template< Params > \ + struct range_const_iterator< Fullname > : \ + range_detail_microsoft::const_iterator_of< Fullname > \ + { }; \ + /**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_size_type(Params, Fullname) \ + template< Params > \ + struct range_size< Fullname > : \ + range_detail_microsoft::size_type_of< Fullname > \ + { }; \ + /**/ + + + // functions + // + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_begin(Params, Fullname) \ + template< Params > inline \ + typename boost::range_detail_microsoft::mutable_iterator_of< Fullname >::type \ + BOOST_RANGE_DETAIL_MICROSOFT_range_begin(Fullname& x) \ + { \ + return boost::range_detail_microsoft::begin_of(x); \ + } \ + /**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_begin_const(Params, Fullname) \ + template< Params > inline \ + typename boost::range_detail_microsoft::const_iterator_of< Fullname >::type \ + BOOST_RANGE_DETAIL_MICROSOFT_range_begin(Fullname const& x) \ + { \ + return boost::range_detail_microsoft::begin_of(x); \ + } \ + /**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_end(Params, Fullname) \ + template< Params > inline \ + typename boost::range_detail_microsoft::mutable_iterator_of< Fullname >::type \ + BOOST_RANGE_DETAIL_MICROSOFT_range_end(Fullname& x) \ + { \ + return boost::range_detail_microsoft::end_of(x); \ + } \ + /**/ + + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_end_const(Params, Fullname) \ + template< Params > inline \ + typename boost::range_detail_microsoft::const_iterator_of< Fullname >::type \ + BOOST_RANGE_DETAIL_MICROSOFT_range_end(Fullname const& x) \ + { \ + return boost::range_detail_microsoft::end_of(x); \ + } \ + /**/ + + + #if !defined(BOOST_RANGE_DETAIL_MICROSOFT_RANGE_VERSION_1) + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_size(Params, Fullname) \ + /**/ + + #else + + #define BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE_size(Params, Fullname) \ + template< Params > inline \ + typename boost::range_detail_microsoft::size_type_of< Fullname >::type \ + boost_range_size(Fullname const& x) \ + { \ + return boost::range_detail_microsoft::size_of(x); \ + } \ + /**/ + + #endif + + + + +// list_iterator and helpers +// + + +#include +#include +#include +#include +#include + + +// POSITION's header is undocumented, so is NULL. +// +struct __POSITION; // incomplete, but used as just a pointer. +typedef __POSITION *POSITION; + + +namespace boost { namespace range_detail_microsoft { + + + template< + class ListT, + class Value, + class Reference, + class Traversal + > + struct list_iterator; + + + template< + class ListT, + class Value, + class Reference, + class Traversal + > + struct list_iterator_super + { + typedef typename mpl::if_< is_same, + Value&, + Reference + >::type ref_t; + + typedef typename mpl::if_< is_same, + bidirectional_traversal_tag, + Traversal + >::type trv_t; + + typedef iterator_facade< + list_iterator, + Value, + trv_t, + ref_t + > type; + }; + + + template< + class ListT, + class Value, + class Reference = use_default, + class Traversal = use_default + > + struct list_iterator : + list_iterator_super::type + { + private: + typedef list_iterator self_t; + typedef typename list_iterator_super::type super_t; + typedef typename super_t::reference ref_t; + + public: + explicit list_iterator() + { } + + explicit list_iterator(ListT& lst, POSITION pos) : + m_plst(boost::addressof(lst)), m_pos(pos) + { } + + template< class, class, class, class > friend struct list_iterator; + template< class ListT_, class Value_, class Reference_, class Traversal_> + list_iterator(list_iterator const& other) : + m_plst(other.m_plst), m_pos(other.m_pos) + { } + + private: + ListT *m_plst; + POSITION m_pos; + + friend class iterator_core_access; + ref_t dereference() const + { + BOOST_ASSERT(m_pos != 0 && "out of range"); + return m_plst->GetAt(m_pos); + } + + // A B C D x + // Head Tail NULL(0) + // + void increment() + { + BOOST_ASSERT(m_pos != 0 && "out of range"); + m_plst->GetNext(m_pos); + } + + void decrement() + { + if (m_pos == 0) { + m_pos = m_plst->GetTailPosition(); + return; + } + + m_plst->GetPrev(m_pos); + } + + bool equal(self_t const& other) const + { + BOOST_ASSERT(m_plst == other.m_plst && "iterators incompatible"); + return m_pos == other.m_pos; + } + }; + + + // customization helpers + // + + struct array_functions + { + template< class Iterator, class X > + Iterator begin(X& x) + { + return x.GetData(); + } + + template< class Iterator, class X > + Iterator end(X& x) + { + return begin(x) + x.GetSize(); + } + }; + + + struct list_functions + { + template< class Iterator, class X > + Iterator begin(X& x) + { + return Iterator(x, x.GetHeadPosition()); + } + + template< class Iterator, class X > + Iterator end(X& x) + { + return Iterator(x, POSITION(0)); + } + }; + + +} } // namespace boost::range_detail_microsoft + + + + +// test +// + + +#if defined(BOOST_RANGE_DETAIL_MICROSOFT_TEST) + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { namespace range_detail_microsoft { + + + template< class Range1, class Range2 > + bool test_equals(Range1 const& rng1, Range2 const& rng2) + { + return + boost::distance(rng1) == boost::distance(rng2) && + std::equal(boost::begin(rng1), boost::end(rng1), boost::begin(rng2)) + ; + } + + + template< class AssocContainer, class PairT > + bool test_find_key_and_mapped(AssocContainer const& ac, PairT const& pa) + { + typedef typename boost::range_const_iterator::type iter_t; + for (iter_t it = boost::const_begin(ac), last = boost::const_end(ac); it != last; ++it) { + if (it->first == pa.first && it->second == pa.second) + return true; + } + + return false; + } + + + // test functions + // + + template< class Range > + bool test_emptiness(Range& ) + { + bool result = true; + + Range emptyRng; + result = result && boost::empty(emptyRng); + + return result; + } + + + template< class Range > + bool test_trivial(Range& rng) + { + bool result = true; + + // convertibility check + typedef typename range_const_iterator::type citer_t; + citer_t cit = boost::begin(rng); + (void)cit; // unused + + // mutability check + typedef typename range_value::type val_t; + val_t v = *boost::begin(rng); + *boost::begin(rng) = v; + result = result && *boost::begin(rng) == v; + + return result; + } + + + template< class Range > + bool test_forward(Range& rng) + { + boost::function_requires< ForwardRangeConcept >(); + + bool result = (test_trivial)(rng); + + typedef typename range_value::type val_t; + + std::vector saved; + std::copy(boost::begin(rng), boost::end(rng), std::back_inserter(saved)); + std::rotate(boost::begin(saved), boost::next(boost::begin(saved)), boost::end(saved)); + + std::rotate(boost::begin(rng), boost::next(boost::begin(rng)), boost::end(rng)); + + return result && (test_equals)(saved, rng); + }; + + + template< class Range > + bool test_bidirectional(Range& rng) + { + boost::function_requires< BidirectionalRangeConcept >(); + + bool result = (test_forward)(rng); + + typedef typename range_value::type val_t; + + std::vector saved; + std::copy(boost::begin(rng), boost::end(rng), std::back_inserter(saved)); + + result = result && (test_equals)( + boost::make_iterator_range(boost::rbegin(saved), boost::rend(saved)), + boost::make_iterator_range(boost::rbegin(rng), boost::rend(rng)) + ); + + return result; + } + + + template< class Range > + bool test_random_access(Range& rng) + { + boost::function_requires< RandomAccessRangeConcept >(); + + bool result = (test_bidirectional)(rng); + + typedef typename range_value::type val_t; + + std::vector saved; + std::copy(boost::begin(rng), boost::end(rng), std::back_inserter(saved)); + std::sort(boost::begin(saved), boost::end(saved)); + + std::random_shuffle(boost::begin(rng), boost::end(rng)); + std::sort(boost::begin(rng), boost::end(rng)); + result = result && (test_equals)(rng, saved); + + std::random_shuffle(boost::begin(rng), boost::end(rng)); + std::stable_sort(boost::begin(rng), boost::end(rng)); + result = result && (test_equals)(rng, saved); + + std::random_shuffle(boost::begin(rng), boost::end(rng)); + std::partial_sort(boost::begin(rng), boost::end(rng), boost::end(rng)); + result = result && (test_equals)(rng, saved); + + return result; + } + + + // initializer + // + + template< class ArrayT, class SampleRange > + bool test_init_array(ArrayT& arr, SampleRange const& sample) + { + typedef typename range_const_iterator::type iter_t; + typedef typename range_value::type val_t; + + for (iter_t it = boost::const_begin(sample), last = boost::const_end(sample); it != last; ++it) { + val_t v = *it; // works around ATL3 CSimpleArray + arr.Add(v); + } + + return (test_equals)(arr, sample); + } + + + template< class ListT, class SampleRange > + bool test_init_list(ListT& lst, SampleRange const& sample) + { + typedef typename range_const_iterator::type iter_t; + + for (iter_t it = boost::const_begin(sample), last = boost::const_end(sample); it != last; ++it) { + lst.AddTail(*it); + } + + return (test_equals)(lst, sample); + } + + + template< class StringT, class SampleRange > + bool test_init_string(StringT& str, SampleRange const& sample) + { + typedef typename range_const_iterator::type iter_t; + typedef typename range_value::type val_t; + + for (iter_t it = boost::const_begin(sample), last = boost::const_end(sample); it != last; ++it) { + str += *it; + } + + return (test_equals)(str, sample); + } + + + template< class MapT, class SampleMap > + bool test_init_map(MapT& map, SampleMap const& sample) + { + typedef typename range_const_iterator::type iter_t; + + for (iter_t it = boost::const_begin(sample), last = boost::const_end(sample); it != last; ++it) { + map.SetAt(it->first, it->second); + } + + return boost::distance(map) == boost::distance(sample); + } + + + // metafunction test + // + + template< class Range, class Iter > + struct test_mutable_iter : + boost::is_same< typename boost::BOOST_RANGE_DETAIL_MICROSOFT_range_mutable_iterator::type, Iter > + { }; + + + template< class Range, class Iter > + struct test_const_iter : + boost::is_same< typename boost::range_const_iterator::type, Iter > + { }; + + +} } // namespace boost::range_detail_microsoft + + +#endif // defined(BOOST_RANGE_DETAIL_MICROSOFT_TEST) + + + +#endif diff --git a/libs/range/include/boost/range/detail/misc_concept.hpp b/libs/range/include/boost/range/detail/misc_concept.hpp new file mode 100644 index 00000000..74cb919f --- /dev/null +++ b/libs/range/include/boost/range/detail/misc_concept.hpp @@ -0,0 +1,33 @@ +// Boost.Range library concept checks +// +// Copyright Neil Groves 2009. Use, modification and distribution +// are subject to 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) +// +#ifndef BOOST_RANGE_DETAIL_MISC_CONCEPT_HPP_INCLUDED +#define BOOST_RANGE_DETAIL_MISC_CONCEPT_HPP_INCLUDED + +#include + +namespace boost +{ + namespace range_detail + { + template + class SameTypeConcept + { + public: + BOOST_CONCEPT_USAGE(SameTypeConcept) + { + same_type(a,b); + } + private: + template void same_type(T,T) {} + T1 a; + T2 b; + }; + } +} + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/msvc_has_iterator_workaround.hpp b/libs/range/include/boost/range/detail/msvc_has_iterator_workaround.hpp new file mode 100644 index 00000000..62b67fd5 --- /dev/null +++ b/libs/range/include/boost/range/detail/msvc_has_iterator_workaround.hpp @@ -0,0 +1,132 @@ +// Boost.Range library +// +// Copyright Eric Niebler 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_DETAIL_MSVC_HAS_ITERATOR_WORKAROUND_HPP +#define BOOST_RANGE_DETAIL_MSVC_HAS_ITERATOR_WORKAROUND_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#ifndef BOOST_RANGE_MUTABLE_ITERATOR_HPP +# error This file should only be included from +#endif + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1600) +namespace boost +{ +namespace cb_details +{ + template + struct iterator; +} + +namespace python +{ + template + struct iterator; +} + +namespace type_erasure +{ + template< + class Traversal, + class T /*= _self*/, + class Reference /*= ::boost::use_default*/, + class DifferenceType /*= ::std::ptrdiff_t*/, + class ValueType /*= typename deduced >::type*/ + > + struct iterator; +} + +namespace unordered { namespace iterator_detail +{ + template + struct iterator; +}} + +namespace container { namespace container_detail +{ + template + class iterator; +}} + +namespace spirit { namespace lex { namespace lexertl +{ + template + class iterator; +}}} + +namespace range_detail +{ + template + struct has_iterator< ::boost::cb_details::iterator > + : mpl::false_ + {}; + + template + struct has_iterator< ::boost::cb_details::iterator const> + : mpl::false_ + {}; + + template + struct has_iterator< ::boost::python::iterator > + : mpl::false_ + {}; + + template + struct has_iterator< ::boost::python::iterator const> + : mpl::false_ + {}; + + template + struct has_iterator< ::boost::type_erasure::iterator > + : mpl::false_ + {}; + + template + struct has_iterator< ::boost::type_erasure::iterator const> + : mpl::false_ + {}; + + template + struct has_iterator< ::boost::unordered::iterator_detail::iterator > + : mpl::false_ + {}; + + template + struct has_iterator< ::boost::unordered::iterator_detail::iterator const> + : mpl::false_ + {}; + + template + struct has_iterator< ::boost::container::container_detail::iterator > + : mpl::false_ + {}; + + template + struct has_iterator< ::boost::container::container_detail::iterator const> + : mpl::false_ + {}; + + template + struct has_iterator< ::boost::spirit::lex::lexertl::iterator > + : mpl::false_ + {}; + + template + struct has_iterator< ::boost::spirit::lex::lexertl::iterator const> + : mpl::false_ + {}; +} +} +#endif +#endif diff --git a/libs/range/include/boost/range/detail/range_return.hpp b/libs/range/include/boost/range/detail/range_return.hpp new file mode 100644 index 00000000..9b98e099 --- /dev/null +++ b/libs/range/include/boost/range/detail/range_return.hpp @@ -0,0 +1,181 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_DETAIL_RANGE_RETURN_HPP_INCLUDED +#define BOOST_RANGE_DETAIL_RANGE_RETURN_HPP_INCLUDED + +#include +#include +#include +#include + +namespace boost +{ + enum range_return_value + { + // (*) indicates the most common values + return_found, // only the found resulting iterator (*) + return_next, // next(found) iterator + return_prior, // prior(found) iterator + return_begin_found, // [begin, found) range (*) + return_begin_next, // [begin, next(found)) range + return_begin_prior, // [begin, prior(found)) range + return_found_end, // [found, end) range (*) + return_next_end, // [next(found), end) range + return_prior_end, // [prior(found), end) range + return_begin_end // [begin, end) range + }; + + template< class SinglePassRange, range_return_value > + struct range_return + { + typedef boost::iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator::type > type; + + static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, + SinglePassRange& rng) + { + return type(found, boost::end(rng)); + } + }; + + template< class SinglePassRange > + struct range_return< SinglePassRange, return_found > + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type type; + + static type pack(type found, SinglePassRange&) + { + return found; + } + }; + + template< class SinglePassRange > + struct range_return< SinglePassRange, return_next > + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type type; + + static type pack(type found, SinglePassRange& rng) + { + return found == boost::end(rng) + ? found + : boost::next(found); + } + }; + + template< class BidirectionalRange > + struct range_return< BidirectionalRange, return_prior > + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type type; + + static type pack(type found, BidirectionalRange& rng) + { + return found == boost::begin(rng) + ? found + : boost::prior(found); + } + }; + + template< class SinglePassRange > + struct range_return< SinglePassRange, return_begin_found > + { + typedef boost::iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator::type > type; + + static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, + SinglePassRange& rng) + { + return type(boost::begin(rng), found); + } + }; + + template< class SinglePassRange > + struct range_return< SinglePassRange, return_begin_next > + { + typedef boost::iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator::type > type; + + static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, + SinglePassRange& rng) + { + return type( boost::begin(rng), + found == boost::end(rng) ? found : boost::next(found) ); + } + }; + + template< class BidirectionalRange > + struct range_return< BidirectionalRange, return_begin_prior > + { + typedef boost::iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator::type > type; + + static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, + BidirectionalRange& rng) + { + return type( boost::begin(rng), + found == boost::begin(rng) ? found : boost::prior(found) ); + } + }; + + template< class SinglePassRange > + struct range_return< SinglePassRange, return_found_end > + { + typedef boost::iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator::type > type; + + static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, + SinglePassRange& rng) + { + return type(found, boost::end(rng)); + } + }; + + template< class SinglePassRange > + struct range_return< SinglePassRange, return_next_end > + { + typedef boost::iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator::type > type; + + static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, + SinglePassRange& rng) + { + return type( found == boost::end(rng) ? found : boost::next(found), + boost::end(rng) ); + } + }; + + template< class BidirectionalRange > + struct range_return< BidirectionalRange, return_prior_end > + { + typedef boost::iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator::type > type; + + static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type found, + BidirectionalRange& rng) + { + return type( found == boost::begin(rng) ? found : boost::prior(found), + boost::end(rng) ); + } + }; + + template< class SinglePassRange > + struct range_return< SinglePassRange, return_begin_end > + { + typedef boost::iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator::type > type; + + static type pack(BOOST_DEDUCED_TYPENAME range_iterator::type, + SinglePassRange& rng) + { + return type(boost::begin(rng), boost::end(rng)); + } + }; + +} + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/safe_bool.hpp b/libs/range/include/boost/range/detail/safe_bool.hpp new file mode 100644 index 00000000..182e5104 --- /dev/null +++ b/libs/range/include/boost/range/detail/safe_bool.hpp @@ -0,0 +1,72 @@ +// This header intentionally has no include guards. +// +// Copyright (c) 2010 Neil Groves +// 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 +// +// This code utilises the experience gained during the evolution of +// +#ifndef BOOST_RANGE_SAFE_BOOL_INCLUDED_HPP +#define BOOST_RANGE_SAFE_BOOL_INCLUDED_HPP + +#include +#include + +namespace boost +{ + namespace range_detail + { + +template +class safe_bool +{ +public: + typedef safe_bool this_type; + +#if (defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570)) || defined(__CINT_) + typedef bool unspecified_bool_type; + static unspecified_bool_type to_unspecified_bool(const bool x, DataMemberPtr) + { + return x; + } +#elif defined(_MANAGED) + static void unspecified_bool(this_type***) + { + } + typedef void(*unspecified_bool_type)(this_type***); + static unspecified_bool_type to_unspecified_bool(const bool x, DataMemberPtr) + { + return x ? unspecified_bool : 0; + } +#elif \ + ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ + ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \ + ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) + + typedef bool (this_type::*unspecified_bool_type)() const; + + static unspecified_bool_type to_unspecified_bool(const bool x, DataMemberPtr) + { + return x ? &this_type::detail_safe_bool_member_fn : 0; + } +private: + bool detail_safe_bool_member_fn() const { return false; } +#else + typedef DataMemberPtr unspecified_bool_type; + static unspecified_bool_type to_unspecified_bool(const bool x, DataMemberPtr p) + { + return x ? p : 0; + } +#endif +private: + safe_bool(); + safe_bool(const safe_bool&); + void operator=(const safe_bool&); + ~safe_bool(); +}; + + } // namespace range_detail +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/detail/sfinae.hpp b/libs/range/include/boost/range/detail/sfinae.hpp new file mode 100644 index 00000000..5b2c61e7 --- /dev/null +++ b/libs/range/include/boost/range/detail/sfinae.hpp @@ -0,0 +1,77 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_DETAIL_SFINAE_HPP +#define BOOST_RANGE_DETAIL_SFINAE_HPP + +#include +#include +#include +#include + + +namespace boost +{ + namespace range_detail + { + using type_traits::yes_type; + using type_traits::no_type; + + ////////////////////////////////////////////////////////////////////// + // string + ////////////////////////////////////////////////////////////////////// + + yes_type is_string_impl( const char* const ); + yes_type is_string_impl( const wchar_t* const ); + no_type is_string_impl( ... ); + + template< std::size_t sz > + yes_type is_char_array_impl( char BOOST_RANGE_ARRAY_REF()[sz] ); + template< std::size_t sz > + yes_type is_char_array_impl( const char BOOST_RANGE_ARRAY_REF()[sz] ); + no_type is_char_array_impl( ... ); + + template< std::size_t sz > + yes_type is_wchar_t_array_impl( wchar_t BOOST_RANGE_ARRAY_REF()[sz] ); + template< std::size_t sz > + yes_type is_wchar_t_array_impl( const wchar_t BOOST_RANGE_ARRAY_REF()[sz] ); + no_type is_wchar_t_array_impl( ... ); + + yes_type is_char_ptr_impl( char* const ); + no_type is_char_ptr_impl( ... ); + + yes_type is_const_char_ptr_impl( const char* const ); + no_type is_const_char_ptr_impl( ... ); + + yes_type is_wchar_t_ptr_impl( wchar_t* const ); + no_type is_wchar_t_ptr_impl( ... ); + + yes_type is_const_wchar_t_ptr_impl( const wchar_t* const ); + no_type is_const_wchar_t_ptr_impl( ... ); + + ////////////////////////////////////////////////////////////////////// + // pair + ////////////////////////////////////////////////////////////////////// + + template< typename Iterator > + yes_type is_pair_impl( const std::pair* ); + no_type is_pair_impl( ... ); + + ////////////////////////////////////////////////////////////////////// + // tags + ////////////////////////////////////////////////////////////////////// + + struct char_or_wchar_t_array_tag {}; + + } // namespace 'range_detail' + +} // namespace 'boost' + +#endif diff --git a/libs/range/include/boost/range/detail/sizer.hpp b/libs/range/include/boost/range/detail/sizer.hpp new file mode 100644 index 00000000..cd6679c2 --- /dev/null +++ b/libs/range/include/boost/range/detail/sizer.hpp @@ -0,0 +1,35 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_DETAIL_SIZER_HPP +#define BOOST_RANGE_DETAIL_SIZER_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include + +namespace boost +{ + ////////////////////////////////////////////////////////////////////// + // constant array size + ////////////////////////////////////////////////////////////////////// + + template< typename T, std::size_t sz > + char (& sizer( const T BOOST_RANGE_ARRAY_REF()[sz] ) )[sz]; + + template< typename T, std::size_t sz > + char (& sizer( T BOOST_RANGE_ARRAY_REF()[sz] ) )[sz]; + +} // namespace 'boost' + +#endif diff --git a/libs/range/include/boost/range/detail/str_types.hpp b/libs/range/include/boost/range/detail/str_types.hpp new file mode 100644 index 00000000..f8cab190 --- /dev/null +++ b/libs/range/include/boost/range/detail/str_types.hpp @@ -0,0 +1,38 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_DETAIL_STR_TYPES_HPP +#define BOOST_RANGE_DETAIL_STR_TYPES_HPP + +#include +#include + +namespace boost +{ + template< class T > + struct range_mutable_iterator + { + typedef T* type; + }; + + template< class T > + struct range_const_iterator + { + typedef const T* type; + }; + + template< class T > + struct range_size + { + typedef std::size_t type; + }; +} + +#endif diff --git a/libs/range/include/boost/range/difference_type.hpp b/libs/range/include/boost/range/difference_type.hpp new file mode 100644 index 00000000..6bb3c5f5 --- /dev/null +++ b/libs/range/include/boost/range/difference_type.hpp @@ -0,0 +1,47 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_DIFFERENCE_TYPE_HPP +#define BOOST_RANGE_DIFFERENCE_TYPE_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + template< class T, bool B = has_type >::value > + struct range_difference + { }; + + template< class T > + struct range_difference + : iterator_difference< + BOOST_DEDUCED_TYPENAME range_iterator::type + > + { }; + } + + template< class T > + struct range_difference + : range_detail::range_difference::type> + { }; +} + +#endif diff --git a/libs/range/include/boost/range/distance.hpp b/libs/range/include/boost/range/distance.hpp new file mode 100644 index 00000000..5b82cf0c --- /dev/null +++ b/libs/range/include/boost/range/distance.hpp @@ -0,0 +1,40 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_DISTANCE_HPP +#define BOOST_RANGE_DISTANCE_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include +#include + +namespace boost +{ + + namespace range_distance_adl_barrier + { + template< class T > + inline BOOST_CXX14_CONSTEXPR BOOST_DEDUCED_TYPENAME range_difference::type + distance( const T& r ) + { + return boost::iterators::distance( boost::begin( r ), boost::end( r ) ); + } + } + + using namespace range_distance_adl_barrier; + +} // namespace 'boost' + +#endif diff --git a/libs/range/include/boost/range/empty.hpp b/libs/range/include/boost/range/empty.hpp new file mode 100644 index 00000000..d57a30ed --- /dev/null +++ b/libs/range/include/boost/range/empty.hpp @@ -0,0 +1,34 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_EMPTY_HPP +#define BOOST_RANGE_EMPTY_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ + + template< class T > + inline bool empty( const T& r ) + { + return boost::begin( r ) == boost::end( r ); + } + +} // namespace 'boost' + + +#endif diff --git a/libs/range/include/boost/range/end.hpp b/libs/range/include/boost/range/end.hpp new file mode 100644 index 00000000..33259097 --- /dev/null +++ b/libs/range/include/boost/range/end.hpp @@ -0,0 +1,130 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_END_HPP +#define BOOST_RANGE_END_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include + +#include +#include +#include +#include +#include + +namespace boost +{ + +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +namespace range_detail +{ +#endif + + ////////////////////////////////////////////////////////////////////// + // primary template + ////////////////////////////////////////////////////////////////////// + template< typename C > + BOOST_CONSTEXPR inline BOOST_DEDUCED_TYPENAME range_iterator::type + range_end( C& c ) + { + // + // If you get a compile-error here, it is most likely because + // you have not implemented range_begin() properly in + // the namespace of C + // + return c.end(); + } + + ////////////////////////////////////////////////////////////////////// + // pair + ////////////////////////////////////////////////////////////////////// + + template< typename Iterator > + BOOST_CONSTEXPR inline Iterator range_end( const std::pair& p ) + { + return p.second; + } + + template< typename Iterator > + BOOST_CONSTEXPR inline Iterator range_end( std::pair& p ) + { + return p.second; + } + + ////////////////////////////////////////////////////////////////////// + // array + ////////////////////////////////////////////////////////////////////// + + template< typename T, std::size_t sz > + BOOST_CONSTEXPR inline const T* range_end( const T (&a)[sz] ) BOOST_NOEXCEPT + { + return range_detail::array_end( a ); + } + + template< typename T, std::size_t sz > + BOOST_CONSTEXPR inline T* range_end( T (&a)[sz] ) BOOST_NOEXCEPT + { + return range_detail::array_end( a ); + } + +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +} // namespace 'range_detail' +#endif + +namespace range_adl_barrier +{ + +template< class T > +#if !BOOST_WORKAROUND(BOOST_GCC, < 40700) +BOOST_CONSTEXPR +#endif +inline BOOST_DEDUCED_TYPENAME range_iterator::type end( T& r ) +{ +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) + using namespace range_detail; +#endif + return range_end( r ); +} + +template< class T > +#if !BOOST_WORKAROUND(BOOST_GCC, < 40700) +BOOST_CONSTEXPR +#endif +inline BOOST_DEDUCED_TYPENAME range_iterator::type end( const T& r ) +{ +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) + using namespace range_detail; +#endif + return range_end( r ); +} + + } // namespace range_adl_barrier +} // namespace 'boost' + +namespace boost +{ + namespace range_adl_barrier + { + template< class T > + BOOST_CONSTEXPR inline BOOST_DEDUCED_TYPENAME range_iterator::type + const_end( const T& r ) + { + return boost::range_adl_barrier::end( r ); + } + } // namespace range_adl_barrier + using namespace range_adl_barrier; +} // namespace boost + +#endif + diff --git a/libs/range/include/boost/range/functions.hpp b/libs/range/include/boost/range/functions.hpp new file mode 100644 index 00000000..43c54b15 --- /dev/null +++ b/libs/range/include/boost/range/functions.hpp @@ -0,0 +1,27 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_FUNCTIONS_HPP +#define BOOST_RANGE_FUNCTIONS_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +#endif + diff --git a/libs/range/include/boost/range/has_range_iterator.hpp b/libs/range/include/boost/range/has_range_iterator.hpp new file mode 100644 index 00000000..88d8664d --- /dev/null +++ b/libs/range/include/boost/range/has_range_iterator.hpp @@ -0,0 +1,83 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +// Acknowledgments: +// Ticket #8341: Arno Schoedl - improved handling of has_range_iterator upon +// use-cases where T was const. +#ifndef BOOST_RANGE_HAS_ITERATOR_HPP_INCLUDED +#define BOOST_RANGE_HAS_ITERATOR_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + BOOST_MPL_HAS_XXX_TRAIT_DEF(type) + + template + struct has_range_iterator_impl + : boost::mpl::false_ + { + }; + + template + struct has_range_iterator_impl< + T, + BOOST_DEDUCED_TYPENAME ::boost::enable_if< + BOOST_DEDUCED_TYPENAME mpl::eval_if, + has_type::type> >, + has_type > + >::type + >::type + > + : boost::mpl::true_ + { + }; + + template + struct has_range_const_iterator_impl + : boost::mpl::false_ + { + }; + + template + struct has_range_const_iterator_impl< + T, + BOOST_DEDUCED_TYPENAME ::boost::enable_if< + has_type > + >::type + > + : boost::mpl::true_ + { + }; + + } // namespace range_detail + + template + struct has_range_iterator + : range_detail::has_range_iterator_impl< + BOOST_DEDUCED_TYPENAME remove_reference::type> + {}; + + template + struct has_range_const_iterator + : range_detail::has_range_const_iterator_impl< + BOOST_DEDUCED_TYPENAME remove_reference::type> + {}; +} // namespace boost + +#endif // include guard + diff --git a/libs/range/include/boost/range/irange.hpp b/libs/range/include/boost/range/irange.hpp new file mode 100644 index 00000000..7d5fee5c --- /dev/null +++ b/libs/range/include/boost/range/irange.hpp @@ -0,0 +1,243 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_IRANGE_HPP_INCLUDED +#define BOOST_RANGE_IRANGE_HPP_INCLUDED + +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + // integer_iterator is an iterator over an integer sequence that + // is bounded only by the limits of the underlying integer + // representation. + // + // This is useful for implementing the irange(first, last) + // function. + // + // Note: + // This use of this iterator and irange is appreciably less + // performant than the corresponding hand-written integer + // loop on many compilers. + template + class integer_iterator + : public boost::iterator_facade< + integer_iterator, + Integer, + boost::random_access_traversal_tag, + Integer, + std::ptrdiff_t + > + { + typedef boost::iterator_facade< + integer_iterator, + Integer, + boost::random_access_traversal_tag, + Integer, + std::ptrdiff_t + > base_t; + public: + typedef typename base_t::value_type value_type; + typedef typename base_t::difference_type difference_type; + typedef typename base_t::reference reference; + typedef std::random_access_iterator_tag iterator_category; + + integer_iterator() : m_value() {} + explicit integer_iterator(value_type x) : m_value(x) {} + + private: + void increment() + { + ++m_value; + } + + void decrement() + { + --m_value; + } + + void advance(difference_type offset) + { + m_value += offset; + } + + difference_type distance_to(const integer_iterator& other) const + { + return is_signed::value + ? (other.m_value - m_value) + : (other.m_value >= m_value) + ? static_cast(other.m_value - m_value) + : -static_cast(m_value - other.m_value); + } + + bool equal(const integer_iterator& other) const + { + return m_value == other.m_value; + } + + reference dereference() const + { + return m_value; + } + + friend class ::boost::iterator_core_access; + value_type m_value; + }; + + // integer_iterator_with_step is similar in nature to the + // integer_iterator but provides the ability to 'move' in + // a number of steps specified at construction time. + // + // The three variable implementation provides the best guarantees + // of loop termination upon various combinations of input. + // + // While this design is less performant than some less + // safe alternatives, the use of ranges and iterators to + // perform counting will never be optimal anyhow, hence + // if optimal performance is desired a hand-coded loop + // is the solution. + template + class integer_iterator_with_step + : public boost::iterator_facade< + integer_iterator_with_step, + Integer, + boost::random_access_traversal_tag, + Integer, + std::ptrdiff_t + > + { + typedef boost::iterator_facade< + integer_iterator_with_step, + Integer, + boost::random_access_traversal_tag, + Integer, + std::ptrdiff_t + > base_t; + public: + typedef typename base_t::value_type value_type; + typedef typename base_t::difference_type difference_type; + typedef typename base_t::reference reference; + typedef std::random_access_iterator_tag iterator_category; + + integer_iterator_with_step(value_type first, difference_type step, value_type step_size) + : m_first(first) + , m_step(step) + , m_step_size(step_size) + { + } + + private: + void increment() + { + ++m_step; + } + + void decrement() + { + --m_step; + } + + void advance(difference_type offset) + { + m_step += offset; + } + + difference_type distance_to(const integer_iterator_with_step& other) const + { + return other.m_step - m_step; + } + + bool equal(const integer_iterator_with_step& other) const + { + return m_step == other.m_step; + } + + reference dereference() const + { + return m_first + (m_step * m_step_size); + } + + friend class ::boost::iterator_core_access; + value_type m_first; + difference_type m_step; + difference_type m_step_size; + }; + + } // namespace range_detail + + template + class integer_range + : public iterator_range< range_detail::integer_iterator > + { + typedef range_detail::integer_iterator iterator_t; + typedef iterator_range base_t; + public: + integer_range(Integer first, Integer last) + : base_t(iterator_t(first), iterator_t(last)) + { + } + }; + + template + class strided_integer_range + : public iterator_range< range_detail::integer_iterator_with_step > + { + typedef range_detail::integer_iterator_with_step iterator_t; + typedef iterator_range base_t; + public: + template + strided_integer_range(Iterator first, Iterator last) + : base_t(first, last) + { + } + }; + + template + integer_range + irange(Integer first, Integer last) + { + BOOST_ASSERT( first <= last ); + return integer_range(first, last); + } + + template + strided_integer_range + irange(Integer first, Integer last, StepSize step_size) + { + BOOST_ASSERT( step_size != 0 ); + BOOST_ASSERT( (step_size > 0) ? (last >= first) : (last <= first) ); + + typedef typename range_detail::integer_iterator_with_step iterator_t; + + const std::ptrdiff_t sz = static_cast(step_size >= 0 ? step_size : -step_size); + const Integer l = step_size >= 0 ? last : first; + const Integer f = step_size >= 0 ? first : last; + const std::ptrdiff_t num_steps = (l - f) / sz + ((l - f) % sz ? 1 : 0); + BOOST_ASSERT(num_steps >= 0); + + return strided_integer_range( + iterator_t(first, 0, step_size), + iterator_t(first, num_steps, step_size)); + } + + template + integer_range + irange(Integer last) + { + return integer_range(static_cast(0), last); + } + +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/istream_range.hpp b/libs/range/include/boost/range/istream_range.hpp new file mode 100644 index 00000000..a4863171 --- /dev/null +++ b/libs/range/include/boost/range/istream_range.hpp @@ -0,0 +1,37 @@ +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ISTREAM_RANGE_HPP_INCLUDED +#define BOOST_RANGE_ISTREAM_RANGE_HPP_INCLUDED + +/*! + * \file istream_range.hpp + */ + +#include +#include +#include +#include + +namespace boost +{ + namespace range + { + template inline + iterator_range > + istream_range(std::basic_istream& in) + { + return iterator_range >( + std::istream_iterator(in), + std::istream_iterator()); + } + } // namespace range + using range::istream_range; +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/iterator.hpp b/libs/range/include/boost/range/iterator.hpp new file mode 100644 index 00000000..2956353a --- /dev/null +++ b/libs/range/include/boost/range/iterator.hpp @@ -0,0 +1,74 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ITERATOR_HPP +#define BOOST_RANGE_ITERATOR_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + +#if BOOST_WORKAROUND(BOOST_MSVC, == 1310) + + namespace range_detail_vc7_1 + { + template< typename C, typename Sig = void(C) > + struct range_iterator + { + typedef BOOST_RANGE_DEDUCED_TYPENAME + mpl::eval_if_c< is_const::value, + range_const_iterator< typename remove_const::type >, + range_mutable_iterator >::type type; + }; + + template< typename C, typename T > + struct range_iterator< C, void(T[]) > + { + typedef T* type; + }; + } + + template< typename C, typename Enabler=void > + struct range_iterator + { + + typedef BOOST_RANGE_DEDUCED_TYPENAME + range_detail_vc7_1::range_iterator::type type; + + }; + +#else + + template< typename C, typename Enabler=void > + struct range_iterator + : mpl::if_c< + is_const::type>::value, + range_const_iterator::type>::type>, + range_mutable_iterator::type> + >::type + { + }; + +#endif + +} // namespace boost + +#endif diff --git a/libs/range/include/boost/range/iterator_range.hpp b/libs/range/include/boost/range/iterator_range.hpp new file mode 100644 index 00000000..dfcd4d2f --- /dev/null +++ b/libs/range/include/boost/range/iterator_range.hpp @@ -0,0 +1,16 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. +// Use, modification and distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ITERATOR_RANGE_HPP_INCLUDED +#define BOOST_RANGE_ITERATOR_RANGE_HPP_INCLUDED + +#include "boost/range/iterator_range_core.hpp" +#include "boost/range/iterator_range_io.hpp" + +#endif // include guard diff --git a/libs/range/include/boost/range/iterator_range_core.hpp b/libs/range/include/boost/range/iterator_range_core.hpp new file mode 100644 index 00000000..e6d55d3b --- /dev/null +++ b/libs/range/include/boost/range/iterator_range_core.hpp @@ -0,0 +1,852 @@ +// Boost.Range library +// +// Copyright Neil Groves & Thorsten Ottosen & Pavol Droba 2003-2004. +// Use, modification and distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +// Credits: +// 'michel' reported Trac 9072 which included a patch for allowing references +// to function types. +// +#ifndef BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED +#define BOOST_RANGE_ITERATOR_RANGE_CORE_HPP_INCLUDED + +#include // Define __STL_CONFIG_H, if appropriate. +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) + #pragma warning( push ) + #pragma warning( disable : 4996 ) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*! \file + Defines the \c iterator_class and related functions. + \c iterator_range is a simple wrapper of iterator pair idiom. It provides + a rich subset of Container interface. +*/ + + +namespace boost +{ + namespace iterator_range_detail + { + // + // The functions adl_begin and adl_end are implemented in a separate + // class for gcc-2.9x + // + template + struct iterator_range_impl { + template< class ForwardRange > + static IteratorT adl_begin( ForwardRange& r ) + { + return IteratorT( boost::begin( r ) ); + } + + template< class ForwardRange > + static IteratorT adl_end( ForwardRange& r ) + { + return IteratorT( boost::end( r ) ); + } + }; + + template< class Left, class Right > + inline bool less_than( const Left& l, const Right& r ) + { + return std::lexicographical_compare( boost::begin(l), + boost::end(l), + boost::begin(r), + boost::end(r) ); + } + + template< class Left, class Right > + inline bool greater_than( const Left& l, const Right& r ) + { + return iterator_range_detail::less_than(r,l); + } + + template< class Left, class Right > + inline bool less_or_equal_than( const Left& l, const Right& r ) + { + return !iterator_range_detail::less_than(r,l); + } + + template< class Left, class Right > + inline bool greater_or_equal_than( const Left& l, const Right& r ) + { + return !iterator_range_detail::less_than(l,r); + } + + // This version is maintained since it is used in other boost libraries + // such as Boost.Assign + template< class Left, class Right > + inline bool equal(const Left& l, const Right& r) + { + return boost::equal(l, r); + } + +struct range_tag +{ +}; + +struct const_range_tag +{ +}; + +struct iterator_range_tag +{ +}; + +typedef char (&incrementable_t)[1]; +typedef char (&bidirectional_t)[2]; +typedef char (&random_access_t)[3]; + +incrementable_t test_traversal_tag(boost::incrementable_traversal_tag); +bidirectional_t test_traversal_tag(boost::bidirectional_traversal_tag); +random_access_t test_traversal_tag(boost::random_access_traversal_tag); + +template +struct pure_iterator_traversal_impl +{ + typedef boost::incrementable_traversal_tag type; +}; + +template<> +struct pure_iterator_traversal_impl +{ + typedef boost::bidirectional_traversal_tag type; +}; + +template<> +struct pure_iterator_traversal_impl +{ + typedef boost::random_access_traversal_tag type; +}; + +template +struct pure_iterator_traversal +{ + typedef + BOOST_DEDUCED_TYPENAME iterator_traversal::type + traversal_t; + BOOST_STATIC_CONSTANT( + std::size_t, + traversal_i = sizeof(iterator_range_detail::test_traversal_tag((traversal_t()))) + ); + typedef + BOOST_DEDUCED_TYPENAME pure_iterator_traversal_impl::type + type; +}; + +template +class iterator_range_base + : public iterator_range_tag +{ + typedef range_detail::safe_bool< + IteratorT iterator_range_base::* + > safe_bool_t; + + typedef iterator_range_base type; + +protected: + typedef iterator_range_impl impl; + +public: + typedef BOOST_DEDUCED_TYPENAME + safe_bool_t::unspecified_bool_type unspecified_bool_type; + + typedef BOOST_DEDUCED_TYPENAME + iterator_value::type value_type; + + typedef BOOST_DEDUCED_TYPENAME + iterator_difference::type difference_type; + + typedef std::size_t size_type; // note: must be unsigned + + // Needed because value-type is the same for + // const and non-const iterators + typedef BOOST_DEDUCED_TYPENAME + iterator_reference::type reference; + + //! const_iterator type + /*! + There is no distinction between const_iterator and iterator. + These typedefs are provides to fulfill container interface + */ + typedef IteratorT const_iterator; + //! iterator type + typedef IteratorT iterator; + +protected: + iterator_range_base() + : m_Begin() + , m_End() + { + } + + template + iterator_range_base(Iterator Begin, Iterator End) + : m_Begin(Begin) + , m_End(End) + { + } + +public: + IteratorT begin() const + { + return m_Begin; + } + + IteratorT end() const + { + return m_End; + } + + bool empty() const + { + return m_Begin == m_End; + } + + operator unspecified_bool_type() const + { + return safe_bool_t::to_unspecified_bool( + m_Begin != m_End, &iterator_range_base::m_Begin); + } + + bool operator!() const + { + return empty(); + } + + bool equal(const iterator_range_base& r) const + { + return m_Begin == r.m_Begin && m_End == r.m_End; + } + + reference front() const + { + BOOST_ASSERT(!empty()); + return *m_Begin; + } + + void drop_front() + { + BOOST_ASSERT(!empty()); + ++m_Begin; + } + + void drop_front(difference_type n) + { + BOOST_ASSERT(n >= difference_type()); + std::advance(this->m_Begin, n); + } + + // Deprecated + void pop_front() { drop_front(); } + +protected: + template + void assign(Iterator first, Iterator last) + { + m_Begin = first; + m_End = last; + } + + template + void assign(const SinglePassRange& r) + { + m_Begin = impl::adl_begin(r); + m_End = impl::adl_end(r); + } + + template + void assign(SinglePassRange& r) + { + m_Begin = impl::adl_begin(r); + m_End = impl::adl_end(r); + } + + IteratorT m_Begin; + IteratorT m_End; +}; + +template +class iterator_range_base + : public iterator_range_base +{ + typedef iterator_range_base base_type; + +protected: + iterator_range_base() + { + } + + template + iterator_range_base(Iterator first, Iterator last) + : base_type(first, last) + { + } + +public: + typedef BOOST_DEDUCED_TYPENAME base_type::difference_type difference_type; + typedef BOOST_DEDUCED_TYPENAME base_type::reference reference; + + reference back() const + { + BOOST_ASSERT(!this->empty()); + return *boost::prior(this->m_End); + } + + void drop_back() + { + BOOST_ASSERT(!this->empty()); + --this->m_End; + } + + void drop_back(difference_type n) + { + BOOST_ASSERT(n >= difference_type()); + std::advance(this->m_End, -n); + } + + // Deprecated + void pop_back() { drop_back(); } +}; + +template +class iterator_range_base + : public iterator_range_base +{ + typedef iterator_range_base< + IteratorT, bidirectional_traversal_tag> base_type; + +public: + typedef BOOST_DEDUCED_TYPENAME + boost::mpl::if_< + boost::mpl::or_< + boost::is_abstract< + BOOST_DEDUCED_TYPENAME base_type::value_type + >, + boost::is_array< + BOOST_DEDUCED_TYPENAME base_type::value_type + >, + boost::is_function< + BOOST_DEDUCED_TYPENAME base_type::value_type + > + >, + BOOST_DEDUCED_TYPENAME base_type::reference, + BOOST_DEDUCED_TYPENAME base_type::value_type + >::type abstract_value_type; + + // Rationale: + // typedef these here to reduce verbiage in the implementation of this + // type. + typedef BOOST_DEDUCED_TYPENAME base_type::difference_type difference_type; + typedef BOOST_DEDUCED_TYPENAME base_type::size_type size_type; + typedef BOOST_DEDUCED_TYPENAME base_type::reference reference; + +protected: + iterator_range_base() + { + } + + template + iterator_range_base(Iterator first, Iterator last) + : base_type(first, last) + { + } + +public: + reference operator[](difference_type at) const + { + BOOST_ASSERT(at >= 0); + BOOST_ASSERT(static_cast(at) < size()); + return this->m_Begin[at]; + } + + // + // When storing transform iterators, operator[]() + // fails because it returns by reference. Therefore + // operator()() is provided for these cases. + // + abstract_value_type operator()(difference_type at) const + { + BOOST_ASSERT(at >= 0); + BOOST_ASSERT(static_cast(at) < size()); + return this->m_Begin[at]; + } + + BOOST_DEDUCED_TYPENAME base_type::size_type size() const + { + return this->m_End - this->m_Begin; + } +}; + + } + +// iterator range template class -----------------------------------------// + + //! iterator_range class + /*! + An \c iterator_range delimits a range in a sequence by beginning and ending iterators. + An iterator_range can be passed to an algorithm which requires a sequence as an input. + For example, the \c toupper() function may be used most frequently on strings, + but can also be used on iterator_ranges: + + \code + boost::tolower( find( s, "UPPERCASE STRING" ) ); + \endcode + + Many algorithms working with sequences take a pair of iterators, + delimiting a working range, as an arguments. The \c iterator_range class is an + encapsulation of a range identified by a pair of iterators. + It provides a collection interface, + so it is possible to pass an instance to an algorithm requiring a collection as an input. + */ + template + class iterator_range + : public iterator_range_detail::iterator_range_base< + IteratorT, + BOOST_DEDUCED_TYPENAME iterator_range_detail::pure_iterator_traversal::type + > + { + typedef iterator_range_detail::iterator_range_base< + IteratorT, + BOOST_DEDUCED_TYPENAME iterator_range_detail::pure_iterator_traversal::type + > base_type; + + template + struct is_compatible_range_ + : is_convertible< + BOOST_DEDUCED_TYPENAME mpl::eval_if< + has_range_iterator, + range_iterator, + mpl::identity + >::type, + BOOST_DEDUCED_TYPENAME base_type::iterator + > + { + }; + + template + struct is_compatible_range + : mpl::and_< + mpl::not_< + is_convertible< + Source, + BOOST_DEDUCED_TYPENAME base_type::iterator + > + >, + is_compatible_range_ + > + { + }; + + protected: + typedef iterator_range_detail::iterator_range_impl impl; + + public: + typedef iterator_range type; + + iterator_range() + { + } + + template + iterator_range(Iterator first, Iterator last) + : base_type(first, last) + { + } + + template + iterator_range( + const SinglePassRange& r, + BOOST_DEDUCED_TYPENAME ::boost::enable_if< + is_compatible_range + >::type* = 0 + ) + : base_type(impl::adl_begin(r), impl::adl_end(r)) + { + } + + template + iterator_range( + SinglePassRange& r, + BOOST_DEDUCED_TYPENAME ::boost::enable_if< + is_compatible_range + >::type* = 0 + ) + : base_type(impl::adl_begin(r), impl::adl_end(r)) + { + } + + template + iterator_range(const SinglePassRange& r, + iterator_range_detail::const_range_tag) + : base_type(impl::adl_begin(r), impl::adl_end(r)) + { + } + + template + iterator_range(SinglePassRange& r, + iterator_range_detail::range_tag) + : base_type(impl::adl_begin(r), impl::adl_end(r)) + { + } + + template + iterator_range& operator=(const iterator_range& other) + { + this->assign(other.begin(), other.end()); + return *this; + } + + template + iterator_range& operator=(iterator_range& other) + { + this->assign(other.begin(), other.end()); + return *this; + } + + template + iterator_range& operator=(SinglePassRange& r) + { + this->assign(r); + return *this; + } + + template + iterator_range& operator=(const SinglePassRange& r) + { + this->assign(r); + return *this; + } + + iterator_range& advance_begin( + BOOST_DEDUCED_TYPENAME base_type::difference_type n) + { + std::advance(this->m_Begin, n); + return *this; + } + + iterator_range& advance_end( + BOOST_DEDUCED_TYPENAME base_type::difference_type n) + { + std::advance(this->m_End, n); + return *this; + } + + protected: + // + // Allow subclasses an easy way to access the + // base type + // + typedef iterator_range iterator_range_; + }; + +// iterator range free-standing operators ---------------------------// + + ///////////////////////////////////////////////////////////////////// + // comparison operators + ///////////////////////////////////////////////////////////////////// + + template< class IteratorT, class ForwardRange > + inline BOOST_DEDUCED_TYPENAME boost::enable_if< + mpl::not_ >, + bool + >::type + operator==( const ForwardRange& l, const iterator_range& r ) + { + return boost::equal( l, r ); + } + + template< class IteratorT, class ForwardRange > + inline BOOST_DEDUCED_TYPENAME boost::enable_if< + mpl::not_ >, + bool + >::type + operator!=( const ForwardRange& l, const iterator_range& r ) + { + return !boost::equal( l, r ); + } + + template< class IteratorT, class ForwardRange > + inline BOOST_DEDUCED_TYPENAME boost::enable_if< + mpl::not_ >, + bool + >::type + operator<( const ForwardRange& l, const iterator_range& r ) + { + return iterator_range_detail::less_than( l, r ); + } + + template< class IteratorT, class ForwardRange > + inline BOOST_DEDUCED_TYPENAME boost::enable_if< + mpl::not_ >, + bool + >::type + operator<=( const ForwardRange& l, const iterator_range& r ) + { + return iterator_range_detail::less_or_equal_than( l, r ); + } + + template< class IteratorT, class ForwardRange > + inline BOOST_DEDUCED_TYPENAME boost::enable_if< + mpl::not_ >, + bool + >::type + operator>( const ForwardRange& l, const iterator_range& r ) + { + return iterator_range_detail::greater_than( l, r ); + } + + template< class IteratorT, class ForwardRange > + inline BOOST_DEDUCED_TYPENAME boost::enable_if< + mpl::not_ >, + bool + >::type + operator>=( const ForwardRange& l, const iterator_range& r ) + { + return iterator_range_detail::greater_or_equal_than( l, r ); + } + + template< class Iterator1T, class Iterator2T > + inline bool + operator==( const iterator_range& l, const iterator_range& r ) + { + return boost::equal( l, r ); + } + + template< class IteratorT, class ForwardRange > + inline BOOST_DEDUCED_TYPENAME boost::enable_if< + mpl::not_ >, + bool + >::type + operator==( const iterator_range& l, const ForwardRange& r ) + { + return boost::equal( l, r ); + } + + + template< class Iterator1T, class Iterator2T > + inline bool + operator!=( const iterator_range& l, const iterator_range& r ) + { + return !boost::equal( l, r ); + } + + template< class IteratorT, class ForwardRange > + inline BOOST_DEDUCED_TYPENAME boost::enable_if< + mpl::not_ >, + bool + >::type + operator!=( const iterator_range& l, const ForwardRange& r ) + { + return !boost::equal( l, r ); + } + + + template< class Iterator1T, class Iterator2T > + inline bool + operator<( const iterator_range& l, const iterator_range& r ) + { + return iterator_range_detail::less_than( l, r ); + } + + template< class IteratorT, class ForwardRange > + inline BOOST_DEDUCED_TYPENAME boost::enable_if< + mpl::not_ >, + bool + >::type + operator<( const iterator_range& l, const ForwardRange& r ) + { + return iterator_range_detail::less_than( l, r ); + } + + template< class Iterator1T, class Iterator2T > + inline bool + operator<=( const iterator_range& l, const iterator_range& r ) + { + return iterator_range_detail::less_or_equal_than( l, r ); + } + + template< class IteratorT, class ForwardRange > + inline BOOST_DEDUCED_TYPENAME boost::enable_if< + mpl::not_ >, + bool + >::type + operator<=( const iterator_range& l, const ForwardRange& r ) + { + return iterator_range_detail::less_or_equal_than( l, r ); + } + + template< class Iterator1T, class Iterator2T > + inline bool + operator>( const iterator_range& l, const iterator_range& r ) + { + return iterator_range_detail::greater_than( l, r ); + } + + template< class IteratorT, class ForwardRange > + inline BOOST_DEDUCED_TYPENAME boost::enable_if< + mpl::not_ >, + bool + >::type + operator>( const iterator_range& l, const ForwardRange& r ) + { + return iterator_range_detail::greater_than( l, r ); + } + + template< class Iterator1T, class Iterator2T > + inline bool + operator>=( const iterator_range& l, const iterator_range& r ) + { + return iterator_range_detail::greater_or_equal_than( l, r ); + } + + template< class IteratorT, class ForwardRange > + inline BOOST_DEDUCED_TYPENAME boost::enable_if< + mpl::not_ >, + bool + >::type + operator>=( const iterator_range& l, const ForwardRange& r ) + { + return iterator_range_detail::greater_or_equal_than( l, r ); + } + +// iterator range utilities -----------------------------------------// + + //! iterator_range construct helper + /*! + Construct an \c iterator_range from a pair of iterators + + \param Begin A begin iterator + \param End An end iterator + \return iterator_range object + */ + template< typename IteratorT > + inline iterator_range< IteratorT > + make_iterator_range( IteratorT Begin, IteratorT End ) + { + return iterator_range( Begin, End ); + } + + template + inline iterator_range + make_iterator_range_n(IteratorT first, IntegerT n) + { + return iterator_range(first, boost::next(first, n)); + } + + //! iterator_range construct helper + /*! + Construct an \c iterator_range from a \c Range containing the begin + and end iterators. + */ + template< class ForwardRange > + inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > + make_iterator_range( ForwardRange& r ) + { + return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > + ( r, iterator_range_detail::range_tag() ); + } + + template< class ForwardRange > + inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > + make_iterator_range( const ForwardRange& r ) + { + return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > + ( r, iterator_range_detail::const_range_tag() ); + } + + namespace iterator_range_detail + { + template< class Range > + inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > + make_range_impl( Range& r, + BOOST_DEDUCED_TYPENAME range_difference::type advance_begin, + BOOST_DEDUCED_TYPENAME range_difference::type advance_end ) + { + // + // Not worth the effort + // + //if( advance_begin == 0 && advance_end == 0 ) + // return make_iterator_range( r ); + // + + BOOST_DEDUCED_TYPENAME range_iterator::type + new_begin = boost::begin( r ), + new_end = boost::end( r ); + std::advance( new_begin, advance_begin ); + std::advance( new_end, advance_end ); + return make_iterator_range( new_begin, new_end ); + } + } + + template< class Range > + inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > + make_iterator_range( Range& r, + BOOST_DEDUCED_TYPENAME range_difference::type advance_begin, + BOOST_DEDUCED_TYPENAME range_difference::type advance_end ) + { + return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); + } + + template< class Range > + inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > + make_iterator_range( const Range& r, + BOOST_DEDUCED_TYPENAME range_difference::type advance_begin, + BOOST_DEDUCED_TYPENAME range_difference::type advance_end ) + { + return iterator_range_detail::make_range_impl( r, advance_begin, advance_end ); + } + + //! copy a range into a sequence + /*! + Construct a new sequence of the specified type from the elements + in the given range + + \param Range An input range + \return New sequence + */ + template< typename SeqT, typename Range > + inline SeqT copy_range( const Range& r ) + { + return SeqT( boost::begin( r ), boost::end( r ) ); + } + +} // namespace 'boost' + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) + #pragma warning( pop ) +#endif + +#endif + diff --git a/libs/range/include/boost/range/iterator_range_hash.hpp b/libs/range/include/boost/range/iterator_range_hash.hpp new file mode 100644 index 00000000..615d22fc --- /dev/null +++ b/libs/range/include/boost/range/iterator_range_hash.hpp @@ -0,0 +1,22 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014 +// Use, modification and distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include + +namespace boost +{ + +template +std::size_t hash_value(const iterator_range& rng) +{ + return boost::hash_range(rng.begin(), rng.end()); +} + +} // namespace boost diff --git a/libs/range/include/boost/range/iterator_range_io.hpp b/libs/range/include/boost/range/iterator_range_io.hpp new file mode 100644 index 00000000..8c294008 --- /dev/null +++ b/libs/range/include/boost/range/iterator_range_io.hpp @@ -0,0 +1,93 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. +// Use, modification and distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_ITERATOR_RANGE_IO_HPP_INCLUDED +#define BOOST_RANGE_ITERATOR_RANGE_IO_HPP_INCLUDED + +#include +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) + #pragma warning( push ) + #pragma warning( disable : 4996 ) +#endif + +// From boost/dynamic_bitset.hpp; thanks to Matthias Troyer for Cray X1 patch. +#ifndef BOOST_OLD_IOSTREAMS +# if defined(__STL_CONFIG_H) && \ + !defined (__STL_USE_NEW_IOSTREAMS) && !defined(__crayx1) \ + /**/ +# define BOOST_OLD_IOSTREAMS +# endif +#endif // #ifndef BOOST_OLD_IOSTREAMS + +#ifndef _STLP_NO_IOSTREAMS +# ifndef BOOST_OLD_IOSTREAMS +# include +# else +# include +# endif +#endif // _STLP_NO_IOSTREAMS + +#include +#include +#include +#include + +namespace boost +{ + +#ifndef _STLP_NO_IOSTREAMS +# ifndef BOOST_OLD_IOSTREAMS + + //! iterator_range output operator + /*! + Output the range to an ostream. Elements are outputted + in a sequence without separators. + */ + template< typename IteratorT, typename Elem, typename Traits > + inline std::basic_ostream& operator<<( + std::basic_ostream& Os, + const iterator_range& r ) + { + std::copy( r.begin(), r.end(), + std::ostream_iterator< BOOST_DEDUCED_TYPENAME + iterator_value::type, + Elem, Traits>(Os) ); + return Os; + } + +# else + + //! iterator_range output operator + /*! + Output the range to an ostream. Elements are outputted + in a sequence without separators. + */ + template< typename IteratorT > + inline std::ostream& operator<<( + std::ostream& Os, + const iterator_range& r ) + { + std::copy( r.begin(), r.end(), std::ostream_iterator(Os)); + return Os; + } + +# endif +#endif // _STLP_NO_IOSTREAMS + +} // namespace boost + +#undef BOOST_OLD_IOSTREAMS + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) + #pragma warning(pop) +#endif + +#endif // include guard diff --git a/libs/range/include/boost/range/join.hpp b/libs/range/include/boost/range/join.hpp new file mode 100644 index 00000000..aacc0a37 --- /dev/null +++ b/libs/range/include/boost/range/join.hpp @@ -0,0 +1,91 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_JOIN_HPP_INCLUDED +#define BOOST_RANGE_JOIN_HPP_INCLUDED + +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + +template +class joined_type +{ +public: + typedef iterator_range< + range_detail::join_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type, + BOOST_DEDUCED_TYPENAME range_iterator::type, + BOOST_DEDUCED_TYPENAME range_value::type + > + > type; +}; + + } // namespace range_detail + +namespace range +{ + +template +class joined_range + : public range_detail::joined_type::type +{ + typedef range_detail::join_iterator< + BOOST_DEDUCED_TYPENAME range_iterator::type, + BOOST_DEDUCED_TYPENAME range_iterator::type, + BOOST_DEDUCED_TYPENAME range_value::type + > iterator_t; + + typedef BOOST_DEDUCED_TYPENAME range_detail::joined_type< + SinglePassRange1, SinglePassRange2>::type base_t; +public: + joined_range(SinglePassRange1& rng1, SinglePassRange2& rng2) + : base_t( + iterator_t(rng1, rng2, range_detail::join_iterator_begin_tag()), + iterator_t(rng1, rng2, range_detail::join_iterator_end_tag()) + ) + { + } +}; + +template +joined_range +join(const SinglePassRange1& r1, const SinglePassRange2& r2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return joined_range(r1, r2); +} + +template +joined_range +join(SinglePassRange1& r1, SinglePassRange2& r2) +{ + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + BOOST_RANGE_CONCEPT_ASSERT(( SinglePassRangeConcept )); + + return joined_range(r1, r2); +} + +} // namespace range + +using ::boost::range::joined_range; +using ::boost::range::join; + +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/metafunctions.hpp b/libs/range/include/boost/range/metafunctions.hpp new file mode 100644 index 00000000..7ca2f93e --- /dev/null +++ b/libs/range/include/boost/range/metafunctions.hpp @@ -0,0 +1,28 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_METAFUNCTIONS_HPP +#define BOOST_RANGE_METAFUNCTIONS_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/libs/range/include/boost/range/mfc.hpp b/libs/range/include/boost/range/mfc.hpp new file mode 100644 index 00000000..058e54ec --- /dev/null +++ b/libs/range/include/boost/range/mfc.hpp @@ -0,0 +1,984 @@ +#ifndef BOOST_RANGE_MFC_HPP +#define BOOST_RANGE_MFC_HPP + + + + +// Boost.Range MFC Extension +// +// Copyright Shunsuke Sogame 2005-2006. +// 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) + + + + +// config +// + + +#include // _MFC_VER + + +#if !defined(BOOST_RANGE_MFC_NO_CPAIR) + #if (_MFC_VER < 0x0700) // dubious + #define BOOST_RANGE_MFC_NO_CPAIR + #endif +#endif + + +#if !defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING) + #if (_MFC_VER < 0x0700) // dubious + #define BOOST_RANGE_MFC_HAS_LEGACY_STRING + #endif +#endif + + +// A const collection of old MFC doesn't return const reference. +// +#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF) + #if (_MFC_VER < 0x0700) // dubious + #define BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF + #endif +#endif + + + + +// forward declarations +// + + +template< class Type, class ArgType > +class CArray; + +template< class Type, class ArgType > +class CList; + +template< class Key, class ArgKey, class Mapped, class ArgMapped > +class CMap; + +template< class BaseClass, class PtrType > +class CTypedPtrArray; + +template< class BaseClass, class PtrType > +class CTypedPtrList; + +template< class BaseClass, class KeyPtrType, class MappedPtrType > +class CTypedPtrMap; + + + + +// extended customizations +// + + +#include // ptrdiff_t +#include // pair +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // legacy CString +#include // CXXXArray, CXXXList, CMapXXXToXXX +#include + + +namespace boost { namespace range_detail_microsoft { + + + // mfc_ptr_array_iterator + // + // 'void **' is not convertible to 'void const **', + // so we define... + // + + template< class ArrayT, class PtrType > + struct mfc_ptr_array_iterator; + + template< class ArrayT, class PtrType > + struct mfc_ptr_array_iterator_super + { + typedef iterator_adaptor< + mfc_ptr_array_iterator, + std::ptrdiff_t, // Base! + PtrType, // Value + random_access_traversal_tag, + use_default, + std::ptrdiff_t // Difference + > type; + }; + + template< class ArrayT, class PtrType > + struct mfc_ptr_array_iterator : + mfc_ptr_array_iterator_super::type + { + private: + typedef mfc_ptr_array_iterator self_t; + typedef typename mfc_ptr_array_iterator_super::type super_t; + typedef typename super_t::reference ref_t; + + public: + explicit mfc_ptr_array_iterator() + { } + + explicit mfc_ptr_array_iterator(ArrayT& arr, INT_PTR index) : + super_t(index), m_parr(boost::addressof(arr)) + { } + + template< class, class > friend struct mfc_ptr_array_iterator; + template< class ArrayT_, class PtrType_ > + mfc_ptr_array_iterator(mfc_ptr_array_iterator const& other) : + super_t(other.base()), m_parr(other.m_parr) + { } + + private: + ArrayT *m_parr; + + friend class iterator_core_access; + ref_t dereference() const + { + BOOST_ASSERT(0 <= this->base() && this->base() < m_parr->GetSize() && "out of range"); + return *( m_parr->GetData() + this->base() ); + } + + bool equal(self_t const& other) const + { + BOOST_ASSERT(m_parr == other.m_parr && "iterators incompatible"); + return this->base() == other.base(); + } + }; + + struct mfc_ptr_array_functions + { + template< class Iterator, class X > + Iterator begin(X& x) + { + return Iterator(x, 0); + } + + template< class Iterator, class X > + Iterator end(X& x) + { + return Iterator(x, x.GetSize()); + } + }; + + + // arrays + // + + template< > + struct customization< ::CByteArray > : + array_functions + { + template< class X > + struct meta + { + typedef BYTE val_t; + + typedef val_t *mutable_iterator; + typedef val_t const *const_iterator; + }; + }; + + + template< > + struct customization< ::CDWordArray > : + array_functions + { + template< class X > + struct meta + { + typedef DWORD val_t; + + typedef val_t *mutable_iterator; + typedef val_t const *const_iterator; + }; + }; + + + template< > + struct customization< ::CObArray > : + mfc_ptr_array_functions + { + template< class X > + struct meta + { + typedef mfc_ptr_array_iterator mutable_iterator; + typedef mfc_ptr_array_iterator const_iterator; + }; + }; + + + template< > + struct customization< ::CPtrArray > : + mfc_ptr_array_functions + { + template< class X > + struct meta + { + typedef mfc_ptr_array_iterator mutable_iterator; + typedef mfc_ptr_array_iterator const_iterator; + }; + }; + + + template< > + struct customization< ::CStringArray > : + array_functions + { + template< class X > + struct meta + { + typedef ::CString val_t; + + typedef val_t *mutable_iterator; + typedef val_t const *const_iterator; + }; + }; + + + template< > + struct customization< ::CUIntArray > : + array_functions + { + template< class X > + struct meta + { + typedef UINT val_t; + + typedef val_t *mutable_iterator; + typedef val_t const *const_iterator; + }; + }; + + + template< > + struct customization< ::CWordArray > : + array_functions + { + template< class X > + struct meta + { + typedef WORD val_t; + + typedef val_t *mutable_iterator; + typedef val_t const *const_iterator; + }; + }; + + + // lists + // + + template< > + struct customization< ::CObList > : + list_functions + { + template< class X > + struct meta + { + typedef list_iterator mutable_iterator; + #if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF) + typedef list_iterator const_iterator; + #else + typedef list_iterator const_iterator; + #endif + }; + }; + + + template< > + struct customization< ::CPtrList > : + list_functions + { + template< class X > + struct meta + { + typedef list_iterator mutable_iterator; + #if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF) + typedef list_iterator const_iterator; + #else + typedef list_iterator const_iterator; + #endif + }; + }; + + + template< > + struct customization< ::CStringList > : + list_functions + { + template< class X > + struct meta + { + typedef ::CString val_t; + + typedef list_iterator mutable_iterator; + #if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF) + typedef list_iterator const_iterator; + #else + typedef list_iterator const_iterator; + #endif + }; + }; + + + // mfc_map_iterator + // + + template< class MapT, class KeyT, class MappedT > + struct mfc_map_iterator; + + template< class MapT, class KeyT, class MappedT > + struct mfc_map_iterator_super + { + typedef iterator_facade< + mfc_map_iterator, + std::pair, + forward_traversal_tag, + std::pair const + > type; + }; + + template< class MapT, class KeyT, class MappedT > + struct mfc_map_iterator : + mfc_map_iterator_super::type + { + private: + typedef mfc_map_iterator self_t; + typedef typename mfc_map_iterator_super::type super_t; + typedef typename super_t::reference ref_t; + + public: + explicit mfc_map_iterator() + { } + + explicit mfc_map_iterator(MapT const& map, POSITION pos) : + m_pmap(boost::addressof(map)), m_posNext(pos) + { + increment(); + } + + explicit mfc_map_iterator(MapT const& map) : + m_pmap(&map), m_pos(0) // end iterator + { } + + template< class, class, class > friend struct mfc_map_iterator; + template< class MapT_, class KeyT_, class MappedT_> + mfc_map_iterator(mfc_map_iterator const& other) : + m_pmap(other.m_pmap), + m_pos(other.m_pos), m_posNext(other.m_posNext), + m_key(other.m_key), m_mapped(other.m_mapped) + { } + + private: + MapT const *m_pmap; + POSITION m_pos, m_posNext; + KeyT m_key; MappedT m_mapped; + + friend class iterator_core_access; + ref_t dereference() const + { + BOOST_ASSERT(m_pos != 0 && "out of range"); + return std::make_pair(m_key, m_mapped); + } + + void increment() + { + BOOST_ASSERT(m_pos != 0 && "out of range"); + + if (m_posNext == 0) { + m_pos = 0; + return; + } + + m_pos = m_posNext; + m_pmap->GetNextAssoc(m_posNext, m_key, m_mapped); + } + + bool equal(self_t const& other) const + { + BOOST_ASSERT(m_pmap == other.m_pmap && "iterators incompatible"); + return m_pos == other.m_pos; + } + }; + + struct mfc_map_functions + { + template< class Iterator, class X > + Iterator begin(X& x) + { + return Iterator(x, x.GetStartPosition()); + } + + template< class Iterator, class X > + Iterator end(X& x) + { + return Iterator(x); + } + }; + + +#if !defined(BOOST_RANGE_MFC_NO_CPAIR) + + + // mfc_cpair_map_iterator + // + // used by ::CMap and ::CMapStringToString + // + + template< class MapT, class PairT > + struct mfc_cpair_map_iterator; + + template< class MapT, class PairT > + struct mfc_pget_map_iterator_super + { + typedef iterator_facade< + mfc_cpair_map_iterator, + PairT, + forward_traversal_tag + > type; + }; + + template< class MapT, class PairT > + struct mfc_cpair_map_iterator : + mfc_pget_map_iterator_super::type + { + private: + typedef mfc_cpair_map_iterator self_t; + typedef typename mfc_pget_map_iterator_super::type super_t; + typedef typename super_t::reference ref_t; + + public: + explicit mfc_cpair_map_iterator() + { } + + explicit mfc_cpair_map_iterator(MapT& map, PairT *pp) : + m_pmap(boost::addressof(map)), m_pp(pp) + { } + + template< class, class > friend struct mfc_cpair_map_iterator; + template< class MapT_, class PairT_> + mfc_cpair_map_iterator(mfc_cpair_map_iterator const& other) : + m_pmap(other.m_pmap), m_pp(other.m_pp) + { } + + private: + MapT *m_pmap; + PairT *m_pp; + + friend class iterator_core_access; + ref_t dereference() const + { + BOOST_ASSERT(m_pp != 0 && "out of range"); + return *m_pp; + } + + void increment() + { + BOOST_ASSERT(m_pp != 0 && "out of range"); + m_pp = m_pmap->PGetNextAssoc(m_pp); + } + + bool equal(self_t const& other) const + { + BOOST_ASSERT(m_pmap == other.m_pmap && "iterators incompatible"); + return m_pp == other.m_pp; + } + }; + + struct mfc_cpair_map_functions + { + template< class Iterator, class X > + Iterator begin(X& x) + { + // Workaround: + // Assertion fails if empty. + // MFC document is wrong. + #if !defined(NDEBUG) + if (x.GetCount() == 0) + return Iterator(x, 0); + #endif + + return Iterator(x, x.PGetFirstAssoc()); + } + + template< class Iterator, class X > + Iterator end(X& x) + { + return Iterator(x, 0); + } + }; + + +#endif // !defined(BOOST_RANGE_MFC_NO_CPAIR) + + + // maps + // + + template< > + struct customization< ::CMapPtrToWord > : + mfc_map_functions + { + template< class X > + struct meta + { + typedef void *key_t; + typedef WORD mapped_t; + + typedef mfc_map_iterator mutable_iterator; + typedef mutable_iterator const_iterator; + }; + }; + + + template< > + struct customization< ::CMapPtrToPtr > : + mfc_map_functions + { + template< class X > + struct meta + { + typedef void *key_t; + typedef void *mapped_t; + + typedef mfc_map_iterator mutable_iterator; + typedef mutable_iterator const_iterator; + }; + }; + + + template< > + struct customization< ::CMapStringToOb > : + mfc_map_functions + { + template< class X > + struct meta + { + typedef ::CString key_t; + typedef ::CObject *mapped_t; + + typedef mfc_map_iterator mutable_iterator; + typedef mutable_iterator const_iterator; + }; + }; + + + template< > + struct customization< ::CMapStringToPtr > : + mfc_map_functions + { + template< class X > + struct meta + { + typedef ::CString key_t; + typedef void *mapped_t; + + typedef mfc_map_iterator mutable_iterator; + typedef mutable_iterator const_iterator; + }; + }; + + + template< > + struct customization< ::CMapStringToString > : + #if !defined(BOOST_RANGE_MFC_NO_CPAIR) + mfc_cpair_map_functions + #else + mfc_map_functions + #endif + { + template< class X > + struct meta + { + #if !defined(BOOST_RANGE_MFC_NO_CPAIR) + typedef typename X::CPair pair_t; + + typedef mfc_cpair_map_iterator mutable_iterator; + typedef mfc_cpair_map_iterator const_iterator; + #else + typedef ::CString key_t; + typedef ::CString mapped_t; + + typedef mfc_map_iterator mutable_iterator; + typedef mutable_iterator const_iterator; + #endif + }; + }; + + + template< > + struct customization< ::CMapWordToOb > : + mfc_map_functions + { + template< class X > + struct meta + { + typedef WORD key_t; + typedef ::CObject *mapped_t; + + typedef mfc_map_iterator mutable_iterator; + typedef mutable_iterator const_iterator; + }; + }; + + + template< > + struct customization< ::CMapWordToPtr > : + mfc_map_functions + { + template< class X > + struct meta + { + typedef WORD key_t; + typedef void *mapped_t; + + typedef mfc_map_iterator mutable_iterator; + typedef mutable_iterator const_iterator; + }; + }; + + + // templates + // + + template< class Type, class ArgType > + struct customization< ::CArray > : + array_functions + { + template< class X > + struct meta + { + typedef Type val_t; + + typedef val_t *mutable_iterator; + typedef val_t const *const_iterator; + }; + }; + + + template< class Type, class ArgType > + struct customization< ::CList > : + list_functions + { + template< class X > + struct meta + { + typedef Type val_t; + + typedef list_iterator mutable_iterator; + #if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF) + typedef list_iterator const_iterator; + #else + typedef list_iterator const_iterator; + #endif + }; + }; + + + template< class Key, class ArgKey, class Mapped, class ArgMapped > + struct customization< ::CMap > : + #if !defined(BOOST_RANGE_MFC_NO_CPAIR) + mfc_cpair_map_functions + #else + mfc_map_functions + #endif + { + template< class X > + struct meta + { + #if !defined(BOOST_RANGE_MFC_NO_CPAIR) + typedef typename X::CPair pair_t; + + typedef mfc_cpair_map_iterator mutable_iterator; + typedef mfc_cpair_map_iterator const_iterator; + #else + typedef Key key_t; + typedef Mapped mapped_t; + + typedef mfc_map_iterator mutable_iterator; + typedef mutable_iterator const_iterator; + #endif + }; + }; + + + template< class BaseClass, class PtrType > + struct customization< ::CTypedPtrArray > + { + template< class X > + struct fun + { + typedef typename remove_pointer::type val_t; + + typedef typename mpl::if_< is_const, + val_t const, + val_t + >::type val_t_; + + typedef val_t_ * const result_type; + + template< class PtrType_ > + result_type operator()(PtrType_ p) const + { + return static_cast(p); + } + }; + + template< class X > + struct meta + { + typedef typename compatible_mutable_iterator::type miter_t; + typedef typename range_const_iterator::type citer_t; + + typedef transform_iterator, miter_t> mutable_iterator; + typedef transform_iterator, citer_t> const_iterator; + }; + + template< class Iterator, class X > + Iterator begin(X& x) + { + return Iterator(boost::begin(x), fun()); + } + + template< class Iterator, class X > + Iterator end(X& x) + { + return Iterator(boost::end(x), fun()); + } + }; + + + template< class BaseClass, class PtrType > + struct customization< ::CTypedPtrList > : + list_functions + { + template< class X > + struct meta + { + typedef typename remove_pointer::type val_t; + + // not l-value + typedef list_iterator mutable_iterator; + typedef list_iterator const_iterator; + }; + }; + + + template< class BaseClass, class KeyPtrType, class MappedPtrType > + struct customization< ::CTypedPtrMap > : + mfc_map_functions + { + template< class X > + struct meta + { + typedef mfc_map_iterator mutable_iterator; + typedef mutable_iterator const_iterator; + }; + }; + + + // strings + // + +#if defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING) + + template< > + struct customization< ::CString > + { + template< class X > + struct meta + { + // LPTSTR/LPCTSTR is not always defined in . + typedef TCHAR *mutable_iterator; + typedef TCHAR const *const_iterator; + }; + + template< class Iterator, class X > + typename mutable_::type begin(X& x) + { + return x.GetBuffer(0); + } + + template< class Iterator, class X > + Iterator begin(X const& x) + { + return x; + } + + template< class Iterator, class X > + Iterator end(X& x) + { + return begin(x) + x.GetLength(); + } + }; + +#endif // defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING) + + +} } // namespace boost::range_detail_microsoft + + + + +// range customizations +// + + +// arrays +// +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CByteArray +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CDWordArray +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CStringArray +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CUIntArray +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CWordArray +) + + +// lists +// +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CObList +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CPtrList +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CStringList +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CObArray +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CPtrArray +) + + +// maps +// +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CMapPtrToWord +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CMapPtrToPtr +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CMapStringToOb +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CMapStringToPtr +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CMapStringToString +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CMapWordToOb +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CMapWordToPtr +) + + +// templates +// +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CArray, 2 +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CList, 2 +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CMap, 4 +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CTypedPtrArray, 2 +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CTypedPtrList, 2 +) + +BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TEMPLATE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CTypedPtrMap, 3 +) + + +// strings +// +#if defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING) + + BOOST_RANGE_DETAIL_MICROSOFT_CUSTOMIZATION_TYPE( + boost::range_detail_microsoft::using_type_as_tag, + BOOST_PP_NIL, CString + ) + +#endif + + + + +#endif diff --git a/libs/range/include/boost/range/mfc_map.hpp b/libs/range/include/boost/range/mfc_map.hpp new file mode 100644 index 00000000..2cd42b43 --- /dev/null +++ b/libs/range/include/boost/range/mfc_map.hpp @@ -0,0 +1,114 @@ +// Boost.Range library +// +// Copyright Adam D. Walling 2012. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_ADAPTOR_MFC_MAP_HPP +#define BOOST_RANGE_ADAPTOR_MFC_MAP_HPP + +#if !defined(BOOST_RANGE_MFC_NO_CPAIR) + +#include +#include + +namespace boost +{ + namespace range_detail + { + // CMap and CMapStringToString range iterators return CPair, + // which has a key and value member. Other MFC range iterators + // already return adapted std::pair objects. This allows usage + // of the map_keys and map_values range adaptors with CMap + // and CMapStringToString + + // CPair has a VALUE value member, and a KEY key member; we will + // use VALUE& as the result_type consistent with CMap::operator[] + + // specialization for CMap + template + struct select_first< CMap > + { + typedef BOOST_DEDUCED_TYPENAME CMap map_type; + typedef BOOST_DEDUCED_TYPENAME range_reference::type argument_type; + typedef BOOST_DEDUCED_TYPENAME const KEY& result_type; + + result_type operator()( argument_type r ) const + { + return r.key; + } + }; + + template + struct select_second_mutable< CMap > + { + typedef BOOST_DEDUCED_TYPENAME CMap map_type; + typedef BOOST_DEDUCED_TYPENAME range_reference::type argument_type; + typedef BOOST_DEDUCED_TYPENAME VALUE& result_type; + + result_type operator()( argument_type r ) const + { + return r.value; + } + }; + + template + struct select_second_const< CMap > + { + typedef BOOST_DEDUCED_TYPENAME CMap map_type; + typedef BOOST_DEDUCED_TYPENAME range_reference::type argument_type; + typedef BOOST_DEDUCED_TYPENAME const VALUE& result_type; + + result_type operator()( argument_type r ) const + { + return r.value; + } + }; + + + // specialization for CMapStringToString + template<> + struct select_first< CMapStringToString > + { + typedef range_reference::type argument_type; + typedef const CString& result_type; + + result_type operator()( argument_type r ) const + { + return r.key; + } + }; + + template<> + struct select_second_mutable< CMapStringToString > + { + typedef range_reference::type argument_type; + typedef CString& result_type; + + result_type operator()( argument_type r ) const + { + return r.value; + } + }; + + template<> + struct select_second_const< CMapStringToString > + { + typedef range_reference::type argument_type; + typedef const CString& result_type; + + result_type operator()( argument_type r ) const + { + return r.value; + } + }; + } // 'range_detail' +} // 'boost' + +#endif // !defined(BOOST_RANGE_MFC_NO_CPAIR) + +#endif diff --git a/libs/range/include/boost/range/mutable_iterator.hpp b/libs/range/include/boost/range/mutable_iterator.hpp new file mode 100644 index 00000000..b9246666 --- /dev/null +++ b/libs/range/include/boost/range/mutable_iterator.hpp @@ -0,0 +1,79 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_MUTABLE_ITERATOR_HPP +#define BOOST_RANGE_MUTABLE_ITERATOR_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + + ////////////////////////////////////////////////////////////////////////// + // default + ////////////////////////////////////////////////////////////////////////// + + namespace range_detail + { + +BOOST_RANGE_EXTRACT_OPTIONAL_TYPE( iterator ) + +template< typename C > +struct range_mutable_iterator + : range_detail::extract_iterator< + BOOST_DEDUCED_TYPENAME remove_reference::type> +{}; + +////////////////////////////////////////////////////////////////////////// +// pair +////////////////////////////////////////////////////////////////////////// + +template< typename Iterator > +struct range_mutable_iterator< std::pair > +{ + typedef Iterator type; +}; + +////////////////////////////////////////////////////////////////////////// +// array +////////////////////////////////////////////////////////////////////////// + +template< typename T, std::size_t sz > +struct range_mutable_iterator< T[sz] > +{ + typedef T* type; +}; + + } // namespace range_detail + +template +struct range_mutable_iterator + : range_detail::range_mutable_iterator< + BOOST_DEDUCED_TYPENAME remove_reference::type + > +{ +}; + +} // namespace boost + +#include + +#endif diff --git a/libs/range/include/boost/range/numeric.hpp b/libs/range/include/boost/range/numeric.hpp new file mode 100644 index 00000000..d1510cde --- /dev/null +++ b/libs/range/include/boost/range/numeric.hpp @@ -0,0 +1,188 @@ +// Copyright 2009-2014 Neil Groves. +// 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) +// +// Copyright 2006 Thorsten Ottosen. +// 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) +// +// Copyright 2004 Eric Niebler. +// 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) +// +// Contains range-based versions of the numeric std algorithms +// +#if defined(_MSC_VER) + #pragma once +#endif + +#ifndef BOOST_RANGE_NUMERIC_HPP +#define BOOST_RANGE_NUMERIC_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost +{ + template + inline Value accumulate(const SinglePassRange& rng, Value init) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return std::accumulate(boost::begin(rng), boost::end(rng), init); + } + + template + inline Value accumulate(const SinglePassRange& rng, Value init, + BinaryOperation op) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept )); + + return std::accumulate(boost::begin(rng), boost::end(rng), init, op); + } + + namespace range_detail + { + template + inline bool inner_product_precondition( + const SinglePassRange1&, + const SinglePassRange2&, + std::input_iterator_tag, + std::input_iterator_tag) + { + return true; + } + + template + inline bool inner_product_precondition( + const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + std::forward_iterator_tag, + std::forward_iterator_tag) + { + return boost::size(rng2) >= boost::size(rng1); + } + + } // namespace range_detail + + template< + class SinglePassRange1, + class SinglePassRange2, + class Value + > + inline Value inner_product( + const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + Value init) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + BOOST_ASSERT( + range_detail::inner_product_precondition( + rng1, rng2, + typename range_category::type(), + typename range_category::type())); + + return std::inner_product( + boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), init); + } + + template< + class SinglePassRange1, + class SinglePassRange2, + class Value, + class BinaryOperation1, + class BinaryOperation2 + > + inline Value inner_product( + const SinglePassRange1& rng1, + const SinglePassRange2& rng2, + Value init, + BinaryOperation1 op1, + BinaryOperation2 op2) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + BOOST_ASSERT( + range_detail::inner_product_precondition( + rng1, rng2, + typename range_category::type(), + typename range_category::type())); + + return std::inner_product( + boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), init, op1, op2); + } + + template + inline OutputIterator partial_sum(const SinglePassRange& rng, + OutputIterator result) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return std::partial_sum(boost::begin(rng), boost::end(rng), result); + } + + template + inline OutputIterator partial_sum( + const SinglePassRange& rng, + OutputIterator result, + BinaryOperation op) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return std::partial_sum(boost::begin(rng), boost::end(rng), result, op); + } + + template + inline OutputIterator adjacent_difference( + const SinglePassRange& rng, + OutputIterator result) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return std::adjacent_difference(boost::begin(rng), boost::end(rng), + result); + } + + template + inline OutputIterator adjacent_difference( + const SinglePassRange& rng, + OutputIterator result, + BinaryOperation op) + { + BOOST_RANGE_CONCEPT_ASSERT(( + SinglePassRangeConcept)); + + return std::adjacent_difference(boost::begin(rng), boost::end(rng), + result, op); + } + +} // namespace boost + +#endif diff --git a/libs/range/include/boost/range/pointer.hpp b/libs/range/include/boost/range/pointer.hpp new file mode 100644 index 00000000..b1e8dc5c --- /dev/null +++ b/libs/range/include/boost/range/pointer.hpp @@ -0,0 +1,30 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_POINTER_TYPE_HPP +#define BOOST_RANGE_POINTER_TYPE_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ + template< class T > + struct range_pointer + : iterator_pointer< BOOST_DEDUCED_TYPENAME range_iterator::type > + { }; +} + +#endif diff --git a/libs/range/include/boost/range/range_fwd.hpp b/libs/range/include/boost/range/range_fwd.hpp new file mode 100644 index 00000000..0e6e00f5 --- /dev/null +++ b/libs/range/include/boost/range/range_fwd.hpp @@ -0,0 +1,63 @@ +// Boost.Range library +// +// Copyright Neil Groves 2003-2004. +// Use, modification and distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_RANGE_FWD_HPP_INCLUDED +#define BOOST_RANGE_RANGE_FWD_HPP_INCLUDED + +namespace boost +{ + +// Extension points + template + struct range_iterator; + + template + struct range_mutable_iterator; + + template + struct range_const_iterator; + +// Core classes + template + class iterator_range; + + template + class sub_range; + +// Meta-functions + template + struct range_category; + + template + struct range_difference; + + template + struct range_pointer; + + template + struct range_reference; + + template + struct range_reverse_iterator; + + template + struct range_size; + + template + struct range_value; + + template + struct has_range_iterator; + + template + struct has_range_const_iterator; + +} // namespace boost + +#endif // include guard diff --git a/libs/range/include/boost/range/rbegin.hpp b/libs/range/include/boost/range/rbegin.hpp new file mode 100644 index 00000000..83d3ad0b --- /dev/null +++ b/libs/range/include/boost/range/rbegin.hpp @@ -0,0 +1,52 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_RBEGIN_HPP +#define BOOST_RANGE_RBEGIN_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include + +namespace boost +{ + +template< class C > +inline BOOST_DEDUCED_TYPENAME range_reverse_iterator::type +rbegin( C& c ) +{ + typedef BOOST_DEDUCED_TYPENAME range_reverse_iterator::type + iter_type; + return iter_type( boost::end( c ) ); +} + +template< class C > +inline BOOST_DEDUCED_TYPENAME range_reverse_iterator::type +rbegin( const C& c ) +{ + typedef BOOST_DEDUCED_TYPENAME range_reverse_iterator::type + iter_type; + return iter_type( boost::end( c ) ); +} + +template< class T > +inline BOOST_DEDUCED_TYPENAME range_reverse_iterator::type +const_rbegin( const T& r ) +{ + return boost::rbegin( r ); +} + +} // namespace 'boost' + +#endif + diff --git a/libs/range/include/boost/range/reference.hpp b/libs/range/include/boost/range/reference.hpp new file mode 100644 index 00000000..c664c38a --- /dev/null +++ b/libs/range/include/boost/range/reference.hpp @@ -0,0 +1,29 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_REFERENCE_TYPE_HPP +#define BOOST_RANGE_REFERENCE_TYPE_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ + template< class T > + struct range_reference : iterator_reference< typename range_iterator::type > + { }; +} + +#endif diff --git a/libs/range/include/boost/range/rend.hpp b/libs/range/include/boost/range/rend.hpp new file mode 100644 index 00000000..c91a05af --- /dev/null +++ b/libs/range/include/boost/range/rend.hpp @@ -0,0 +1,52 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_REND_HPP +#define BOOST_RANGE_REND_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include + +namespace boost +{ + +template< class C > +inline BOOST_DEDUCED_TYPENAME range_reverse_iterator::type +rend( C& c ) +{ + typedef BOOST_DEDUCED_TYPENAME range_reverse_iterator::type + iter_type; + return iter_type( boost::begin( c ) ); +} + +template< class C > +inline BOOST_DEDUCED_TYPENAME range_reverse_iterator::type +rend( const C& c ) +{ + typedef BOOST_DEDUCED_TYPENAME range_reverse_iterator::type + iter_type; + return iter_type( boost::begin( c ) ); +} + +template< class T > +inline BOOST_DEDUCED_TYPENAME range_reverse_iterator::type +const_rend( const T& r ) +{ + return boost::rend( r ); +} + +} // namespace 'boost' + +#endif + diff --git a/libs/range/include/boost/range/result_iterator.hpp b/libs/range/include/boost/range/result_iterator.hpp new file mode 100644 index 00000000..48f88d7a --- /dev/null +++ b/libs/range/include/boost/range/result_iterator.hpp @@ -0,0 +1,37 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_RESULT_ITERATOR_HPP +#define BOOST_RANGE_RESULT_ITERATOR_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include + +BOOST_HEADER_DEPRECATED("") + +#include + +namespace boost +{ + // + // This interface is deprecated, use range_iterator + // + + template< typename C > + struct range_result_iterator : range_iterator + { }; + +} // namespace boost + + +#endif diff --git a/libs/range/include/boost/range/reverse_iterator.hpp b/libs/range/include/boost/range/reverse_iterator.hpp new file mode 100644 index 00000000..0aa0130a --- /dev/null +++ b/libs/range/include/boost/range/reverse_iterator.hpp @@ -0,0 +1,42 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_REVERSE_ITERATOR_HPP +#define BOOST_RANGE_REVERSE_ITERATOR_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include +#include + + +namespace boost +{ + ////////////////////////////////////////////////////////////////////////// + // default + ////////////////////////////////////////////////////////////////////////// + + template< typename T > + struct range_reverse_iterator + { + typedef reverse_iterator< + BOOST_DEDUCED_TYPENAME range_iterator< + BOOST_DEDUCED_TYPENAME remove_reference::type>::type > type; + }; + + +} // namespace boost + + +#endif diff --git a/libs/range/include/boost/range/reverse_result_iterator.hpp b/libs/range/include/boost/range/reverse_result_iterator.hpp new file mode 100644 index 00000000..e6e6f38d --- /dev/null +++ b/libs/range/include/boost/range/reverse_result_iterator.hpp @@ -0,0 +1,36 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_REVERSE_RESULT_ITERATOR_HPP +#define BOOST_RANGE_REVERSE_RESULT_ITERATOR_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include + +BOOST_HEADER_DEPRECATED("") + +#include + +namespace boost +{ + // + // This interface is deprecated, use range_reverse_iterator + // + + template< typename C > + struct range_reverse_result_iterator : range_reverse_iterator + { }; + +} // namespace boost + +#endif diff --git a/libs/range/include/boost/range/size.hpp b/libs/range/include/boost/range/size.hpp new file mode 100644 index 00000000..5f722d08 --- /dev/null +++ b/libs/range/include/boost/range/size.hpp @@ -0,0 +1,76 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_SIZE_HPP +#define BOOST_RANGE_SIZE_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + + template + inline typename ::boost::enable_if< + has_member_size, + typename range_size::type + >::type + range_calculate_size(const SinglePassRange& rng) + { + return rng.size(); + } + + template + inline typename disable_if< + has_member_size, + typename range_size::type + >::type + range_calculate_size(const SinglePassRange& rng) + { + return std::distance(boost::begin(rng), boost::end(rng)); + } + } + + template + inline typename range_size::type + size(const SinglePassRange& rng) + { +// Very strange things happen on some compilers that have the range concept +// asserts disabled. This preprocessor condition is clearly redundant on a +// working compiler but is vital for at least some compilers such as clang 4.2 +// but only on the Mac! +#if BOOST_RANGE_ENABLE_CONCEPT_ASSERT == 1 + BOOST_RANGE_CONCEPT_ASSERT((boost::SinglePassRangeConcept)); +#endif + +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) && \ + !BOOST_WORKAROUND(__GNUC__, < 3) \ + /**/ + using namespace range_detail; +#endif + + return range_calculate_size(rng); + } + +} // namespace 'boost' + +#endif diff --git a/libs/range/include/boost/range/size_type.hpp b/libs/range/include/boost/range/size_type.hpp new file mode 100644 index 00000000..0a2ea81b --- /dev/null +++ b/libs/range/include/boost/range/size_type.hpp @@ -0,0 +1,90 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_SIZE_TYPE_HPP +#define BOOST_RANGE_SIZE_TYPE_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace detail + { + + ////////////////////////////////////////////////////////////////////////// + // default + ////////////////////////////////////////////////////////////////////////// + + template + class has_size_type + { + typedef char no_type; + struct yes_type { char dummy[2]; }; + + template + static yes_type test(BOOST_DEDUCED_TYPENAME C::size_type x); + + template + static no_type test(...); + + public: + static const bool value = sizeof(test(0)) == sizeof(yes_type); + }; + + template + struct range_size_ + { + typedef BOOST_DEDUCED_TYPENAME make_unsigned< + BOOST_DEDUCED_TYPENAME range_difference::type + >::type type; + }; + + template + struct range_size_< + C, + BOOST_DEDUCED_TYPENAME ::boost::enable_if, void>::type + > + { + typedef BOOST_DEDUCED_TYPENAME C::size_type type; + }; + + template >::value> + struct range_size + { }; + + template + struct range_size + : range_size_ + { }; + } + + template< class T > + struct range_size : + detail::range_size + { }; + +} // namespace boost + + + +#endif diff --git a/libs/range/include/boost/range/sub_range.hpp b/libs/range/include/boost/range/sub_range.hpp new file mode 100644 index 00000000..d1c3b99b --- /dev/null +++ b/libs/range/include/boost/range/sub_range.hpp @@ -0,0 +1,287 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_SUB_RANGE_HPP +#define BOOST_RANGE_SUB_RANGE_HPP + +#include + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) + #pragma warning( push ) + #pragma warning( disable : 4996 ) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace range_detail + { + +template +class sub_range_base + : public iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator::type + > +{ + typedef iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator::type + > base; + +protected: + typedef BOOST_DEDUCED_TYPENAME base::iterator_range_ iterator_range_; + +public: + typedef BOOST_DEDUCED_TYPENAME range_value::type value_type; + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator; + typedef BOOST_DEDUCED_TYPENAME range_iterator::type const_iterator; + typedef BOOST_DEDUCED_TYPENAME range_difference::type difference_type; + typedef BOOST_DEDUCED_TYPENAME range_size::type size_type; + typedef BOOST_DEDUCED_TYPENAME range_reference::type reference; + typedef BOOST_DEDUCED_TYPENAME range_reference::type const_reference; + + sub_range_base() + { + } + + template + sub_range_base(Iterator first, Iterator last) + : base(first, last) + { + } + + reference front() + { + return base::front(); + } + + const_reference front() const + { + return base::front(); + } +}; + +template +class sub_range_base + : public sub_range_base +{ + typedef sub_range_base base; +public: + sub_range_base() + { + } + + template + sub_range_base(Iterator first, Iterator last) + : base(first, last) + { + } + + BOOST_DEDUCED_TYPENAME base::reference back() + { + return base::back(); + } + + BOOST_DEDUCED_TYPENAME base::const_reference back() const + { + return base::back(); + } +}; + +template +class sub_range_base + : public sub_range_base +{ + typedef sub_range_base base; + +public: + sub_range_base() + { + } + + template + sub_range_base(Iterator first, Iterator last) + : base(first, last) + { + } + + BOOST_DEDUCED_TYPENAME base::reference + operator[](BOOST_DEDUCED_TYPENAME base::difference_type n) + { + return this->begin()[n]; + } + + BOOST_DEDUCED_TYPENAME base::const_reference + operator[](BOOST_DEDUCED_TYPENAME base::difference_type n) const + { + return this->begin()[n]; + } +}; + + } // namespace range_detail + + template + class sub_range + : public range_detail::sub_range_base< + ForwardRange, + BOOST_DEDUCED_TYPENAME iterator_traversal< + BOOST_DEDUCED_TYPENAME range_iterator::type + >::type + > + { + typedef BOOST_DEDUCED_TYPENAME range_iterator< + ForwardRange + >::type iterator_t; + + typedef range_detail::sub_range_base< + ForwardRange, + BOOST_DEDUCED_TYPENAME iterator_traversal< + BOOST_DEDUCED_TYPENAME range_iterator::type + >::type + > base; + + typedef BOOST_DEDUCED_TYPENAME base::impl impl; + + protected: + typedef BOOST_DEDUCED_TYPENAME base::iterator_range_ iterator_range_; + + private: + template + struct is_compatible_range + : is_convertible< + BOOST_DEDUCED_TYPENAME mpl::eval_if< + has_range_iterator, + range_iterator, + mpl::identity + >::type, + BOOST_DEDUCED_TYPENAME base::iterator + > + { + }; + + public: + sub_range() + { } + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500) ) + sub_range(const sub_range& r) + : base(impl::adl_begin(const_cast(static_cast(r))), + impl::adl_end(const_cast(static_cast(r)))) + { } +#endif + + template< class ForwardRange2 > + sub_range( + ForwardRange2& r, + BOOST_DEDUCED_TYPENAME ::boost::enable_if< + is_compatible_range + >::type* = 0 + ) + : base(impl::adl_begin(r), impl::adl_end(r)) + { + } + + template< class ForwardRange2 > + sub_range( + const ForwardRange2& r, + BOOST_DEDUCED_TYPENAME ::boost::enable_if< + is_compatible_range + >::type* = 0 + ) + : base(impl::adl_begin(r), impl::adl_end(r)) + { + } + + BOOST_DEDUCED_TYPENAME base::const_iterator begin() const + { + return base::begin(); + } + + BOOST_DEDUCED_TYPENAME base::iterator begin() + { + return base::begin(); + } + + BOOST_DEDUCED_TYPENAME base::const_iterator end() const + { + return base::end(); + } + + BOOST_DEDUCED_TYPENAME base::iterator end() + { + return base::end(); + } + + template< class Iter > + sub_range( Iter first, Iter last ) : + base( first, last ) + { } + + template + BOOST_DEDUCED_TYPENAME ::boost::enable_if< + is_compatible_range, + sub_range& + >::type + operator=(ForwardRange2& r) + { + iterator_range_::operator=( r ); + return *this; + } + + template + BOOST_DEDUCED_TYPENAME ::boost::enable_if< + is_compatible_range, + sub_range& + >::type + operator=( const ForwardRange2& r ) + { + iterator_range_::operator=( r ); + return *this; + } + + sub_range& operator=( const sub_range& r ) + { + iterator_range_::operator=( static_cast(r) ); + return *this; + } + + sub_range& advance_begin( + BOOST_DEDUCED_TYPENAME base::difference_type n) + { + std::advance(this->m_Begin, n); + return *this; + } + + sub_range& advance_end( + BOOST_DEDUCED_TYPENAME base::difference_type n) + { + std::advance(this->m_End, n); + return *this; + } + }; + +} // namespace 'boost' + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) + #pragma warning( pop ) +#endif + +#endif + diff --git a/libs/range/include/boost/range/traversal.hpp b/libs/range/include/boost/range/traversal.hpp new file mode 100644 index 00000000..237b3e88 --- /dev/null +++ b/libs/range/include/boost/range/traversal.hpp @@ -0,0 +1,31 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_TRAVERSAL_HPP +#define BOOST_RANGE_TRAVERSAL_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include +#include + +namespace boost +{ + template + struct range_traversal + : iterator_traversal::type> + { + }; +} + +#endif diff --git a/libs/range/include/boost/range/value_type.hpp b/libs/range/include/boost/range/value_type.hpp new file mode 100644 index 00000000..5a3187ec --- /dev/null +++ b/libs/range/include/boost/range/value_type.hpp @@ -0,0 +1,30 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#ifndef BOOST_RANGE_VALUE_TYPE_HPP +#define BOOST_RANGE_VALUE_TYPE_HPP + +#if defined(_MSC_VER) +# pragma once +#endif + +#include +#include + +#include + +namespace boost +{ + template< class T > + struct range_value : iterator_value< typename range_iterator::type > + { }; +} + +#endif diff --git a/libs/range/index.html b/libs/range/index.html new file mode 100644 index 00000000..29b7f42c --- /dev/null +++ b/libs/range/index.html @@ -0,0 +1,16 @@ + + + + + Boost.Range Documentation + + + + + + Automatic redirection failed, please go to doc/html/index.html + + + + + diff --git a/libs/range/meta/libraries.json b/libs/range/meta/libraries.json new file mode 100644 index 00000000..03d8830f --- /dev/null +++ b/libs/range/meta/libraries.json @@ -0,0 +1,17 @@ +{ + "key": "range", + "name": "Range", + "authors": [ + "Niel Groves", + "Thorsten Ottosen" + ], + "description": "A new infrastructure for generic algorithms that builds on top of the new iterator concepts.", + "category": [ + "Algorithms" + ], + "maintainers": [ + "Neil Groves ", + "Nathan Ridge " + ], + "cxxstd": "03" +} diff --git a/libs/range/test/Jamfile.v2 b/libs/range/test/Jamfile.v2 new file mode 100644 index 00000000..cd2774e9 --- /dev/null +++ b/libs/range/test/Jamfile.v2 @@ -0,0 +1,226 @@ +# Boost.Range library +# +# Copyright Neil Groves 2009 +# Copyright Thorsten Ottosen 2003-2004. Use, modification and +# distribution is subject to 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) +# +# For more information, see http://www.boost.org/libs/range/ +# + +# bring in rules for testing +import testing ; + +project + : requirements + /boost/test//boost_unit_test_framework/ + /boost/regex//boost_regex/ + static + multi + ; + +rule range-test ( name : includes * ) +{ + return [ + run $(name).cpp /boost/test//boost_unit_test_framework /boost/regex//boost_regex/static + : + : + : gcc:"-Wall -Wunused " + ] ; +} + +test-suite range : + [ compile-fail compile_fail/iterator_range1.cpp ] + [ compile-fail compile_fail/adaptor/adjacent_filtered_concept.cpp ] + [ compile-fail compile_fail/adaptor/adjacent_filtered_concept2.cpp ] + [ compile-fail compile_fail/adaptor/adjacent_filtered_concept3.cpp ] + [ compile-fail compile_fail/adaptor/adjacent_filtered_concept4.cpp ] + [ compile-fail compile_fail/adaptor/copied_concept.cpp ] + [ compile-fail compile_fail/adaptor/copied_concept2.cpp ] + [ compile-fail compile_fail/adaptor/copied_concept3.cpp ] + [ compile-fail compile_fail/adaptor/copied_concept4.cpp ] + [ compile-fail compile_fail/adaptor/reversed_concept.cpp ] + [ compile-fail compile_fail/adaptor/reversed_concept2.cpp ] + [ compile-fail compile_fail/adaptor/reversed_concept3.cpp ] + [ compile-fail compile_fail/adaptor/reversed_concept4.cpp ] + [ compile-fail compile_fail/adaptor/sliced_concept.cpp ] + [ compile-fail compile_fail/adaptor/sliced_concept2.cpp ] + [ compile-fail compile_fail/adaptor/sliced_concept3.cpp ] + [ compile-fail compile_fail/adaptor/sliced_concept4.cpp ] + [ compile-fail compile_fail/adaptor/uniqued_concept.cpp ] + [ compile-fail compile_fail/adaptor/uniqued_concept2.cpp ] + [ compile-fail compile_fail/adaptor/uniqued_concept3.cpp ] + [ compile-fail compile_fail/adaptor/uniqued_concept4.cpp ] + [ range-test adaptor_test/adjacent_filtered ] + [ range-test adaptor_test/chained ] + [ range-test adaptor_test/copied ] + [ range-test adaptor_test/filtered ] + [ range-test adaptor_test/indexed ] + [ range-test adaptor_test/indirected ] + [ range-test adaptor_test/map ] + [ range-test adaptor_test/ref_unwrapped ] + [ range-test adaptor_test/ref_unwrapped_example ] + [ range-test adaptor_test/replaced ] + [ range-test adaptor_test/replaced_if ] + [ range-test adaptor_test/reversed ] + [ range-test adaptor_test/sliced ] + [ range-test adaptor_test/strided ] + [ range-test adaptor_test/strided2 ] + [ range-test adaptor_test/ticket_6742_transformed_c4789_warning ] + [ range-test adaptor_test/ticket_8676_sliced_transformed ] + [ range-test adaptor_test/ticket_9519_strided_reversed ] + [ range-test adaptor_test/tokenized ] + [ range-test adaptor_test/transformed ] + [ range-test adaptor_test/type_erased ] + [ range-test adaptor_test/type_erased_abstract ] + [ range-test adaptor_test/type_erased_brackets ] + [ range-test adaptor_test/type_erased_mix_values ] + [ range-test adaptor_test/type_erased_tparam_conv ] + [ range-test adaptor_test/type_erased_single_pass ] + [ range-test adaptor_test/type_erased_forward ] + [ range-test adaptor_test/type_erased_bidirectional ] + [ range-test adaptor_test/type_erased_random_access ] + [ range-test adaptor_test/type_erased_transformed ] + [ range-test adaptor_test/uniqued ] + [ range-test adaptor_test/adjacent_filtered_example ] + [ range-test adaptor_test/copied_example ] + [ range-test adaptor_test/filtered_example ] + [ range-test adaptor_test/formatted ] + [ range-test adaptor_test/formatted_example ] + [ range-test adaptor_test/indexed_example ] + [ range-test adaptor_test/indirected_example ] + [ range-test adaptor_test/map_keys_example ] + [ range-test adaptor_test/map_values_example ] + [ range-test adaptor_test/replaced_example ] + [ range-test adaptor_test/replaced_if_example ] + [ range-test adaptor_test/reversed_example ] + [ range-test adaptor_test/sliced_example ] + [ range-test adaptor_test/strided_example ] + [ range-test adaptor_test/transformed_example ] + [ range-test adaptor_test/tokenized_example ] + [ range-test adaptor_test/type_erased_example ] + [ range-test adaptor_test/uniqued_example ] + [ range-test algorithm_test/adjacent_find ] + [ range-test algorithm_test/binary_search ] + [ range-test algorithm_test/copy ] + [ range-test algorithm_test/copy_backward ] + [ range-test algorithm_test/count ] + [ range-test algorithm_test/count_if ] + [ range-test algorithm_test/equal ] + [ range-test algorithm_test/equal_range ] + [ range-test algorithm_test/fill ] + [ range-test algorithm_test/find ] + [ range-test algorithm_test/find_if ] + [ range-test algorithm_test/find_end ] + [ range-test algorithm_test/find_first_of ] + [ range-test algorithm_test/for_each ] + [ range-test algorithm_test/generate ] + [ range-test algorithm_test/heap ] + [ range-test algorithm_test/includes ] + [ range-test algorithm_test/inplace_merge ] + [ range-test algorithm_test/lexicographical_compare ] + [ range-test algorithm_test/lower_bound ] + [ range-test algorithm_test/max_element ] + [ range-test algorithm_test/merge ] + [ range-test algorithm_test/min_element ] + [ range-test algorithm_test/mismatch ] + [ range-test algorithm_test/next_permutation ] + [ range-test algorithm_test/nth_element ] + [ range-test algorithm_test/partial_sort ] + [ range-test algorithm_test/partition ] + [ range-test algorithm_test/prev_permutation ] + [ range-test algorithm_test/random_shuffle ] + [ range-test algorithm_test/remove ] + [ range-test algorithm_test/remove_copy ] + [ range-test algorithm_test/remove_copy_if ] + [ range-test algorithm_test/remove_if ] + [ range-test algorithm_test/replace ] + [ range-test algorithm_test/replace_copy ] + [ range-test algorithm_test/replace_copy_if ] + [ range-test algorithm_test/replace_if ] + [ range-test algorithm_test/reverse ] + [ range-test algorithm_test/reverse_copy ] + [ range-test algorithm_test/rotate ] + [ range-test algorithm_test/rotate_copy ] + [ range-test algorithm_test/search ] + [ range-test algorithm_test/search_n ] + [ range-test algorithm_test/set_difference ] + [ range-test algorithm_test/set_intersection ] + [ range-test algorithm_test/set_symmetric_difference ] + [ range-test algorithm_test/set_union ] + [ range-test algorithm_test/sort ] + [ range-test algorithm_test/stable_partition ] + [ range-test algorithm_test/stable_sort ] + [ range-test algorithm_test/swap_ranges ] + [ range-test algorithm_test/transform ] + [ range-test algorithm_test/unique ] + [ range-test algorithm_test/unique_copy ] + [ range-test algorithm_test/upper_bound ] + [ range-test algorithm_ext_test/copy_n ] + [ range-test algorithm_ext_test/erase ] + [ range-test algorithm_ext_test/for_each_ext ] + [ range-test algorithm_ext_test/insert ] + [ range-test algorithm_ext_test/iota ] + [ range-test algorithm_ext_test/is_sorted ] + [ range-test algorithm_ext_test/overwrite ] + [ range-test algorithm_ext_test/push_back ] + [ range-test algorithm_ext_test/push_front ] + [ range-test adl_conformance ] + [ range-test adl_conformance_no_using ] + [ range-test algorithm ] + [ range-test algorithm_example ] + [ range-test array ] +# [ range-test atl : $(VC71_ROOT)/atlmfc/include ] + [ range-test begin ] + [ range-test category ] + [ range-test combine ] + [ range-test compat2 ] + [ range-test compat3 ] + [ range-test const_iterator ] + [ range-test const_ranges ] + [ range-test const_reverse_iterator ] + [ range-test counting_range ] + [ range-test difference_type ] + [ range-test end ] + [ range-test extension_mechanism ] + [ range-test extension_size ] + [ range-test has_range_iterator ] + [ range-test irange ] + [ range-test istream_range ] + [ range-test iterator ] + [ range-test iterator_ext ] + [ range-test iterator_pair ] + [ range-test iterator_range ] + [ range-test iterator_range_drop ] + [ range-test iterator_range_equality_bug ] + [ range-test iterator_range_hash ] + [ range-test iterator_range_variant ] +# [ range-test mfc : $(VC71_ROOT)/atlmfc/include ] + [ range-test join ] + [ range-test mutable_iterator ] + [ range-test partial_workaround ] + [ range-test pointer ] + [ range-test pointer_as_iterator ] + [ range-test reference ] + [ range-test result_iterator ] + [ range-test reverse_iterator ] + [ range-test reverse_result_iterator ] + [ range-test reversible_range ] + [ range-test size_type ] + [ range-test std_container ] + [ range-test string ] + [ range-test sub_range ] + [ range-test ticket_5486 ] + [ range-test ticket_5544_terminate_irange ] + [ range-test ticket_5547 ] + [ range-test ticket_5556_is_sorted_namespace ] + [ range-test ticket_5811_indirected_optional ] + [ range-test ticket_6715_iterator_range_equality ] + [ range-test ticket_6944 ] + [ range-test ticket_10336 ] + [ range-test value_type ] + ; + +# `quick` target (for CI) +alias quick : std_container ; diff --git a/libs/range/test/adaptor_test/adjacent_filtered.cpp b/libs/range/test/adaptor_test/adjacent_filtered.cpp new file mode 100644 index 00000000..48025abf --- /dev/null +++ b/libs/range/test/adaptor_test/adjacent_filtered.cpp @@ -0,0 +1,110 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void adjacent_filtered_test_impl( Container& c ) + { + using namespace boost::adaptors; + + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + // This is my preferred syntax using the | operator. + std::vector< value_t > test_result1 + = boost::copy_range< std::vector< value_t > >( + c | adjacent_filtered(std::not_equal_to< value_t >())); + + // This is an alternative syntax preferred by some. + std::vector< value_t > test_result2 + = boost::copy_range< std::vector< value_t > >( + adaptors::adjacent_filter(c, std::not_equal_to< value_t >())); + + // Calculate the reference result. + std::vector< value_t > reference_result; + typedef BOOST_DEDUCED_TYPENAME Container::const_iterator iter_t; + value_t prev_v = value_t(); + for (iter_t it = c.begin(); it != c.end(); ++it) + { + if (it == c.begin()) + { + reference_result.push_back(*it); + } + else if (*it != prev_v) + { + reference_result.push_back(*it); + } + prev_v = *it; + } + + BOOST_CHECK_EQUAL_COLLECTIONS( reference_result.begin(), + reference_result.end(), + test_result1.begin(), + test_result1.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference_result.begin(), + reference_result.end(), + test_result2.begin(), + test_result2.end() ); + } + + template< class Collection > + void adjacent_filtered_test_impl() + { + using namespace boost::assign; + + Collection c; + + // test empty collection + adjacent_filtered_test_impl(c); + + // test one element; + c += 1; + adjacent_filtered_test_impl(c); + + // test many elements; + c += 1,2,2,2,3,4,4,4,4,5,6,7,8,9,9; + adjacent_filtered_test_impl(c); + } + + void adjacent_filtered_test() + { + adjacent_filtered_test_impl< std::vector< int > >(); + adjacent_filtered_test_impl< std::list< int > >(); + adjacent_filtered_test_impl< std::set< int > >(); + adjacent_filtered_test_impl< std::multiset< int > >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.adjacent_filtered" ); + + test->add( BOOST_TEST_CASE( &boost::adjacent_filtered_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/adjacent_filtered_example.cpp b/libs/range/test/adaptor_test/adjacent_filtered_example.cpp new file mode 100644 index 00000000..83f7a8ac --- /dev/null +++ b/libs/range/test/adaptor_test/adjacent_filtered_example.cpp @@ -0,0 +1,65 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[adjacent_filtered_example +#include +#include +#include +#include +#include +#include +#include + +//<- +#include + +#include +#include + +namespace +{ +void adjacent_filtered_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::assign; + using namespace boost::adaptors; + + std::vector input; + input += 1,1,2,2,2,3,4,5,6; + + boost::copy( + input | adjacent_filtered(std::not_equal_to()), + std::ostream_iterator(std::cout, ",")); + +//= return 0; +//=} +//] + std::vector reference; + reference += 1,2,3,4,5,6; + + std::vector test; + boost::push_back(test, input | adjacent_filtered(std::not_equal_to())); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.adjacent_filtered_example" ); + + test->add( BOOST_TEST_CASE( &adjacent_filtered_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/chained.cpp b/libs/range/test/adaptor_test/chained.cpp new file mode 100644 index 00000000..df9de433 --- /dev/null +++ b/libs/range/test/adaptor_test/chained.cpp @@ -0,0 +1,119 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +// Credits: +// Jurgen Hunold provided a test case that demonstrated that the range adaptors +// were producing iterators that were not default constructible. This became +// symptomatic after enabling concept checking assertions. This test is a +// lightly modified version of his supplied code to ensure that his use case +// never breaks again. (hopefully!) +// + +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace boost_range_test +{ + namespace + { + +class foo +{ +public: + static foo from_string(const std::string& source) + { + foo f; + f.m_valid = true; + f.m_value = 0u; + for (std::string::const_iterator it = source.begin(); + it != source.end(); ++it) + { + f.m_value += *it; + if ((*it < 'a') || (*it > 'z')) + f.m_valid = false; + } + return f; + } + bool is_valid() const + { + return m_valid; + } + bool operator<(const foo& other) const + { + return m_value < other.m_value; + } + bool operator==(const foo& other) const + { + return m_value == other.m_value && m_valid == other.m_valid; + } + bool operator!=(const foo& other) const + { + return !operator==(other); + } + + friend inline std::ostream& operator<<(std::ostream& out, const foo& obj) + { + out << "{value=" << obj.m_value + << ", valid=" << std::boolalpha << obj.m_valid << "}\n"; + return out; + } + +private: + boost::uint64_t m_value; + bool m_valid; +}; + +void chained_adaptors_test() +{ + std::vector sep; + + sep.push_back("AB"); + sep.push_back("ab"); + sep.push_back("aghj"); + + std::set foos; + + using namespace boost::placeholders; + + boost::copy(sep + | boost::adaptors::transformed(boost::bind(&foo::from_string, _1)) + | boost::adaptors::filtered(boost::bind(&foo::is_valid, _1)), + std::inserter(foos, foos.end())); + + std::vector reference; + reference.push_back(foo::from_string("ab")); + reference.push_back(foo::from_string("aghj")); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + foos.begin(), foos.end()); +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.chained adaptors" ); + + test->add(BOOST_TEST_CASE( boost_range_test::chained_adaptors_test)); + + return test; +} diff --git a/libs/range/test/adaptor_test/copied.cpp b/libs/range/test/adaptor_test/copied.cpp new file mode 100644 index 00000000..93f1cb79 --- /dev/null +++ b/libs/range/test/adaptor_test/copied.cpp @@ -0,0 +1,84 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void copied_test_impl( Container& c ) + { + using namespace boost::adaptors; + + // This is my preferred syntax using the | operator. + std::vector< int > test_result1; + boost::push_back(test_result1, c | copied(0u, c.size())); + + // This is the alternative syntax preferred by some. + std::vector< int > test_result2; + boost::push_back(test_result2, adaptors::copy(c, 0u, c.size())); + + BOOST_CHECK_EQUAL_COLLECTIONS( test_result1.begin(), test_result1.end(), + c.begin(), c.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( test_result2.begin(), test_result2.end(), + c.begin(), c.end() ); + } + + template< class Container > + void copied_test_impl() + { + using namespace boost::assign; + + Container c; + + // test empty collection + copied_test_impl(c); + + // test one element + c += 1; + copied_test_impl(c); + + // test many elements + c += 1,2,2,2,3,4,4,4,4,5,6,7,8,9,9; + copied_test_impl(c); + } + + void copied_test() + { + copied_test_impl< std::vector< int > >(); + copied_test_impl< std::deque< int > >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.copied" ); + + test->add( BOOST_TEST_CASE( &boost::copied_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/copied_example.cpp b/libs/range/test/adaptor_test/copied_example.cpp new file mode 100644 index 00000000..c1d0e31d --- /dev/null +++ b/libs/range/test/adaptor_test/copied_example.cpp @@ -0,0 +1,64 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[copied_example +#include +#include +#include +#include +#include +#include + +//<- +#include + +#include +#include + +namespace +{ +void copied_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::assign; + using namespace boost::adaptors; + + std::vector input; + input += 1,2,3,4,5,6,7,8,9,10; + + boost::copy( + input | copied(1, 5), + std::ostream_iterator(std::cout, ",")); + +//= return 0; +//=} +//] + std::vector reference; + reference += 2,3,4,5; + + std::vector test; + boost::push_back(test, input | copied(1, 5)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.copied_example" ); + + test->add( BOOST_TEST_CASE( &copied_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/filtered.cpp b/libs/range/test/adaptor_test/filtered.cpp new file mode 100644 index 00000000..be348726 --- /dev/null +++ b/libs/range/test/adaptor_test/filtered.cpp @@ -0,0 +1,197 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + struct always_false_pred + { + template< class T1 > + bool operator()(T1) const { return false; } + }; + + struct always_true_pred + { + template< class T1 > + bool operator()(T1) const { return true; } + }; + + struct is_even + { + template< class IntegerT > + bool operator()( IntegerT x ) const { return x % 2 == 0; } + }; + + struct is_odd + { + template< class IntegerT > + bool operator()( IntegerT x ) const { return x % 2 != 0; } + }; + + struct lambda_init + { + }; + + struct lambda + { + lambda(const lambda_init& init) {} + lambda(const lambda& rhs) {} + + template< class T1 > + bool operator()(T1) const { return false; } + + private: + lambda() {} + lambda& operator=(const lambda& rhs) { return *this; } + }; + + template< class Container, class Pred > + void filtered_test_impl( Container& c, Pred pred ) + { + using namespace boost::adaptors; + + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + // This is my preferred syntax using the | operator. + std::vector< value_t > test_result1; + boost::push_back(test_result1, c | filtered(pred)); + + // This is an alternative syntax preferred by some. + std::vector< value_t > test_result2; + boost::push_back(test_result2, adaptors::filter(c, pred)); + + // Calculate the reference result. + std::vector< value_t > reference_result; + typedef BOOST_DEDUCED_TYPENAME Container::const_iterator iter_t; + for (iter_t it = c.begin(); it != c.end(); ++it) + { + if (pred(*it)) + reference_result.push_back(*it); + } + + BOOST_CHECK_EQUAL_COLLECTIONS( reference_result.begin(), + reference_result.end(), + test_result1.begin(), + test_result1.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference_result.begin(), + reference_result.end(), + test_result2.begin(), + test_result2.end() ); + } + + template< class Rng > + void check_copy_assign(Rng r) + { + Rng r2 = r; + r2 = r; + } + + template< class Container, class Pred > + void filtered_range_copy_assign(Container& c, Pred pred) + { + using namespace boost::adaptors; + check_copy_assign(c | filtered(pred)); + check_copy_assign(adaptors::filter(c, pred)); + } + + template< class Container, class Pred, class PredInit > + void filtered_test_impl() + { + using namespace boost::assign; + + Container c; + PredInit init; + Pred pred(init); + + // test empty container + filtered_test_impl(c, pred); + + // test one element + c += 1; + filtered_test_impl(c, pred); + + // test many elements + c += 1,2,2,2,3,4,4,4,4,5,6,7,8,9,9; + filtered_test_impl(c, pred); + + // test the range and iterator are copy assignable + filtered_range_copy_assign(c, pred); + } + + template< class Container > + void filtered_test_all_predicates() + { + filtered_test_impl< Container, always_false_pred, always_false_pred >(); + filtered_test_impl< Container, always_true_pred, always_true_pred >(); + filtered_test_impl< Container, is_odd, is_odd >(); + filtered_test_impl< Container, is_even, is_even >(); + filtered_test_impl< Container, lambda, lambda_init >(); + } + + void ticket_10988_single_pass() + { + std::vector v; + std::string str("0 1 2 3 4 5"); + std::istringstream in(str); + + boost::push_back(v, + boost::make_iterator_range( + std::istream_iterator(in), + std::istream_iterator()) + | boost::adaptors::filtered(is_even())); + + std::vector reference; + for (int i = 0; i < 6; i += 2) + { + reference.push_back(i); + } + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + v.begin(), v.end()); + } + + void filtered_test() + { + filtered_test_all_predicates< std::vector< int > >(); + filtered_test_all_predicates< std::list< int > >(); + filtered_test_all_predicates< std::set< int > >(); + filtered_test_all_predicates< std::multiset< int > >(); + ticket_10988_single_pass(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.filtered" ); + + test->add( BOOST_TEST_CASE( &boost::filtered_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/filtered_example.cpp b/libs/range/test/adaptor_test/filtered_example.cpp new file mode 100644 index 00000000..e16d0af6 --- /dev/null +++ b/libs/range/test/adaptor_test/filtered_example.cpp @@ -0,0 +1,71 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[filtered_example +#include +#include +#include +#include +#include +#include + +//<- +#include +#include + +#include + +namespace +{ +//-> +struct is_even +{ + bool operator()( int x ) const { return x % 2 == 0; } +}; + +//<- +void filtered_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::assign; + using namespace boost::adaptors; + + std::vector input; + input += 1,2,3,4,5,6,7,8,9; + + boost::copy( + input | filtered(is_even()), + std::ostream_iterator(std::cout, ",")); + +//= return 0; +//=} +//] + std::vector reference; + reference += 2,4,6,8; + + std::vector test; + boost::push_back(test, input | filtered(is_even())); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.filtered_example" ); + + test->add( BOOST_TEST_CASE( &filtered_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/formatted.cpp b/libs/range/test/adaptor_test/formatted.cpp new file mode 100644 index 00000000..b6c1783c --- /dev/null +++ b/libs/range/test/adaptor_test/formatted.cpp @@ -0,0 +1,311 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost_range_test +{ + namespace + { + + template + std::string make_string(T x) + { + std::ostringstream result; + result << x; + return result.str(); + } + + template + std::string make_string(T1 x, T2 y) + { + std::ostringstream result; + result << x << y; + return result.str(); + } + +std::string reference_result(const std::vector& v, + const std::string& separator, + const std::string& prefix, + const std::string& postfix) +{ + std::ostringstream out; + out << prefix; + if (!v.empty()) + { + out << v.at(0); + std::vector::const_iterator it = v.begin(); + for (++it; it != v.end(); ++it) + { + out << separator << *it; + } + } + out << postfix; + + return out.str(); +} + +void test_formatted_0args_impl(const std::vector& v) +{ + std::ostringstream out1; + out1 << '[' << (v | boost::adaptors::formatted()) << ']'; + BOOST_CHECK_EQUAL(out1.str(), reference_result(v, ",", "[{", "}]")); + + std::ostringstream out2; + out2 << '[' << boost::adaptors::format(v) << ']'; + BOOST_CHECK_EQUAL(out2.str(), reference_result(v, ",", "[{", "}]")); + + std::ostringstream out3; + out3 << (v | boost::adaptors::formatted()); + BOOST_CHECK_EQUAL(out3.str(), reference_result(v, ",", "{", "}")); + + std::ostringstream out4; + out4 << boost::adaptors::format(v); + BOOST_CHECK_EQUAL(out4.str(), reference_result(v, ",", "{", "}")); +} + +template +void test_formatted_1arg_impl( + const std::vector& v, + const Sep& sep) +{ + const std::string ref_sep = make_string(sep); + std::ostringstream out1; + out1 << '[' << (v | boost::adaptors::formatted(sep)) << ']'; + + BOOST_CHECK_EQUAL(out1.str(), reference_result(v, ref_sep, "[{", "}]")); + + std::ostringstream out2; + out2 << '[' << boost::adaptors::format(v, sep) << ']'; + BOOST_CHECK_EQUAL(out2.str(), reference_result(v, ref_sep, "[{", "}]")); + + std::ostringstream out3; + out3 << (v | boost::adaptors::formatted(sep)); + BOOST_CHECK_EQUAL(out3.str(), reference_result(v, ref_sep, "{", "}")); + + std::ostringstream out4; + out4 << boost::adaptors::format(v, sep); + BOOST_CHECK_EQUAL(out4.str(), reference_result(v, ref_sep, "{", "}")); +} + +void test_formatted_1arg_impl(const std::vector& v) +{ + test_formatted_1arg_impl(v, ','); + test_formatted_1arg_impl(v, ' '); + test_formatted_1arg_impl(v, ":?"); +} + +template +void test_formatted_2args_impl( + const std::vector& v, + const Sep& sep, + const Prefix& prefix +) +{ + const std::string ref_sep = make_string(sep); + + std::ostringstream out1; + out1 << '[' << (v | boost::adaptors::formatted(sep, prefix)) << ']'; + BOOST_CHECK_EQUAL( + out1.str(), + reference_result(v, ref_sep, make_string('[', prefix), "}]")); + + std::ostringstream out2; + out2 << '[' << boost::adaptors::format(v, sep, prefix) << ']'; + BOOST_CHECK_EQUAL( + out2.str(), + reference_result(v, ref_sep, make_string('[', prefix), "}]")); + + std::ostringstream out3; + out3 << (v | boost::adaptors::formatted(sep, prefix)); + BOOST_CHECK_EQUAL( + out3.str(), + reference_result(v, ref_sep, make_string(prefix), "}")); + + std::ostringstream out4; + out4 << boost::adaptors::format(v, sep, prefix); + BOOST_CHECK_EQUAL( + out4.str(), + reference_result(v, ref_sep, make_string(prefix), "}")); +} + +void test_formatted_2args_impl(const std::vector& v) +{ + test_formatted_2args_impl(v, ',', '{'); + test_formatted_2args_impl(v, ':', '('); + test_formatted_2args_impl(v, ',', "{!"); + test_formatted_2args_impl(v, "#$", '{'); + test_formatted_2args_impl(v, "#$", "{!"); +} + +template +void test_formatted_3args_impl( + const std::vector& v, + const Sep& sep, + const Prefix& prefix, + const Postfix& postfix +) +{ + const std::string ref_sep = make_string(sep); + + std::ostringstream out1; + out1 << '[' << (v | boost::adaptors::formatted(sep, prefix, postfix)) + << ']'; + BOOST_CHECK_EQUAL( + out1.str(), + reference_result(v, ref_sep, make_string('[', prefix), + make_string(postfix, ']'))); +} + +void test_formatted_3args_impl(const std::vector& v) +{ + test_formatted_3args_impl(v, ',', '{', '}'); + test_formatted_3args_impl(v, ':', '(', ')'); + test_formatted_3args_impl(v, ',', '{', "!}"); + test_formatted_3args_impl(v, ',', "{!", '}'); + test_formatted_3args_impl(v, "#$", '{', '}'); + test_formatted_3args_impl< + const char[3], const char[3], const char[3] + >(v, "#$", "{!", "!}"); +} + +void test_formatted_impl(const std::vector& v) +{ + test_formatted_0args_impl(v); + test_formatted_1arg_impl(v); + test_formatted_2args_impl(v); + test_formatted_3args_impl(v); +} + +void test_formatted1() +{ + std::vector v; + for (boost::int32_t i = 0; i < 10; ++i) + v.push_back(i); + + test_formatted_impl(v); +} + +void test_formatted2() +{ + std::vector v; + v.push_back(3); + + test_formatted_impl(v); +} + +void test_formatted3() +{ + std::vector v; + + test_formatted_impl(v); +} + +void test_formatted4() +{ + std::vector v; + for (boost::int32_t i = 0; i < 5; ++i) + v.push_back(i); + + test_formatted_impl(v); +} + +struct udt_separator +{ +}; + +template +inline std::basic_ostream& +operator<<(std::basic_ostream& out, udt_separator) +{ + return out << "[sep]"; +} + +void test_formatted5() +{ + std::vector v; + for (boost::int32_t i = 0; i < 5; ++i) + v.push_back(i); + + std::ostringstream out1; + out1 << (v | boost::adaptors::formatted(udt_separator())); + BOOST_CHECK_EQUAL(out1.str(), "{0[sep]1[sep]2[sep]3[sep]4}"); + + std::ostringstream out2; + out2 << boost::adaptors::format(v, udt_separator()); + BOOST_CHECK_EQUAL(out2.str(), "{0[sep]1[sep]2[sep]3[sep]4}"); +} + +// This test is already covered by the more complex code above. This +// code duplicates coverage to ensure that char literal arrays are handled +// correctly. I was particularly concerned that my test code above may pass +// erroneously by decaying a char literal to a pointer. This function makes +// it very plain that character literal strings work. +void test_formatted_empty() +{ + std::vector v; + + std::ostringstream out1; + out1 << (v | boost::adaptors::formatted()); + BOOST_CHECK_EQUAL(out1.str(), "{}"); + + std::ostringstream out2; + out2 << boost::adaptors::format(v); + BOOST_CHECK_EQUAL(out2.str(), "{}"); + + std::ostringstream out3; + out3 << (v | boost::adaptors::formatted(',')); + BOOST_CHECK_EQUAL(out3.str(), "{}"); + + std::ostringstream out4; + out4 << boost::adaptors::format(v, ','); + BOOST_CHECK_EQUAL(out4.str(), "{}"); + + std::ostringstream out5; + out5 << (v | boost::adaptors::formatted("#$")); + BOOST_CHECK_EQUAL(out5.str(), "{}"); + + std::ostringstream out6; + out6 << boost::adaptors::format(v, "#$"); + BOOST_CHECK_EQUAL(out6.str(), "{}"); + + std::ostringstream out7; + out7 << (v | boost::adaptors::formatted("", "12", "34")); + BOOST_CHECK_EQUAL(out7.str(), "1234"); + + std::ostringstream out8; + out8 << boost::adaptors::format(v, "", "12", "34"); + BOOST_CHECK_EQUAL(out8.str(), "1234"); +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite(int, char*[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE( "Boost.Range formatted test suite" ); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted1)); + test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted2)); + test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted3)); + test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted4)); + test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted5)); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_formatted_empty)); + + return test; +} diff --git a/libs/range/test/adaptor_test/formatted_example.cpp b/libs/range/test/adaptor_test/formatted_example.cpp new file mode 100644 index 00000000..838a6712 --- /dev/null +++ b/libs/range/test/adaptor_test/formatted_example.cpp @@ -0,0 +1,61 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[formatted_example +#include +#include +#include +#include +#include +#include +#include + +//<- +#include +#include + +#include + +namespace +{ +void formatted_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::assign; + + std::vector input; + input += 1,2,3,4,5; + + std::cout << boost::adaptors::format(input) << std::endl; + + // Alternatively this can be written: + // std::cout << (input | boost::adaptors::formatted()) << std::endl; + +//= return 0; +//=} +//] + std::ostringstream test; + test << boost::adaptors::format(input); + + BOOST_CHECK_EQUAL(test.str(), "{1,2,3,4,5}"); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.formatted_example" ); + + test->add( BOOST_TEST_CASE( &formatted_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/indexed.cpp b/libs/range/test/adaptor_test/indexed.cpp new file mode 100644 index 00000000..f4085be0 --- /dev/null +++ b/libs/range/test/adaptor_test/indexed.cpp @@ -0,0 +1,152 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "../test_utils.hpp" + +namespace boost_range_test +{ + namespace + { + +template +void check_result( + const Container& reference_range, + const AdaptedRange& adapted_range, + std::ptrdiff_t start_index + ) +{ + typedef typename boost::range_iterator::type + reference_iterator; + + typedef typename boost::range_iterator::type + adapted_iterator; + + BOOST_REQUIRE_EQUAL(boost::size(reference_range), + boost::size(adapted_range)); + + reference_iterator reference_it = boost::begin(reference_range); + adapted_iterator adapted_it = boost::begin(adapted_range); + for (std::ptrdiff_t i = start_index; + reference_it != boost::end(reference_range); + ++reference_it, ++adapted_it, ++i) + { + BOOST_CHECK_EQUAL(i, adapted_it->index()); + BOOST_CHECK_EQUAL(*reference_it, adapted_it->value()); + } +} + +template +void indexed_test_impl(Container& c, std::ptrdiff_t start_index) +{ + // This is my preferred syntax using the | operator. + check_result(c, c | boost::adaptors::indexed(), 0); + check_result(c, c | boost::adaptors::indexed(start_index), start_index); + + // This is the function syntax + check_result(c, boost::adaptors::index(c), 0); + check_result(c, boost::adaptors::index(c, start_index), start_index); +} + +template +void indexed_test_impl(Container& c) +{ + indexed_test_impl(c, 0); + indexed_test_impl(c, -1); + indexed_test_impl(c, 4); +} + +template +void indexed_test_impl() +{ + using namespace boost::assign; + + Container c; + + // test empty container + indexed_test_impl(c); + + // test one element + c += 1; + indexed_test_impl(c); + + // test many elements + c += 1,2,2,2,3,4,4,4,4,5,6,7,8,9,9; + indexed_test_impl(c); +} + +template +void check_traversal(const Range& rng) +{ + BOOST_STATIC_ASSERT( + boost::is_convertible< + typename boost::range_traversal::type, + Traversal + >::value); +} + +template +void check_not_traversal(const Range& rng) +{ + BOOST_STATIC_ASSERT( + !boost::is_convertible< + typename boost::range_traversal::type, + Traversal + >::value); +} + +void indexed_test() +{ + indexed_test_impl< std::vector< int > >(); + indexed_test_impl< std::list< int > >(); + + std::vector vi; + + check_traversal( + vi | boost::adaptors::indexed()); + + std::list li; + + check_traversal( + li | boost::adaptors::indexed()); + + check_not_traversal( + li | boost::adaptors::indexed()); + + check_not_traversal( + li | boost::adaptors::indexed()); +} + + } // anonymous namesapce +} // namespace boost_range_test + +boost::unit_test::test_suite* +init_unit_test_suite(int, char*[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "Boost.Range indexed adaptor test suite" ); + + test->add(BOOST_TEST_CASE(&boost_range_test::indexed_test)); + + return test; +} diff --git a/libs/range/test/adaptor_test/indexed_example.cpp b/libs/range/test/adaptor_test/indexed_example.cpp new file mode 100644 index 00000000..c65e62e1 --- /dev/null +++ b/libs/range/test/adaptor_test/indexed_example.cpp @@ -0,0 +1,104 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[indexed_example + +//<- +#include +//-> + +#include +#include +#include +#include +#include + +//<- +#include +#include + +namespace +{ + +template +void check_element_and_index( + Iterator1 test_first, + Iterator1 test_last, + Iterator2 reference_first, + Iterator2 reference_last) +{ + BOOST_CHECK_EQUAL( std::distance(test_first, test_last), + std::distance(reference_first, reference_last) ); + + std::ptrdiff_t reference_index = 0; + + Iterator1 test_it = test_first; + Iterator2 reference_it = reference_first; + for (; test_it != test_last; ++test_it, ++reference_it, ++reference_index) + { + BOOST_CHECK_EQUAL(test_it->value(), *reference_it); + BOOST_CHECK_EQUAL(test_it->index(), reference_index); + } +} + +template +void check_element_and_index( + const SinglePassRange1& test_rng, + const SinglePassRange2& reference_rng) +{ + check_element_and_index( + boost::begin(test_rng), boost::end(test_rng), + boost::begin(reference_rng), boost::end(reference_rng)); +} +//-> + +//<- +void indexed_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::assign; + using namespace boost::adaptors; + + std::vector input; + input += 10,20,30,40,50,60,70,80,90; + +//<- +#ifndef BOOST_NO_CXX11_RANGE_BASED_FOR +//-> + for (const auto& element : input | indexed(0)) + { + std::cout << "Element = " << element.value() + << " Index = " << element.index() + << std::endl; + } +//<- +#endif // C++11 has range for loop +//-> + +//= return 0; +//=} +//] + check_element_and_index( + input | indexed(0), + input); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.indexed_example" ); + + test->add( BOOST_TEST_CASE( &indexed_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/indirected.cpp b/libs/range/test/adaptor_test/indirected.cpp new file mode 100644 index 00000000..fe3ebdfa --- /dev/null +++ b/libs/range/test/adaptor_test/indirected.cpp @@ -0,0 +1,99 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost +{ + namespace + { + + template< class Container > + void indirected_test_impl( Container& c ) + { + using namespace boost::adaptors; + + // This is my preferred syntax using the | operator. + std::vector< int > test_result1; + boost::push_back(test_result1, c | indirected); + + // This is an alternative syntax preferred by some. + std::vector< int > test_result2; + boost::push_back(test_result2, adaptors::indirect(c)); + + // Calculate the reference result. + std::vector< int > reference_result; + typedef BOOST_DEDUCED_TYPENAME Container::const_iterator iter_t; + for (iter_t it = c.begin(); it != c.end(); ++it) + { + reference_result.push_back(**it); + } + + BOOST_CHECK_EQUAL_COLLECTIONS( reference_result.begin(), + reference_result.end(), + test_result1.begin(), + test_result1.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference_result.begin(), + reference_result.end(), + test_result2.begin(), + test_result2.end() ); + } + + template< class Container > + void indirected_test_impl() + { + using namespace boost::assign; + + Container c; + + indirected_test_impl(c); + + c += boost::shared_ptr(new int(1)); + indirected_test_impl(c); + + std::vector v; + v += 1,1,2,2,2,3,4,4,4,4,5,6,7,8,9,9; + for (std::vector::const_iterator it = v.begin(); it != v.end(); ++it) + { + c += boost::shared_ptr(new int(*it)); + } + indirected_test_impl(c); + } + + void indirected_test() + { + indirected_test_impl< std::vector< boost::shared_ptr< int > > >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.indirected" ); + + test->add( BOOST_TEST_CASE( &boost::indirected_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/indirected_example.cpp b/libs/range/test/adaptor_test/indirected_example.cpp new file mode 100644 index 00000000..8b538b5a --- /dev/null +++ b/libs/range/test/adaptor_test/indirected_example.cpp @@ -0,0 +1,66 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[indirected_example +#include +#include +#include +#include +#include +#include + +//<- +#include +#include + +#include + +namespace +{ +void indirected_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::adaptors; + + std::vector > input; + + for (int i = 0; i < 10; ++i) + input.push_back(boost::shared_ptr(new int(i))); + + boost::copy( + input | indirected, + std::ostream_iterator(std::cout, ",")); + +//= return 0; +//=} +//] + std::vector reference; + for (int i = 0; i < 10; ++i) + reference.push_back(i); + + std::vector test; + boost::push_back(test, input | indirected); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.indirected_example" ); + + test->add( BOOST_TEST_CASE( &indirected_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/map.cpp b/libs/range/test/adaptor_test/map.cpp new file mode 100644 index 00000000..615b4677 --- /dev/null +++ b/libs/range/test/adaptor_test/map.cpp @@ -0,0 +1,171 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void map_test_keys( Container& c ) + { + using namespace boost::adaptors; + + std::vector keys; + boost::push_back(keys, c | map_keys); + + std::vector keys2; + boost::push_back(keys2, adaptors::keys(c)); + + std::vector reference_keys; + typedef BOOST_DEDUCED_TYPENAME Container::const_iterator iter_t; + for (iter_t it = c.begin(); it != c.end(); ++it) + { + reference_keys.push_back(it->first); + } + + BOOST_CHECK_EQUAL_COLLECTIONS( reference_keys.begin(), + reference_keys.end(), + keys.begin(), + keys.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference_keys.begin(), + reference_keys.end(), + keys2.begin(), + keys2.end() ); + } + + template< class Container > + void map_test_values( Container& c ) + { + using namespace boost::adaptors; + + std::vector values; + boost::push_back(values, c | map_values); + + std::vector values2; + boost::push_back(values2, adaptors::values(c)); + + std::vector reference_values; + typedef BOOST_DEDUCED_TYPENAME Container::const_iterator iter_t; + for (iter_t it = c.begin(); it != c.end(); ++it) + { + reference_values.push_back(it->second); + } + + BOOST_CHECK_EQUAL_COLLECTIONS( reference_values.begin(), + reference_values.end(), + values.begin(), + values.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference_values.begin(), + reference_values.end(), + values2.begin(), + values2.end() ); + } + + template< class Container > + void map_test_impl() + { + using namespace boost::assign; + + Container c; + + // Test empty + map_test_keys(c); + map_test_values(c); + + // Test one element + c.insert(std::make_pair(1,2)); + map_test_keys(c); + map_test_values(c); + + // Test many elements + for (int x = 2; x < 10; ++x) + { + c.insert(std::make_pair(x, x * 2)); + } + map_test_keys(c); + map_test_values(c); + } + + void map_test() + { + map_test_impl< std::map >(); + } + + void test_trac_item_4388() + { + typedef std::pair pair_t; + const boost::array ar = {{ + pair_t(3, 'a'), + pair_t(1, 'b'), + pair_t(4, 'c') + }}; + + const boost::array expected_keys = {{ 3, 1, 4 }}; + const boost::array expected_values = {{ 'a', 'b', 'c' }}; + + { + std::vector test; + boost::push_back(test, ar | boost::adaptors::map_keys); + BOOST_CHECK_EQUAL_COLLECTIONS( + expected_keys.begin(), expected_keys.end(), + test.begin(), test.end() + ); + } + + { + std::vector test; + boost::push_back(test, ar | boost::adaptors::map_values); + BOOST_CHECK_EQUAL_COLLECTIONS( + expected_values.begin(), expected_values.end(), + test.begin(), test.end() + ); + } + + { + std::vector test; + boost::array, 3> src(ar); + boost::push_back(test, src | boost::adaptors::map_values); + BOOST_CHECK_EQUAL_COLLECTIONS( + expected_values.begin(), expected_values.end(), + test.begin(), test.end() + ); + } + } + + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.map" ); + + test->add( BOOST_TEST_CASE( &boost::map_test ) ); + test->add( BOOST_TEST_CASE( &boost::test_trac_item_4388 ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/map_keys_example.cpp b/libs/range/test/adaptor_test/map_keys_example.cpp new file mode 100644 index 00000000..99f8505c --- /dev/null +++ b/libs/range/test/adaptor_test/map_keys_example.cpp @@ -0,0 +1,66 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[map_keys_example +#include +#include +#include +#include +#include +#include +#include + +//<- +#include +#include + +#include + +namespace +{ +void map_keys_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::assign; + using namespace boost::adaptors; + + std::map input; + for (int i = 0; i < 10; ++i) + input.insert(std::make_pair(i, i * 10)); + + boost::copy( + input | map_keys, + std::ostream_iterator(std::cout, ",")); + +//= return 0; +//=} +//] + std::vector reference; + reference += 0,1,2,3,4,5,6,7,8,9; + + std::vector test; + boost::push_back(test, input | map_keys); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.map_keys_example" ); + + test->add( BOOST_TEST_CASE( &map_keys_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/map_values_example.cpp b/libs/range/test/adaptor_test/map_values_example.cpp new file mode 100644 index 00000000..bfa533fd --- /dev/null +++ b/libs/range/test/adaptor_test/map_values_example.cpp @@ -0,0 +1,66 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[map_values_example +#include +#include +#include +#include +#include +#include +#include + +//<- +#include +#include + +#include + +namespace +{ +void map_values_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::assign; + using namespace boost::adaptors; + + std::map input; + for (int i = 0; i < 10; ++i) + input.insert(std::make_pair(i, i * 10)); + + boost::copy( + input | map_values, + std::ostream_iterator(std::cout, ",")); + +//= return 0; +//=} +//] + std::vector reference; + reference += 0,10,20,30,40,50,60,70,80,90; + + std::vector test; + boost::push_back(test, input | map_values); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.map_values_example" ); + + test->add( BOOST_TEST_CASE( &map_values_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/ref_unwrapped.cpp b/libs/range/test/adaptor_test/ref_unwrapped.cpp new file mode 100644 index 00000000..c476b741 --- /dev/null +++ b/libs/range/test/adaptor_test/ref_unwrapped.cpp @@ -0,0 +1,101 @@ +// Boost.Range library +// +// Copyright Robin Eckert 2015. Use, modification and distribution is +// subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#define BOOST_TEST_MAIN + +#include +#include + +#include + +#if !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && !defined(BOOST_NO_CXX11_RANGE_BASED_FOR) && !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) + +namespace boost +{ + + BOOST_AUTO_TEST_CASE(test_mutable) + { + int one = 1; + int two = 2; + int three = 3; + + std::vector> input_values{one, two, three}; + + const std::vector expected{&one, &two, &three}; + std::vector actual; + + for (auto&& value : input_values | adaptors::ref_unwrapped) + { + actual.push_back(&value); + } + + BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), + expected.end(), + actual.begin(), + actual.end()); + } + + BOOST_AUTO_TEST_CASE(test_const_range) + { + int one = 1; + int two = 2; + int three = 3; + + const std::vector> input_values{one, two, three}; + + const std::vector expected{&one, &two, &three}; + std::vector actual; + + for (auto&& value : input_values | adaptors::ref_unwrapped) + { + actual.push_back(&value); + } + + BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), + expected.end(), + actual.begin(), + actual.end()); + } + + BOOST_AUTO_TEST_CASE(test_const_reference) + { + const int one = 1; + const int two = 2; + const int three = 3; + + const std::vector> input_values{one, two, three}; + + const std::vector expected{&one, &two, &three}; + std::vector actual; + + for (auto&& value : input_values | adaptors::ref_unwrapped) + { + actual.push_back(&value); + } + + BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), + expected.end(), + actual.begin(), + actual.end()); + } + + +} + +#else + +BOOST_AUTO_TEST_CASE(empty) +{ + // C++11 only +} + +#endif diff --git a/libs/range/test/adaptor_test/ref_unwrapped_example.cpp b/libs/range/test/adaptor_test/ref_unwrapped_example.cpp new file mode 100644 index 00000000..ab3e4016 --- /dev/null +++ b/libs/range/test/adaptor_test/ref_unwrapped_example.cpp @@ -0,0 +1,47 @@ +// Boost.Range library +// +// Copyright Robin Eckert 2015. Use, modification and distribution is +// subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[ref_unwrapped_example +#include +#include +#include + +struct example +{ + int value; +}; + +int main(int argc, const char* argv[]) +{ +//<- +#if !defined(BOOST_NO_CXX11_DECLTYPE) \ + && !defined(BOOST_NO_CXX11_RANGE_BASED_FOR) \ + && !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) \ + && !defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) +//-> + using boost::adaptors::ref_unwrapped; + + example one{1}; + example two{2}; + example three{3}; + + std::vector > input{one, two, three}; + + for (auto&& entry : input | ref_unwrapped) + { + std::cout << entry.value; + } + + return 0; +//<- +#endif +//-> +} +//] diff --git a/libs/range/test/adaptor_test/replaced.cpp b/libs/range/test/adaptor_test/replaced.cpp new file mode 100644 index 00000000..d3eac813 --- /dev/null +++ b/libs/range/test/adaptor_test/replaced.cpp @@ -0,0 +1,87 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void replaced_test_impl( Container& c ) + { + using namespace boost::adaptors; + + const int value_to_replace = 1; + const int replacement_value = 0; + + std::vector< int > test_result1; + boost::push_back(test_result1, c | replaced(value_to_replace, replacement_value)); + + std::vector< int > test_result2; + boost::push_back(test_result2, adaptors::replace(c, value_to_replace, replacement_value)); + + std::vector< int > reference( c.begin(), c.end() ); + std::replace(reference.begin(), reference.end(), value_to_replace, replacement_value); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test_result1.begin(), test_result1.end() ); + } + + template< class Container > + void replaced_test_impl() + { + using namespace boost::assign; + + Container c; + + // Test empty + replaced_test_impl(c); + + // Test one + c += 1; + replaced_test_impl(c); + + // Test many + c += 1,1,1,2,2,2,3,3,3,3,3,4,5,6,6,6,7,8,9; + replaced_test_impl(c); + } + + void replaced_test() + { + replaced_test_impl< std::vector< int > >(); + replaced_test_impl< std::list< int > >(); + replaced_test_impl< std::set< int > >(); + replaced_test_impl< std::multiset< int > >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.replaced" ); + + test->add( BOOST_TEST_CASE( &boost::replaced_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/replaced_example.cpp b/libs/range/test/adaptor_test/replaced_example.cpp new file mode 100644 index 00000000..8e1f1145 --- /dev/null +++ b/libs/range/test/adaptor_test/replaced_example.cpp @@ -0,0 +1,64 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[replaced_example +#include +#include +#include +#include +#include +#include + +//<- +#include +#include + +#include + +namespace +{ +void replaced_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::adaptors; + using namespace boost::assign; + + std::vector input; + input += 1,2,3,2,5,2,7,2,9; + + boost::copy( + input | replaced(2, 10), + std::ostream_iterator(std::cout, ",")); + +//= return 0; +//=} +//] + std::vector reference; + reference += 1,10,3,10,5,10,7,10,9; + + std::vector test; + boost::push_back(test, input | replaced(2, 10)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.replaced_example" ); + + test->add( BOOST_TEST_CASE( &replaced_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/replaced_if.cpp b/libs/range/test/adaptor_test/replaced_if.cpp new file mode 100644 index 00000000..0bf227f3 --- /dev/null +++ b/libs/range/test/adaptor_test/replaced_if.cpp @@ -0,0 +1,96 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace boost +{ + namespace + { + struct if_value_is_one + { + bool operator()(int x) const { return x == 1; } + }; + + template< class Container > + void replaced_if_test_impl( Container& c ) + { + using namespace boost::adaptors; + + if_value_is_one pred; + + const int replacement_value = 0; + + std::vector< int > test_result1; + boost::push_back(test_result1, c | replaced_if(pred, replacement_value)); + + std::vector< int > test_result2; + boost::push_back(test_result2, boost::adaptors::replace_if(c, pred, replacement_value)); + + std::vector< int > reference( c.begin(), c.end() ); + std::replace_if(reference.begin(), reference.end(), pred, replacement_value); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test_result1.begin(), test_result1.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test_result2.begin(), test_result2.end() ); + } + + template< class Container > + void replaced_if_test_impl() + { + using namespace boost::assign; + + Container c; + + // Test empty + replaced_if_test_impl(c); + + // Test one + c += 1; + replaced_if_test_impl(c); + + // Test many + c += 1,1,1,2,2,2,3,3,3,3,3,4,5,6,6,6,7,8,9; + replaced_if_test_impl(c); + } + + void replaced_if_test() + { + replaced_if_test_impl< std::vector< int > >(); + replaced_if_test_impl< std::list< int > >(); + replaced_if_test_impl< std::set< int > >(); + replaced_if_test_impl< std::multiset< int > >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.replaced_if" ); + + test->add( BOOST_TEST_CASE( &boost::replaced_if_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/replaced_if_example.cpp b/libs/range/test/adaptor_test/replaced_if_example.cpp new file mode 100644 index 00000000..05b5e780 --- /dev/null +++ b/libs/range/test/adaptor_test/replaced_if_example.cpp @@ -0,0 +1,71 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[replaced_if_example +#include +#include +#include +#include +#include +#include + +//<- +#include +#include + +#include + +namespace +{ +//-> +struct is_even +{ + bool operator()(int x) const { return x % 2 == 0; } +}; + +//<- +void replaced_if_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::adaptors; + using namespace boost::assign; + + std::vector input; + input += 1,2,3,4,5,6,7,8,9; + + boost::copy( + input | replaced_if(is_even(), 10), + std::ostream_iterator(std::cout, ",")); + +//= return 0; +//=} +//] + std::vector reference; + reference += 1,10,3,10,5,10,7,10,9; + + std::vector test; + boost::push_back(test, input | replaced_if(is_even(), 10)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.replaced_if_example" ); + + test->add( BOOST_TEST_CASE( &replaced_if_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/reversed.cpp b/libs/range/test/adaptor_test/reversed.cpp new file mode 100644 index 00000000..6663b368 --- /dev/null +++ b/libs/range/test/adaptor_test/reversed.cpp @@ -0,0 +1,84 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace boost +{ + template< class Container > + void reversed_test_impl( Container& c ) + { + using namespace boost::adaptors; + + std::vector< int > test_result1; + boost::push_back(test_result1, c | reversed); + + std::vector< int > test_result2; + boost::push_back(test_result2, adaptors::reverse(c)); + + std::vector< int > reference( c.rbegin(), c.rend() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test_result1.begin(), test_result1.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test_result2.begin(), test_result2.end() ); + } + + template< class Container > + void reversed_test_impl() + { + using namespace boost::assign; + + Container c; + + // Test empty + reversed_test_impl(c); + + // Test one + c += 1; + reversed_test_impl(c); + + // Test many + c += 1,1,1,2,2,2,2,2,3,3,3,3,3,3,4,5,6,7,8,9; + reversed_test_impl(c); + } + + void reversed_test() + { + reversed_test_impl< std::vector< int > >(); + reversed_test_impl< std::list< int > >(); + reversed_test_impl< std::set< int > >(); + reversed_test_impl< std::multiset< int > >(); + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.reversed" ); + + test->add( BOOST_TEST_CASE( &boost::reversed_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/reversed_example.cpp b/libs/range/test/adaptor_test/reversed_example.cpp new file mode 100644 index 00000000..585108fc --- /dev/null +++ b/libs/range/test/adaptor_test/reversed_example.cpp @@ -0,0 +1,61 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[reversed_example +#include +#include +#include +#include +#include +#include + +//<- +#include +#include + +#include + +namespace +{ +void reversed_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::adaptors; + using namespace boost::assign; + + std::vector input; + input += 1,2,3,4,5,6,7,8,9; + + boost::copy( + input | reversed, + std::ostream_iterator(std::cout, ",")); + +//= return 0; +//=} +//] + std::vector test; + boost::push_back(test, input | reversed); + + BOOST_CHECK_EQUAL_COLLECTIONS( input.rbegin(), input.rend(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.reversed_example" ); + + test->add( BOOST_TEST_CASE( &reversed_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/sliced.cpp b/libs/range/test/adaptor_test/sliced.cpp new file mode 100644 index 00000000..f2221f66 --- /dev/null +++ b/libs/range/test/adaptor_test/sliced.cpp @@ -0,0 +1,99 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include + +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void sliced_test_impl( Container& c ) + { + using namespace boost::adaptors; + + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector< value_t > test_result1; + boost::push_back(test_result1, c | sliced(0u,c.size())); + + BOOST_CHECK_EQUAL_COLLECTIONS( test_result1.begin(), test_result1.end(), + c.begin(), c.end() ); + + std::vector< value_t > test_alt_result1; + boost::push_back(test_alt_result1, adaptors::slice(c, 0u, c.size())); + BOOST_CHECK_EQUAL_COLLECTIONS( test_alt_result1.begin(), test_alt_result1.end(), + c.begin(), c.end() ); + + BOOST_CHECK( boost::empty(c | sliced(0u, 0u)) ); + + const std::size_t half_count = c.size() / 2u; + if (half_count > 0u) + { + std::vector< value_t > test_result2; + boost::push_back(test_result2, c | sliced(0u, half_count)); + + BOOST_CHECK_EQUAL_COLLECTIONS( test_result2.begin(), test_result2.end(), + c.begin(), c.begin() + half_count ); + + std::vector< value_t > test_alt_result2; + boost::push_back(test_alt_result2, adaptors::slice(c, 0u, half_count)); + BOOST_CHECK_EQUAL_COLLECTIONS( test_alt_result2.begin(), test_alt_result2.end(), + c.begin(), c.begin() + half_count ); + } + } + + template< class Container > + void sliced_test_impl() + { + using namespace boost::assign; + + Container c; + + // Test empty + sliced_test_impl(c); + + // Test one element + c += 1; + sliced_test_impl(c); + + // Test many elements + c += 1,1,1,2,2,3,4,5,6,6,6,7,8,9; + sliced_test_impl(c); + } + + void sliced_test() + { + sliced_test_impl< std::vector< int > >(); + sliced_test_impl< std::deque< int > >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.sliced" ); + + test->add( BOOST_TEST_CASE( &boost::sliced_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/sliced_example.cpp b/libs/range/test/adaptor_test/sliced_example.cpp new file mode 100644 index 00000000..2b156910 --- /dev/null +++ b/libs/range/test/adaptor_test/sliced_example.cpp @@ -0,0 +1,64 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[sliced_example +#include +#include +#include +#include +#include +#include + +//<- +#include +#include + +#include + +namespace +{ +void sliced_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::adaptors; + using namespace boost::assign; + + std::vector input; + input += 1,2,3,4,5,6,7,8,9; + + boost::copy( + input | sliced(2, 5), + std::ostream_iterator(std::cout, ",")); + +//= return 0; +//=} +//] + std::vector reference; + reference += 3,4,5; + + std::vector test; + boost::push_back(test, input | sliced(2, 5)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.sliced_example" ); + + test->add( BOOST_TEST_CASE( &sliced_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/strided.cpp b/libs/range/test/adaptor_test/strided.cpp new file mode 100644 index 00000000..46c16fa9 --- /dev/null +++ b/libs/range/test/adaptor_test/strided.cpp @@ -0,0 +1,313 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +// The strided_defect_Trac5014 test case is a modified version of a test case +// contributed by Maxim Yanchenko as part of the trac ticket. +// +// The deque test case has been removed due to erroneous standard library +// implementations causing test failures. +// +#include + +#include +#include +#include + +#include +#include + +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void strided_test_impl( Container& c, int stride_size ) + { + using namespace boost::adaptors; + + // Rationale: + // This requirement was too restrictive. It makes the use of the + // strided adaptor too dangerous, and a simple solution existed + // to make it safe, hence the strided adaptor has been modified + // and this restriction no longer applies. + //BOOST_ASSERT( c.size() % STRIDE_SIZE == 0 ); + + Container reference; + + { + typedef BOOST_DEDUCED_TYPENAME Container::const_iterator + iterator_t BOOST_RANGE_UNUSED; + typedef BOOST_DEDUCED_TYPENAME Container::difference_type + diff_t BOOST_RANGE_UNUSED; + typedef BOOST_DEDUCED_TYPENAME Container::size_type + size_type BOOST_RANGE_UNUSED; + iterator_t it = c.begin(); + + iterator_t last = c.end(); + for (; it != last; ) + { + reference.push_back(*it); + + for (int i = 0; (it != last) && (i < stride_size); ++i) + ++it; + } + } + + Container test; + boost::push_back( test, c | strided(stride_size) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), + reference.begin(), reference.end() ); + + Container test2; + boost::push_back( test2, adaptors::stride(c, stride_size) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( test2.begin(), test2.end(), + reference.begin(), reference.end() ); + + // Test the const versions: + const Container& cc = c; + Container test3; + boost::push_back( test3, cc | strided(stride_size) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( test3.begin(), test3.end(), + reference.begin(), reference.end() ); + + Container test4; + boost::push_back( test4, adaptors::stride(cc, stride_size) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( test4.begin(), test4.end(), + reference.begin(), reference.end() ); + } + + template< class Container > + void strided_test_impl(int stride_size) + { + using namespace boost::assign; + + Container c; + + // Test empty + strided_test_impl(c, stride_size); + + // Test two elements + c += 1,2; + strided_test_impl(c, stride_size); + + // Test many elements + c += 1,1,1,2,2,3,4,5,6,6,6,7,8,9; + strided_test_impl(c, stride_size); + + // Test an odd number of elements to determine that the relaxation + // of the requirements has been successful + // Test a sequence of length 1 with a stride of 2 + c.clear(); + c += 1; + strided_test_impl(c, stride_size); + + // Test a sequence of length 2 with a stride of 2 + c.clear(); + c += 1,2; + strided_test_impl(c, stride_size); + + // Test a sequence of length 3 with a stride of 2 + c.clear(); + c += 1,2,3; + strided_test_impl(c, stride_size); + } + + template + void strided_test_zero_stride() + { + Container c; + c.push_back(1); + + typedef boost::strided_range strided_range_t; + strided_range_t rng( boost::adaptors::stride(c, 0) ); + boost::ignore_unused_variable_warning(rng); + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + + typedef BOOST_DEDUCED_TYPENAME boost::iterator_traversal< + BOOST_DEDUCED_TYPENAME Container::const_iterator + >::type container_traversal_tag; + + iter_t first = boost::range_detail::make_begin_strided_iterator( + c, 0, container_traversal_tag()); + + iter_t last = boost::range_detail::make_end_strided_iterator( + c, 0, container_traversal_tag()); + + iter_t it = first; + for (int i = 0; i < 10; ++i, ++it) + { + BOOST_CHECK(it == first); + } + } + + template + void strided_test_impl() + { + strided_test_zero_stride< Container >(); + + const int MAX_STRIDE_SIZE = 10; + for (int stride_size = 1; stride_size <= MAX_STRIDE_SIZE; ++stride_size) + { + strided_test_impl< Container >(stride_size); + } + } + + void strided_test() + { + strided_test_impl< std::vector >(); + strided_test_impl< std::list >(); + } + + void strided_defect_Trac5014() + { + using namespace boost::assign; + + std::vector v; + for (int i = 0; i < 30; ++i) + v.push_back(i); + + std::vector reference; + reference += 0,4,8,12,16,20,24,28; + + std::vector output; + boost::push_back(output, v | boost::adaptors::strided(4)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + output.begin(), output.end() ); + + BOOST_CHECK_EQUAL( output.back(), 28 ); + } + + template + class strided_mock_iterator + : public boost::iterator_adaptor< + strided_mock_iterator + , BaseIterator + , boost::use_default + , Category + > + { + typedef boost::iterator_adaptor< + strided_mock_iterator + , BaseIterator + , boost::use_default + , Category + > super_t; + public: + explicit strided_mock_iterator(BaseIterator it) + : super_t(it) + { + } + + private: + void increment() + { + ++(this->base_reference()); + } + + friend class boost::iterator_core_access; + }; + + template + boost::iterator_range::type, Category> > + as_mock_range(Range& rng) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type range_iter_t; + typedef strided_mock_iterator mock_iter_t; + + return boost::iterator_range( + mock_iter_t(boost::begin(rng)), + mock_iter_t(boost::end(rng))); + } + + void strided_test_traversal() + { + using namespace boost::assign; + + std::vector v; + for (int i = 0; i < 30; ++i) + v.push_back(i); + + std::vector reference; + reference += 0,4,8,12,16,20,24,28; + + std::vector output; + boost::push_back(output, as_mock_range(v) | boost::adaptors::strided(4)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + output.begin(), output.end() ); + + output.clear(); + boost::push_back(output, as_mock_range(v) | boost::adaptors::strided(4)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + output.begin(), output.end() ); + + output.clear(); + boost::push_back(output, as_mock_range(v) | boost::adaptors::strided(4)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + output.begin(), output.end() ); + } + + template + void strided_test_ticket_5236_check_bidirectional(const Range& rng) + { + BOOST_CHECK_EQUAL( boost::distance(rng), 1 ); + BOOST_CHECK_EQUAL( std::distance(boost::begin(rng), boost::prior(boost::end(rng))), 0 ); + } + + template + void strided_test_ticket_5236_check(const Range& rng) + { + strided_test_ticket_5236_check_bidirectional(rng); + + typename boost::range_iterator::type it = boost::end(rng); + it = it - 1; + BOOST_CHECK_EQUAL( std::distance(boost::begin(rng), it), 0 ); + } + + void strided_test_ticket_5236() + { + std::vector v; + v.push_back(1); + strided_test_ticket_5236_check( v | boost::adaptors::strided(2) ); + + // Ensure that there is consistency between the random-access implementation + // and the bidirectional. + + std::list l; + l.push_back(1); + strided_test_ticket_5236_check_bidirectional( l | boost::adaptors::strided(2) ); + } + + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.strided" ); + + test->add( BOOST_TEST_CASE( &boost::strided_test ) ); + test->add( BOOST_TEST_CASE( &boost::strided_defect_Trac5014 ) ); + test->add( BOOST_TEST_CASE( &boost::strided_test_traversal ) ); + test->add( BOOST_TEST_CASE( &boost::strided_test_ticket_5236 ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/strided2.cpp b/libs/range/test/adaptor_test/strided2.cpp new file mode 100644 index 00000000..4ac91f50 --- /dev/null +++ b/libs/range/test/adaptor_test/strided2.cpp @@ -0,0 +1,67 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// + +// This test was added due to a report that the Range Adaptors: +// 1. Caused havoc when using namespace boost::adaptors was used +// 2. Did not work with non-member functions +// 3. The strided adaptor could not be composed with sliced +// +// None of these issues could be reproduced on GCC 4.4, but this +// work makes for useful additional test coverage since this +// uses chaining of adaptors and non-member functions whereas +// most of the tests avoid this use case. + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +namespace boost +{ + namespace + { + int times_two(int x) { return x * 2; } + + void strided_test2() + { + using namespace boost::adaptors; + using namespace boost::assign; + std::vector v; + boost::push_back(v, boost::irange(0,10)); + std::vector z; + boost::push_back(z, v | sliced(2,6) | strided(2) | transformed(×_two)); + std::vector reference; + reference += 4,8; + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + z.begin(), z.end() ); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.strided2" ); + + test->add( BOOST_TEST_CASE( &boost::strided_test2 ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/strided_example.cpp b/libs/range/test/adaptor_test/strided_example.cpp new file mode 100644 index 00000000..b1f8b424 --- /dev/null +++ b/libs/range/test/adaptor_test/strided_example.cpp @@ -0,0 +1,64 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[strided_example +#include +#include +#include +#include +#include +#include + +//<- +#include +#include + +#include + +namespace +{ +void strided_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::adaptors; + using namespace boost::assign; + + std::vector input; + input += 1,2,3,4,5,6,7,8,9,10; + + boost::copy( + input | strided(2), + std::ostream_iterator(std::cout, ",")); + +//= return 0; +//=} +//] + std::vector reference; + reference += 1,3,5,7,9; + + std::vector test; + boost::push_back(test, input | strided(2)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.strided_example" ); + + test->add( BOOST_TEST_CASE( &strided_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/ticket_6742_transformed_c4789_warning.cpp b/libs/range/test/adaptor_test/ticket_6742_transformed_c4789_warning.cpp new file mode 100644 index 00000000..fdd71180 --- /dev/null +++ b/libs/range/test/adaptor_test/ticket_6742_transformed_c4789_warning.cpp @@ -0,0 +1,69 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + struct test_struct + { + double x; + double y; + }; + + struct get_x + { + typedef double result_type; + double operator()(const test_struct& s) const + { + return s.x; + } + }; + + void range_transformed_warning() + { + using namespace boost::phoenix::arg_names; + using namespace boost::adaptors; + + test_struct t; + t.x = 2.0; + t.y = -4.0; + std::vector v(10u, t); + + std::vector output1; + boost::push_back(output1, v | transformed((&arg1)->*& test_struct::x)); + + std::vector output2; + boost::push_back(output2, v | transformed(get_x())); + + BOOST_CHECK_EQUAL_COLLECTIONS( + output1.begin(), output1.end(), + output2.begin(), output2.end()); + } +} // anonymous namespace + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "Range adaptors - transformed warning" ); + + test->add(BOOST_TEST_CASE(&range_transformed_warning)); + + return test; +} diff --git a/libs/range/test/adaptor_test/ticket_8676_sliced_transformed.cpp b/libs/range/test/adaptor_test/ticket_8676_sliced_transformed.cpp new file mode 100644 index 00000000..da0125ec --- /dev/null +++ b/libs/range/test/adaptor_test/ticket_8676_sliced_transformed.cpp @@ -0,0 +1,56 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include +#include +#include + +namespace +{ + struct identity + { + typedef int result_type; + result_type operator()(int i) const { return i; } + }; + + void sliced_and_transformed() + { + using namespace boost::adaptors; + + std::vector input; + for (int i = 0; i < 10; ++i) + input.push_back(i); + + std::vector out1; + boost::push_back(out1, input | sliced(2, 8) + | transformed(identity())); + + std::vector out2; + boost::push_back(out2, input | transformed(identity()) + | sliced(2, 8)); + + BOOST_CHECK_EQUAL_COLLECTIONS(out1.begin(), out1.end(), + out2.begin(), out2.end()); + } +} // anonymous namespace + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "Range adaptors - sliced and transformed" ); + + test->add(BOOST_TEST_CASE(&sliced_and_transformed)); + + return test; +} diff --git a/libs/range/test/adaptor_test/ticket_9519_strided_reversed.cpp b/libs/range/test/adaptor_test/ticket_9519_strided_reversed.cpp new file mode 100644 index 00000000..0c915981 --- /dev/null +++ b/libs/range/test/adaptor_test/ticket_9519_strided_reversed.cpp @@ -0,0 +1,67 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +// Credit goes to Eric Niebler for providing an example to demonstrate this +// issue. This has been trivially modified to create this test case. +// +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace boost +{ + namespace + { + +void ticket_9519_strided_reversed_test() +{ + using namespace boost::adaptors; + + std::vector vi; + for (int i = 0; i < 50; ++i) + { + vi.push_back(i); + } + + std::vector output; + boost::push_back(output, vi | strided(3) | reversed); + + std::list reference; + for (int i = 0; i < 50; i += 3) + { + reference.push_front(i); + } + + BOOST_CHECK_EQUAL_COLLECTIONS(output.begin(), output.end(), + reference.begin(), reference.end()); +} + + } // anonymous namespace +} // namespace boost + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( + "RangeTestSuite.adaptor.ticket_9519_strided_reversed"); + + test->add(BOOST_TEST_CASE(&boost::ticket_9519_strided_reversed_test)); + + return test; +} + diff --git a/libs/range/test/adaptor_test/tokenized.cpp b/libs/range/test/adaptor_test/tokenized.cpp new file mode 100644 index 00000000..8180747c --- /dev/null +++ b/libs/range/test/adaptor_test/tokenized.cpp @@ -0,0 +1,79 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include + +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Iterator, class Container > + void tokenized_test_impl( Container& c, std::size_t expected_result ) + { + using namespace boost::adaptors; + + std::vector< boost::sub_match< Iterator > > test_result1; + boost::push_back(test_result1, c | tokenized(boost::regex("\\b"))); + + BOOST_CHECK_EQUAL( test_result1.size(), expected_result ); + +// std::vector< boost::sub_match< Iterator > > test_result2; +// boost::push_back(test_result2, adaptors::tokenize(c, boost::regex("\\b"))); + +// BOOST_CHECK_EQUAL( test_result2.size(), expected_result ); + } + + template< class Container1, class Container2 > + void tokenized_test_impl() + { + Container1 c; + Container2& r = c; + + typedef typename boost::range_iterator::type It; + + // Test empty + tokenized_test_impl(r, 0u); + + // Test one element + c = "a"; + tokenized_test_impl(r, 2u); + + // Test many elements + c = "a b c d e f g hijlmnopqrstuvwxyz"; + tokenized_test_impl(r, 16u); + } + + void tokenized_test() + { +// tokenized_test_impl(); + tokenized_test_impl(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.tokenized" ); + + test->add( BOOST_TEST_CASE( &boost::tokenized_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/tokenized_example.cpp b/libs/range/test/adaptor_test/tokenized_example.cpp new file mode 100644 index 00000000..5f59bb16 --- /dev/null +++ b/libs/range/test/adaptor_test/tokenized_example.cpp @@ -0,0 +1,65 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[tokenized_example +#include +#include +#include +#include +#include +#include + +//<- +#include +#include + +#include + +namespace +{ +void tokenized_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::adaptors; + + typedef boost::sub_match< std::string::iterator > match_type; + + std::string input = " a b c d e f g hijklmnopqrstuvwxyz"; + boost::copy( + input | tokenized(boost::regex("\\w+")), + std::ostream_iterator(std::cout, "\n")); + +//= return 0; +//=} +//] + using namespace boost::assign; + + std::vector reference; + reference += "a","b","c","d","e","f","g","hijklmnopqrstuvwxyz"; + + std::vector test; + boost::push_back(test, input | tokenized(boost::regex("\\w+"))); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.tokenized_example" ); + + test->add( BOOST_TEST_CASE( &tokenized_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/transformed.cpp b/libs/range/test/adaptor_test/transformed.cpp new file mode 100644 index 00000000..4620a157 --- /dev/null +++ b/libs/range/test/adaptor_test/transformed.cpp @@ -0,0 +1,171 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace boost +{ + namespace + { + struct double_x + { + typedef int result_type; + int operator()(int x) const { return x * 2; } + }; + + struct halve_x + { + typedef int result_type; + int operator()(int x) const { return x / 2; } + }; + + struct lambda_init + { + }; + + struct lambda + { + typedef int result_type; + + lambda(const lambda_init& init) {} + lambda(const lambda& rhs) {} + + int operator()(int x) const { return x + 1; } + + private: + lambda() {} + lambda& operator=(const lambda& rhs) { return *this; } + }; + + template< class Container, class TransformFn > + void transformed_test_impl_core( Container& c, TransformFn fn ) + { + using namespace boost::adaptors; + + std::vector< int > test_result1; + boost::push_back(test_result1, c | transformed(fn)); + + std::vector< int > test_result2; + boost::push_back(test_result2, adaptors::transform(c, fn)); + + std::vector< int > reference; + std::transform(c.begin(), c.end(), std::back_inserter(reference), fn); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test_result1.begin(), test_result1.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test_result2.begin(), test_result2.end() ); + } + + template< class Rng > + void check_copy_assign(Rng r) + { + Rng r2 = r; + r2 = r; + } + + template< class Container, class TransformFn > + void transformed_range_copy_assign(Container& c, TransformFn fn) + { + using namespace boost::adaptors; + check_copy_assign(c | transformed(fn)); + check_copy_assign(adaptors::transform(c, fn)); + } + + template< class Container, class TransformFn, class TransformFnInit > + void transformed_test_fn_impl() + { + using namespace boost::assign; + + Container c; + TransformFnInit init; + TransformFn fn( init ); + + // Test empty + transformed_test_impl_core(c, fn); + + // Test one element + c += 1; + transformed_test_impl_core(c, fn); + + // Test many elements + c += 1,1,1,2,2,2,2,2,3,4,5,6,7,8,9; + transformed_test_impl_core(c, fn); + + // test the range and iterator are copy assignable + transformed_range_copy_assign(c, fn); + } + + template< class Container > + void transformed_test_impl() + { + transformed_test_fn_impl< Container, double_x, double_x >(); + transformed_test_fn_impl< Container, halve_x, halve_x >(); + transformed_test_fn_impl< Container, lambda, lambda_init >(); + } + + void transformed_test() + { + transformed_test_impl< std::vector< int > >(); + transformed_test_impl< std::list< int > >(); + transformed_test_impl< std::set< int > >(); + transformed_test_impl< std::multiset< int > >(); + } + + struct foo_bind + { + int foo() const { return 7; } + }; + + void transformed_bind() + { + using namespace boost::adaptors; + using namespace boost::placeholders; + + std::vector input(5); + std::vector output; + boost::range::push_back( + output, + input | transformed(boost::bind(&foo_bind::foo, _1))); + + BOOST_CHECK_EQUAL(output.size(), input.size()); + + std::vector reference_output(5, 7); + BOOST_CHECK_EQUAL_COLLECTIONS( + output.begin(), output.end(), + reference_output.begin(), reference_output.end()); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.transformed" ); + + test->add(BOOST_TEST_CASE(&boost::transformed_test)); + test->add(BOOST_TEST_CASE(&boost::transformed_bind)); + + return test; +} diff --git a/libs/range/test/adaptor_test/transformed_example.cpp b/libs/range/test/adaptor_test/transformed_example.cpp new file mode 100644 index 00000000..ff4a689a --- /dev/null +++ b/libs/range/test/adaptor_test/transformed_example.cpp @@ -0,0 +1,72 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[transformed_example +#include +#include +#include +#include +#include +#include + +//<- +#include +#include + +#include + +namespace +{ +//-> +struct double_int +{ + typedef int result_type; + int operator()(int x) const { return x * 2; } +}; + +//<- +void transformed_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::adaptors; + using namespace boost::assign; + + std::vector input; + input += 1,2,3,4,5,6,7,8,9,10; + + boost::copy( + input | transformed(double_int()), + std::ostream_iterator(std::cout, ",")); + +//= return 0; +//=} +//] + std::vector reference; + reference += 2,4,6,8,10,12,14,16,18,20; + + std::vector test; + boost::push_back(test, input | transformed(double_int())); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.transformed_example" ); + + test->add( BOOST_TEST_CASE( &transformed_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/type_erased.cpp b/libs/range/test/adaptor_test/type_erased.cpp new file mode 100644 index 00000000..edea1c46 --- /dev/null +++ b/libs/range/test/adaptor_test/type_erased.cpp @@ -0,0 +1,44 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +#include +#include "type_erased_test.hpp" + +#include + +#include +#include + +namespace boost_range_adaptor_type_erased_test +{ + namespace + { + +void test_type_erased() +{ + test_driver< std::list >(); + test_driver< std::vector >(); + + test_driver< std::list >(); + test_driver< std::vector >(); +} + + } // anonymous namespace +} // namespace boost_range_adaptor_type_erased_test + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased"); + + test->add(BOOST_TEST_CASE( + &boost_range_adaptor_type_erased_test::test_type_erased)); + + return test; +} + diff --git a/libs/range/test/adaptor_test/type_erased_abstract.cpp b/libs/range/test/adaptor_test/type_erased_abstract.cpp new file mode 100644 index 00000000..dd548905 --- /dev/null +++ b/libs/range/test/adaptor_test/type_erased_abstract.cpp @@ -0,0 +1,88 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +#include +#include "type_erased_test.hpp" + +#include + +#include + +namespace boost_range_adaptor_type_erased_test +{ + namespace + { + +class dummy_interface +{ +public: + virtual ~dummy_interface() { } + virtual void test() = 0; +protected: + dummy_interface() { } +private: + dummy_interface(const dummy_interface&); + void operator=(const dummy_interface&); +}; + +class dummy_impl + : public dummy_interface +{ +public: + dummy_impl() { } + dummy_impl(const dummy_impl&) { } + dummy_impl& operator=(const dummy_impl&) { return *this; } + virtual void test() { } +}; + +typedef boost::any_range< + dummy_interface, + boost::random_access_traversal_tag, + dummy_interface&, + std::ptrdiff_t +> any_interface_range; + +struct foo_dummy_interface_fn +{ + void operator()(dummy_interface& iface) + { + iface.test(); + } +}; + +void foo_test_dummy_interface_range(any_interface_range rng) +{ + std::for_each(boost::begin(rng), boost::end(rng), + foo_dummy_interface_fn()); +} + +void test_type_erased_abstract() +{ + std::vector v(10); + + any_interface_range r(v); + + foo_test_dummy_interface_range(r); + + foo_test_dummy_interface_range(any_interface_range(v)); +} + + } // anonymous namespace +} // namespace boost_range_adaptor_type_erased_test + +boost::unit_test::test_suite* +init_unit_test_suite(int, char*[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_abstract"); + + test->add( + BOOST_TEST_CASE( + &boost_range_adaptor_type_erased_test::test_type_erased_abstract)); + + return test; +} diff --git a/libs/range/test/adaptor_test/type_erased_bidirectional.cpp b/libs/range/test/adaptor_test/type_erased_bidirectional.cpp new file mode 100644 index 00000000..3dc86fea --- /dev/null +++ b/libs/range/test/adaptor_test/type_erased_bidirectional.cpp @@ -0,0 +1,57 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +#include +#include "type_erased_test.hpp" + +#include + +#include +#include +#include + +namespace boost_range_adaptor_type_erased_test +{ + namespace + { + +void test_bidirectional() +{ + test_type_erased_exercise_buffer_types< + std::list, boost::bidirectional_traversal_tag >(); + + test_type_erased_exercise_buffer_types< + std::deque, boost::bidirectional_traversal_tag >(); + + test_type_erased_exercise_buffer_types< + std::vector, boost::bidirectional_traversal_tag >(); + + test_type_erased_exercise_buffer_types< + std::list, boost::bidirectional_traversal_tag >(); + + test_type_erased_exercise_buffer_types< + std::deque, boost::bidirectional_traversal_tag >(); + + test_type_erased_exercise_buffer_types< + std::vector, boost::bidirectional_traversal_tag >(); +} + + } // anonymous namespace +} // namespace boost_range_adaptor_type_erased_test + +boost::unit_test::test_suite* +init_unit_test_suite(int, char*[]) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_bidirectional"); + + test->add(BOOST_TEST_CASE( + &boost_range_adaptor_type_erased_test::test_bidirectional)); + + return test; +} + diff --git a/libs/range/test/adaptor_test/type_erased_brackets.cpp b/libs/range/test/adaptor_test/type_erased_brackets.cpp new file mode 100644 index 00000000..9d5c7dda --- /dev/null +++ b/libs/range/test/adaptor_test/type_erased_brackets.cpp @@ -0,0 +1,70 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +#include +#include "type_erased_test.hpp" + +#include + +#include + +namespace boost_range_adaptor_type_erased_test +{ + namespace + { + +void test_operator_brackets() +{ + typedef boost::adaptors::type_erased<> type_erased_t; + + std::vector c; + for (int i = 0; i < 10; ++i) + c.push_back(i); + + typedef boost::any_range_type_generator< + std::vector >::type any_range_type; + + BOOST_STATIC_ASSERT(( + boost::is_same< + int, + boost::range_value::type + >::value + )); + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::random_access_traversal_tag, + boost::iterator_traversal< + boost::range_iterator::type + >::type + >::value + )); + + any_range_type rng = c | type_erased_t(); + + for (int i = 0; i < 10; ++i) + { + BOOST_CHECK_EQUAL(rng[i], i); + } +} + + } // anonymous namespace +} // namespace boost_range_adaptor_type_erased_test + +boost::unit_test::test_suite* +init_unit_test_suite(int, char*[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_brackets"); + + test->add( + BOOST_TEST_CASE( + &boost_range_adaptor_type_erased_test::test_operator_brackets)); + + return test; +} + diff --git a/libs/range/test/adaptor_test/type_erased_example.cpp b/libs/range/test/adaptor_test/type_erased_example.cpp new file mode 100644 index 00000000..f8416ae0 --- /dev/null +++ b/libs/range/test/adaptor_test/type_erased_example.cpp @@ -0,0 +1,124 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[type_erased_example +#include +#include +#include +#include +#include +#include +#include +#include +//<- +#include +#include + +namespace +{ + namespace boost_range_test + { + namespace type_erased_example + { +//-> + +// The client interface from an OO perspective merely requires a sequence +// of integers that can be forward traversed +typedef boost::any_range< + int + , boost::forward_traversal_tag + , int + , std::ptrdiff_t +> integer_range; + +namespace server +{ + void display_integers(const integer_range& rng) + { + boost::copy(rng, + std::ostream_iterator(std::cout, ",")); + + std::cout << std::endl; + } +} + +namespace client +{ + void run() + { + using namespace boost::assign; + using namespace boost::adaptors; + + // Under most conditions one would simply use an appropriate + // any_range as a function parameter. The type_erased adaptor + // is often superfluous. However because the type_erased + // adaptor is applied to a range, we can use default template + // arguments that are generated in conjunction with the + // range type to which we are applying the adaptor. + + std::vector input; + input += 1,2,3,4,5; + + // Note that this call is to a non-template function + server::display_integers(input); + + std::list input2; + input2 += 6,7,8,9,10; + + // Note that this call is to the same non-tempate function + server::display_integers(input2); + + input2.clear(); + input2 += 11,12,13,14,15; + + // Calling using the adaptor looks like this: + // Notice that here I have a type_erased that would be a + // bidirectional_traversal_tag, but this is convertible + // to the forward_traversal_tag equivalent hence this + // works. + server::display_integers(input2 | type_erased<>()); + + // However we may simply wish to define an adaptor that + // takes a range and makes it into an appropriate + // forward_traversal any_range... + typedef boost::adaptors::type_erased< + boost::use_default + , boost::forward_traversal_tag + > type_erased_forward; + + // This adaptor can turn other containers with different + // value_types and reference_types into the appropriate + // any_range. + + server::display_integers(input2 | type_erased_forward()); + } +} + +//=int main(int argc, const char* argv[]) +//={ +//= client::run(); +//= return 0; +//=} +//] + + } // namespace type_erased_example + } // namespace boost_range_test +} // anonymous namespace + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.type_erased_example" ); + + test->add( BOOST_TEST_CASE( &boost_range_test::type_erased_example::client::run) ); + + return test; +} diff --git a/libs/range/test/adaptor_test/type_erased_forward.cpp b/libs/range/test/adaptor_test/type_erased_forward.cpp new file mode 100644 index 00000000..7f6540f7 --- /dev/null +++ b/libs/range/test/adaptor_test/type_erased_forward.cpp @@ -0,0 +1,57 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +#include +#include "type_erased_test.hpp" + +#include + +#include +#include +#include + +namespace boost_range_adaptor_type_erased_test +{ + namespace + { + +void test_forward() +{ + test_type_erased_exercise_buffer_types< + std::list, boost::forward_traversal_tag >(); + + test_type_erased_exercise_buffer_types< + std::deque, boost::forward_traversal_tag >(); + + test_type_erased_exercise_buffer_types< + std::vector, boost::forward_traversal_tag >(); + + test_type_erased_exercise_buffer_types< + std::list, boost::forward_traversal_tag >(); + + test_type_erased_exercise_buffer_types< + std::deque, boost::forward_traversal_tag >(); + + test_type_erased_exercise_buffer_types< + std::vector, boost::forward_traversal_tag >(); +} + + } // anonymous namespace +} // namespace boost_range_adaptor_type_erased_test + +boost::unit_test::test_suite* +init_unit_test_suite(int, char*[]) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE( "RangeTestSuite.adaptor.type_erased_forward" ); + + test->add(BOOST_TEST_CASE( + &boost_range_adaptor_type_erased_test::test_forward)); + + return test; +} + diff --git a/libs/range/test/adaptor_test/type_erased_mix_values.cpp b/libs/range/test/adaptor_test/type_erased_mix_values.cpp new file mode 100644 index 00000000..e91644ce --- /dev/null +++ b/libs/range/test/adaptor_test/type_erased_mix_values.cpp @@ -0,0 +1,94 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +#include +#include "type_erased_test.hpp" + +#include + +#include + +namespace boost_range_adaptor_type_erased_test +{ + namespace + { + +template< + class Traversal + , class ValueType + , class SourceValueType + , class SourceReference + , class TargetValueType + , class TargetReference +> +void mix_values_impl() +{ + typedef std::vector Container; + + typedef typename boost::any_range_type_generator< + Container + , SourceValueType + , Traversal + , SourceReference + >::type source_type; + + typedef typename boost::any_range_type_generator< + Container + , TargetValueType + , Traversal + , TargetReference + >::type target_type; + + Container test_data; + for (int i = 0; i < 10; ++i) + test_data.push_back(i); + + const source_type source_data(test_data); + target_type t1(source_data); + BOOST_CHECK_EQUAL_COLLECTIONS(source_data.begin(), source_data.end(), + t1.begin(), t1.end()); + + target_type t2; + t2 = source_data; + BOOST_CHECK_EQUAL_COLLECTIONS(source_data.begin(), source_data.end(), + t2.begin(), t2.end()); +} + +template +void mix_values_driver() +{ + mix_values_impl< + Traversal, + MockType, + MockType2, const MockType&, + MockType, const MockType& + >(); +} + +void mix_values() +{ + mix_values_driver(); + mix_values_driver(); + mix_values_driver(); + mix_values_driver(); +} + + } // anonymous namespace +} // namespace boost_range_adaptor_type_erased_test + +boost::unit_test::test_suite* +init_unit_test_suite(int, char*[]) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_mix_values"); + + test->add(BOOST_TEST_CASE( + &boost_range_adaptor_type_erased_test::mix_values)); + + return test; +} + diff --git a/libs/range/test/adaptor_test/type_erased_random_access.cpp b/libs/range/test/adaptor_test/type_erased_random_access.cpp new file mode 100644 index 00000000..39cf1c6e --- /dev/null +++ b/libs/range/test/adaptor_test/type_erased_random_access.cpp @@ -0,0 +1,50 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +#include +#include "type_erased_test.hpp" + +#include + +#include +#include + +namespace boost_range_adaptor_type_erased_test +{ + namespace + { + +void test_random_access() +{ + test_type_erased_exercise_buffer_types< + std::deque, boost::random_access_traversal_tag >(); + + test_type_erased_exercise_buffer_types< + std::vector, boost::random_access_traversal_tag >(); + + test_type_erased_exercise_buffer_types< + std::deque, boost::random_access_traversal_tag >(); + + test_type_erased_exercise_buffer_types< + std::vector, boost::random_access_traversal_tag >(); +} + + } // anonymous namespace +} // namespace boost_range_adaptor_type_erased_test + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_random_access"); + + test->add(BOOST_TEST_CASE( + &boost_range_adaptor_type_erased_test::test_random_access)); + + return test; +} + diff --git a/libs/range/test/adaptor_test/type_erased_single_pass.cpp b/libs/range/test/adaptor_test/type_erased_single_pass.cpp new file mode 100644 index 00000000..ad0c4ae1 --- /dev/null +++ b/libs/range/test/adaptor_test/type_erased_single_pass.cpp @@ -0,0 +1,57 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +#include +#include "type_erased_test.hpp" + +#include + +#include +#include +#include + +namespace boost_range_adaptor_type_erased_test +{ + namespace + { + +void test_single_pass() +{ + test_type_erased_exercise_buffer_types< + std::list, boost::single_pass_traversal_tag>(); + + test_type_erased_exercise_buffer_types< + std::deque, boost::single_pass_traversal_tag>(); + + test_type_erased_exercise_buffer_types< + std::vector, boost::single_pass_traversal_tag>(); + + test_type_erased_exercise_buffer_types< + std::list, boost::single_pass_traversal_tag>(); + + test_type_erased_exercise_buffer_types< + std::deque, boost::single_pass_traversal_tag>(); + + test_type_erased_exercise_buffer_types< + std::vector, boost::single_pass_traversal_tag>(); +} + + } // anonymous namespace +} // namespace boost_range_adaptor_type_erased_test + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_single_pass"); + + test->add(BOOST_TEST_CASE( + &boost_range_adaptor_type_erased_test::test_single_pass)); + + return test; +} + diff --git a/libs/range/test/adaptor_test/type_erased_test.hpp b/libs/range/test/adaptor_test/type_erased_test.hpp new file mode 100644 index 00000000..9a42e81d --- /dev/null +++ b/libs/range/test/adaptor_test/type_erased_test.hpp @@ -0,0 +1,289 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +#ifndef BOOST_RANGE_ADAPTOR_TEST_TYPE_ERASED_TEST_HPP +#define BOOST_RANGE_ADAPTOR_TEST_TYPE_ERASED_TEST_HPP + +#include +#include +#include +#include + +namespace boost_range_adaptor_type_erased_test +{ + +class MockType +{ +public: + MockType() + : m_x(0) + { + } + + MockType(boost::int32_t x) + : m_x(x) + { + } + + boost::int32_t get() const { return m_x; } + + inline bool operator==(const MockType& other) const + { + return m_x == other.m_x; + } + + inline bool operator!=(const MockType& other) const + { + return m_x != other.m_x; + } + +private: + boost::int32_t m_x; +}; + +class MockType2 : public MockType +{ +public: + MockType2() {} + MockType2(boost::int32_t x) : MockType(x) { } + MockType2(const MockType& other) : MockType(other) { } +}; + +inline std::ostream& operator<<(std::ostream& out, const MockType& obj) +{ + out << obj.get(); + return out; +} + +template +void test_type_erased_impl(Container& c) +{ + using namespace boost::adaptors; + typedef typename boost::range_value::type value_type; + typedef typename boost::adaptors::type_erased<> type_erased_t; + + + std::vector output; + + boost::push_back(output, boost::adaptors::type_erase(c, type_erased_t())); + + BOOST_CHECK_EQUAL_COLLECTIONS( output.begin(), output.end(), + c.begin(), c.end() ); + + output.clear(); + boost::push_back(output, c | type_erased_t()); + + BOOST_CHECK_EQUAL_COLLECTIONS( output.begin(), output.end(), + c.begin(), c.end() ); +} + +template +void test_const_and_mutable(Container& c) +{ + test_type_erased_impl(c); + + const Container& const_c = c; + test_type_erased_impl(const_c); +} + +template +void test_driver() +{ + using namespace boost::assign; + + typedef typename boost::range_value::type value_type; + + Container c; + test_const_and_mutable(c); + + c += value_type(1); + test_const_and_mutable(c); + + c += value_type(2); + test_const_and_mutable(c); +} + +template< + class Traversal + , class Container +> +void test_writeable(Container&, boost::single_pass_traversal_tag) +{} + +template< + class Traversal + , class Container +> +void test_writeable(Container& source, boost::forward_traversal_tag) +{ + using namespace boost::adaptors; + + typedef typename boost::range_value::type value_type; + typedef typename boost::range_difference::type difference_type; + typedef typename boost::range_reference::type mutable_reference_type; + typedef boost::any_range< + value_type + , Traversal + , mutable_reference_type + , difference_type + > mutable_any_range; + + mutable_any_range r = source | boost::adaptors::type_erased<>(); + std::vector output_test; + boost::fill(r, value_type(1)); + BOOST_CHECK_EQUAL( boost::distance(r), boost::distance(source) ); + std::vector reference_output(source.size(), value_type(1)); + BOOST_CHECK_EQUAL_COLLECTIONS( reference_output.begin(), reference_output.end(), + r.begin(), r.end() ); + +} + +template< + class Container + , class Traversal + , class Buffer +> +void test_type_erased_impl() +{ + using namespace boost::adaptors; + + typedef typename boost::range_value::type value_type; + + typedef typename boost::any_range_type_generator< + Container + , boost::use_default + , Traversal + , boost::use_default + , boost::use_default + , Buffer + >::type mutable_any_range; + + typedef typename boost::any_range_type_generator< + const Container + , boost::use_default + , Traversal + , boost::use_default + , boost::use_default + , Buffer + >::type const_any_range; + + typedef boost::adaptors::type_erased< + boost::use_default + , Traversal + , boost::use_default + , boost::use_default + , Buffer + > type_erased_t; + + Container source; + for (int i = 0; i < 10; ++i) + source.push_back(value_type(i)); + + mutable_any_range r(source); + BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(), + r.begin(), r.end() ); + + r = mutable_any_range(); + BOOST_CHECK_EQUAL( r.empty(), true ); + + r = source | type_erased_t(); + BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(), + r.begin(), r.end() ); + r = mutable_any_range(); + + r = boost::adaptors::type_erase(source, type_erased_t()); + BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(), + r.begin(), r.end() ); + r = mutable_any_range(); + + test_writeable(source, Traversal()); + + // convert and construct a const any_range from a mutable source + // range + const_any_range cr(source); + BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(), + cr.begin(), cr.end() ); + // assign an empty range and ensure that this correctly results + // in an empty range. This is important for the validity of + // the rest of the tests. + cr = const_any_range(); + BOOST_CHECK_EQUAL( cr.empty(), true ); + + // Test the pipe type_erased adaptor from a constant source + // range to a constant any_range + const Container& const_source = source; + cr = const_any_range(); + cr = const_source | type_erased_t(); + BOOST_CHECK_EQUAL_COLLECTIONS( const_source.begin(), const_source.end(), + cr.begin(), cr.end() ); + + // Test the pipe type erased adaptor from a mutable source + // range to a constant any_range + cr = const_any_range(); + cr = source | type_erased_t(); + BOOST_CHECK_EQUAL_COLLECTIONS( source.begin(), source.end(), + cr.begin(), cr.end() ); + + // Use the function form of the type_erase adaptor from a constant + // source range + cr = const_any_range(); + cr = boost::adaptors::type_erase(const_source, type_erased_t()); + BOOST_CHECK_EQUAL_COLLECTIONS( const_source.begin(), const_source.end(), + cr.begin(), cr.end() ); + + // Assignment from mutable to const... + cr = const_any_range(); + cr = r; + BOOST_CHECK_EQUAL_COLLECTIONS( cr.begin(), cr.end(), + r.begin(), r.end() ); + + // Converting copy from mutable to const... + cr = const_any_range(); + cr = const_any_range(r); + BOOST_CHECK_EQUAL_COLLECTIONS( cr.begin(), cr.end(), + r.begin(), r.end() ); +} + +template< + class Container + , class Traversal + , class Buffer +> +class test_type_erased_impl_fn +{ +public: + typedef void result_type; + void operator()() + { + test_type_erased_impl< Container, Traversal, Buffer >(); + } +}; + +template< + class Container + , class Traversal +> +void test_type_erased_exercise_buffer_types() +{ + using boost::any_iterator_default_buffer; + using boost::any_iterator_buffer; + using boost::any_iterator_heap_only_buffer; + using boost::any_iterator_stack_only_buffer; + + test_type_erased_impl_fn< Container, Traversal, any_iterator_default_buffer >()(); + test_type_erased_impl_fn< Container, Traversal, any_iterator_heap_only_buffer >()(); + test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<1> >()(); + test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<2> >()(); + test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<32> >()(); + test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<64> >()(); + test_type_erased_impl_fn< Container, Traversal, any_iterator_buffer<128> >()(); + test_type_erased_impl_fn< Container, Traversal, any_iterator_stack_only_buffer<128> >()(); +} + +} // namespace boost_range_adaptor_type_erased_test + +#endif // include guard diff --git a/libs/range/test/adaptor_test/type_erased_tparam_conv.cpp b/libs/range/test/adaptor_test/type_erased_tparam_conv.cpp new file mode 100644 index 00000000..e235ab30 --- /dev/null +++ b/libs/range/test/adaptor_test/type_erased_tparam_conv.cpp @@ -0,0 +1,74 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +#include +#include "type_erased_test.hpp" + +#include + +#include +#include + +namespace boost_range_adaptor_type_erased_test +{ + namespace + { + +void template_parameter_conversion() +{ + typedef boost::any_range< + int + , boost::random_access_traversal_tag + , int& + , std::ptrdiff_t + > source_range_type; + + typedef boost::any_range< + int + , boost::single_pass_traversal_tag + , const int& + , std::ptrdiff_t + > target_range_type; + + source_range_type source; + + // Converting via construction + target_range_type t1(source); + + // Converting via assignment + target_range_type t2; + t2 = source; + + // Converting via construction to a type with a reference type + // that is a value + typedef boost::any_range< + int + , boost::single_pass_traversal_tag + , int + , std::ptrdiff_t + > target_range2_type; + + target_range2_type t3(source); + target_range2_type t4; + t4 = source; +} + + } // anonymous namespace +} // namespace boost_range_adaptor_type_erased_test + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_tparam_conv"); + + test->add(BOOST_TEST_CASE( + &boost_range_adaptor_type_erased_test::template_parameter_conversion)); + + return test; +} + diff --git a/libs/range/test/adaptor_test/type_erased_transformed.cpp b/libs/range/test/adaptor_test/type_erased_transformed.cpp new file mode 100644 index 00000000..1b382615 --- /dev/null +++ b/libs/range/test/adaptor_test/type_erased_transformed.cpp @@ -0,0 +1,67 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +#include +#include +#include +#include "type_erased_test.hpp" + +#include + +#include + +namespace boost_range_adaptor_type_erased_test +{ + namespace + { + +typedef boost::any_range< + int, + boost::random_access_traversal_tag, + int, + std::ptrdiff_t +> any_integer_value_range; + +struct get_fn +{ + typedef boost::int32_t result_type; + boost::int32_t operator()(const MockType& val) const + { + return val.get(); + } +}; + +int accumulate_any_integer_value_range(any_integer_value_range rng) +{ + return boost::accumulate(rng, 0); +} + +void test_type_erased_transformed() +{ + std::vector v(5, MockType(3)); + + const int sum = accumulate_any_integer_value_range( + v | boost::adaptors::transformed(get_fn())); + + BOOST_CHECK_EQUAL(15, sum); +} + + } // anonymous namespace +} // namespace boost_range_adaptor_type_erased_test + +boost::unit_test::test_suite* +init_unit_test_suite(int, char*[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE("RangeTestSuite.adaptor.type_erased_transformed"); + + test->add( + BOOST_TEST_CASE( + &boost_range_adaptor_type_erased_test::test_type_erased_transformed)); + + return test; +} diff --git a/libs/range/test/adaptor_test/uniqued.cpp b/libs/range/test/adaptor_test/uniqued.cpp new file mode 100644 index 00000000..fdf5454a --- /dev/null +++ b/libs/range/test/adaptor_test/uniqued.cpp @@ -0,0 +1,168 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void uniqued_test_impl( Container& c ) + { + using namespace boost::adaptors; + + std::vector< int > test_result1; + boost::push_back(test_result1, c | uniqued); + + std::vector< int > test_result2; + boost::push_back(test_result2, adaptors::unique(c)); + + std::vector< int > reference(c.begin(), c.end()); + reference.erase( + std::unique(reference.begin(), reference.end()), + reference.end()); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test_result1.begin(), test_result1.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test_result2.begin(), test_result2.end() ); + } + + template< class Container > + void uniqued_test_impl() + { + using namespace boost::assign; + + Container c; + + // Test empty + uniqued_test_impl(c); + + // Test one + c += 1; + uniqued_test_impl(c); + + // Test many + c += 1,1,1,2,2,2,2,2,3,3,3,3,4,5,6,6,6,7,7,7,8,8,9,9,9,9,9,10; + uniqued_test_impl(c); + } + + void uniqued_test() + { + uniqued_test_impl< std::vector< int > >(); + uniqued_test_impl< std::list< int > >(); + uniqued_test_impl< std::set< int > >(); + uniqued_test_impl< std::multiset< int > >(); + } + +class istring +{ +public: + istring() + : m_value("") + { + } + + explicit istring(const char* value) + : m_value(value) + { + } + + bool operator==(istring r) const + { + return boost::iequals(m_value, r.m_value); + } + + bool operator!=(istring r) const + { + return !operator==(r); + } + + inline friend std::ostream& operator<<(std::ostream& out, istring o) + { + return out << o.m_value; + } + + const char* get() const { return m_value; } + +private: + const char* m_value; +}; + +struct istring_to_string +{ + typedef std::string result_type; + + std::string operator()(istring s) const + { + return s.get(); + } +}; + +// This is based on a test-case provided by Eric Neibler. +void uniqued_return_first() +{ + using namespace boost::adaptors; + + std::vector strs; + strs.push_back(istring("hello")); + strs.push_back(istring("hElLo")); + strs.push_back(istring("HELLO")); + strs.push_back(istring("ZZZZ")); + + std::vector output1; + + boost::unique_copy(strs, std::back_inserter(output1)); + + std::vector output2; + boost::push_back(output2, strs | uniqued); + + std::vector test1; + boost::push_back(test1, output1 | transformed(istring_to_string())); + + std::vector test2; + boost::push_back(test2, output2 | transformed(istring_to_string())); + + BOOST_CHECK_EQUAL_COLLECTIONS(test1.begin(), test1.end(), + test2.begin(), test2.end()); +} + + } // anonymous namespace +} // namespace boost + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.uniqued" ); + + test->add( BOOST_TEST_CASE( &boost::uniqued_test ) ); + + test->add(BOOST_TEST_CASE(&boost::uniqued_return_first)); + + return test; +} diff --git a/libs/range/test/adaptor_test/uniqued_example.cpp b/libs/range/test/adaptor_test/uniqued_example.cpp new file mode 100644 index 00000000..cf1407a7 --- /dev/null +++ b/libs/range/test/adaptor_test/uniqued_example.cpp @@ -0,0 +1,64 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +//[uniqued_example +#include +#include +#include +#include +#include +#include + +//<- +#include + +#include +#include + +namespace +{ +void uniqued_example_test() +//-> +//=int main(int argc, const char* argv[]) +{ + using namespace boost::assign; + using namespace boost::adaptors; + + std::vector input; + input += 1,1,2,2,2,3,4,5,6; + + boost::copy( + input | uniqued, + std::ostream_iterator(std::cout, ",")); + +//= return 0; +//=} +//] + std::vector reference; + reference += 1,2,3,4,5,6; + + std::vector test; + boost::push_back( test, input | uniqued ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); +} +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.uniqued_example" ); + + test->add( BOOST_TEST_CASE( &uniqued_example_test ) ); + + return test; +} diff --git a/libs/range/test/adaptors.cpp b/libs/range/test/adaptors.cpp new file mode 100644 index 00000000..ea0f5036 --- /dev/null +++ b/libs/range/test/adaptors.cpp @@ -0,0 +1,236 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template< class T > +struct less_than +{ + T val; + + less_than() : val(0) + {} + + less_than( T t ) : val(t) + {} + + bool operator()( const T& r ) const + { + return r < val; + } +}; + + + +template< class T > +struct multiply +{ + T val; + + typedef T& result_type; + + multiply( T t ) : val(t) + { } + + T& operator()( T& r ) const + { + return r *= 2; + } +}; + + + +template< class Rng > +void check_copy( Rng r ) +{ + // + // Make sure the generated iterators + // can actually be copied + // + Rng r2 = r; + r2 = r; +} + + +template< class Rng > +void check_direct() +{ + using namespace boost::adaptors; + + Rng rng = boost::assign::list_of(1)(2)(3)(4)(5).to_container( rng ); + Rng out; + + // + // test each alphabetically + // + BOOST_FOREACH( int i, rng | filtered( less_than(4) ) + /*| reversed*/ + | transformed( multiply(2) ) ) + { + out.push_back( i ); + } + + BOOST_CHECK_EQUAL( out.size(), 3u ); + BOOST_CHECK_EQUAL( *out.begin(), 2 ); + BOOST_CHECK_EQUAL( *boost::next(out.begin()), 4 ); + BOOST_CHECK_EQUAL( *boost::next(out.begin(),2), 6 ); + + rng = boost::assign::list_of(1)(1)(2)(2)(3)(3)(4)(5).to_container( rng ); + out.clear(); + /* + BOOST_FOREACH( int i, rng | adjacent_filtered( std::equal_to() ) + | uniqued ) + { + + out.push_back( i ); + }*/ + +} + + +template< class IndirectRng > +void check_indirect() +{ + using namespace boost::adaptors; + + IndirectRng rng; + + std::vector< boost::shared_ptr< int > > holder; + + for( unsigned i = 0u; i != 20u; ++i ) + { + boost::shared_ptr v(new int(i)); + rng.push_back( v.get() ); + } + + BOOST_FOREACH( int& i, rng | indirected | reversed + | transformed( multiply(2) ) ) + { + i += 1; + } + + + +} + + + +template< class RandomAccessRng > +void check_random_access() +{ + using namespace boost::adaptors; + + RandomAccessRng rng(1, 20u); + RandomAccessRng out; + + BOOST_FOREACH( int i, rng | reversed + | transformed( multiply(2) ) + /* | sliced(0,15) */ ) + { + out.push_back( i ); + } + + + BOOST_FOREACH( int i, rng | copied(3u,13u) ) + { + out.push_back( i ); + } +} + + + +template< class Map > +void check_map() +{ + using namespace boost::adaptors; + + Map m; + m.insert( std::make_pair(1,2) ); + m.insert( std::make_pair(2,2) ); + m.insert( std::make_pair(3,2) ); + m.insert( std::make_pair(4,2) ); + m.insert( std::make_pair(5,2) ); + m.insert( std::make_pair(6,2) ); + m.insert( std::make_pair(7,2) ); + + std::vector keys + = boost::copy_range< std::vector >( m | map_keys ); + std::vector values + = boost::copy_range< std::vector >( m | map_values ); +} + + + +void check_regex() +{ + using namespace boost::adaptors; + std::string s("This is a string of tokens"); + std::vector tokens = + boost::copy_range< std::vector >( s | tokenized( "\\s+", -1 ) ); +} + + +void check_adaptors() +{ + check_direct< std::vector >(); + check_direct< std::list >(); + check_indirect< std::vector >(); + check_indirect< std::list >(); + + check_map< std::map >(); +// check_random_access< std::vector >(); + check_regex(); + + using namespace boost::adaptors; + std::vector vec(10u,20); + std::vector pvec; + std::map map; + + check_copy( vec | adjacent_filtered( std::equal_to() ) ); + // check_copy( vec | indexed ); + check_copy( vec | reversed ); + check_copy( vec | uniqued ); + check_copy( pvec | indirected ); + +// check_copy( vec | sliced(1,5) ); + // + // This does not return an iterator_range<>, so + // won't pass this test of implicit conversion + // check_copy( vec | copied(1,5) ); + // + check_copy( map | map_values ); + check_copy( map | map_keys ); + check_copy( std::string( "a string" ) | tokenized( "\\s+", -1 ) ); + check_copy( vec | filtered( less_than(2) ) ); + check_copy( vec | transformed( multiply(2) ) ); +} + +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + using namespace boost; + + test_suite* test = BOOST_TEST_SUITE( "Range Test Suite - Adaptors" ); + + test->add( BOOST_TEST_CASE( &check_adaptors ) ); + + return test; +} + + diff --git a/libs/range/test/adl_conformance.cpp b/libs/range/test/adl_conformance.cpp new file mode 100644 index 00000000..0d73b6ab --- /dev/null +++ b/libs/range/test/adl_conformance.cpp @@ -0,0 +1,188 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include + +enum adl_types +{ + unused, + boost_namespace, + templated_namespace, + non_templated_namespace, + global_namespace +}; + +// Use boost_test rather than boost as the namespace for this test +// to allow the test framework to use boost::begin() etc. without +// violating the One Defintion Rule. +namespace boost_test +{ + namespace range_detail + { + template< class Range > + inline typename Range::iterator begin( Range& r ) + { + return boost_namespace; + } + + template< class Range > + inline typename Range::iterator begin( const Range& r ) + { + return boost_namespace; + } + + } + + template< class Range > + inline typename Range::iterator begin( Range& r ) + { + using range_detail::begin; // create ADL hook + return begin( r ); + } + + template< class Range > + inline typename Range::iterator begin( const Range& r ) + { + using range_detail::begin; // create ADL hook + return begin( r ); + } +} // 'boost_test' + + +namespace find_templated +{ + template< class T > + struct range + { + typedef adl_types iterator; + + range() { /* allow const objects */ } + iterator begin() { return unused; } + iterator begin() const { return unused; } + iterator end() { return unused; } + iterator end() const { return unused; } + }; + + // + // A fully generic version here will create + // ambiguity. + // + template< class T > + inline typename range::iterator begin( range& r ) + { + return templated_namespace; + } + + template< class T > + inline typename range::iterator begin( const range& r ) + { + return templated_namespace; + } + +} + +namespace find_non_templated +{ + struct range + { + typedef adl_types iterator; + + range() { /* allow const objects */ } + iterator begin() { return unused; } + iterator begin() const { return unused; } + iterator end() { return unused; } + iterator end() const { return unused; } + }; + + inline range::iterator begin( range& r ) + { + return non_templated_namespace; + } + + + inline range::iterator begin( const range& r ) + { + return non_templated_namespace; + } +} + +struct range +{ + typedef adl_types iterator; + + range() { /* allow const objects */ } + iterator begin() { return unused; } + iterator begin() const { return unused; } + iterator end() { return unused; } + iterator end() const { return unused; } +}; + +inline range::iterator begin( range& r ) +{ + return global_namespace; +} + +inline range::iterator begin( const range& r ) +{ + return global_namespace; +} + +void check_adl_conformance() +{ + find_templated::range r; + const find_templated::range r2; + find_non_templated::range r3; + const find_non_templated::range r4; + range r5; + const range r6; + + // + // Notice how ADL kicks in even when we have qualified + // notation! + // + + + BOOST_CHECK( boost_test::begin( r ) != boost_namespace ); + BOOST_CHECK( boost_test::begin( r2 ) != boost_namespace ); + BOOST_CHECK( boost_test::begin( r3 ) != boost_namespace ); + BOOST_CHECK( boost_test::begin( r4 ) != boost_namespace ); + BOOST_CHECK( boost_test::begin( r5 ) != boost_namespace ); + BOOST_CHECK( boost_test::begin( r6 ) != boost_namespace ); + + BOOST_CHECK_EQUAL( boost_test::begin( r ), templated_namespace ) ; + BOOST_CHECK_EQUAL( boost_test::begin( r2 ), templated_namespace ); + BOOST_CHECK_EQUAL( boost_test::begin( r3 ), non_templated_namespace ); + BOOST_CHECK_EQUAL( boost_test::begin( r4 ), non_templated_namespace ); + BOOST_CHECK_EQUAL( boost_test::begin( r5 ), global_namespace ); + BOOST_CHECK_EQUAL( boost_test::begin( r6 ), global_namespace ); +} + +#include + +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &check_adl_conformance ) ); + + return test; +} + + diff --git a/libs/range/test/adl_conformance_no_using.cpp b/libs/range/test/adl_conformance_no_using.cpp new file mode 100644 index 00000000..82c1cd2e --- /dev/null +++ b/libs/range/test/adl_conformance_no_using.cpp @@ -0,0 +1,110 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include + +namespace A +{ + namespace detail + { + template< typename T > + int f( const T& x ) + { + // Default: + std::cout << 1 << std::endl; + return 1; + } + + template< typename T > + int adl_f2( const T& x, int* ) + { + return f( x ); + } + + template< typename T > + int adl_f( const T& x ) + { + return adl_f2( x, 0 ); + } + } + + template< typename T > + int f( const T& x ) + { + return detail::adl_f( x ); + } + + template< typename T > + int adl_f2( const T& x, int ) + { + return detail::f( x ); + } + + //-------------------------------- + + class C {}; +/* + // Optional: + int f( const C& x ) + { + std::cout << 2 << std::endl; + } +*/ + template< typename T > + class D {}; +/* + // Optional: + template< typename T > + int f( const D< T >& x ) + { + std::cout << 3 << std::endl; + } + */ +} + + +namespace B +{ + class C {}; + + // Optional: +/* int f( const C& ) + { + std::cout << 4 << std::endl; + } +*/ + template< typename T > + class D {}; +/* + // Optional: + template< typename T > + int f( const D< T >& x ) + { + std::cout << 5 << std::endl; + } + */ +} + +int main() +{ + A::f( 42 ); + + A::C ac; + A::f( ac ); + + A::D< int > ad; + A::f( ad ); + + B::C bc; + A::f( bc ); + + B::D< int > bd; + A::f( bd ); +} diff --git a/libs/range/test/algorithm.cpp b/libs/range/test/algorithm.cpp new file mode 100644 index 00000000..024e4043 --- /dev/null +++ b/libs/range/test/algorithm.cpp @@ -0,0 +1,478 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +// (C) Copyright Eric Niebler 2004. +// Use, modification and distribution are subject to 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) + +/* + Revision history: + 13 December 2004 : Initial version. +*/ + +#ifdef _MSC_VER +// The 'secure' library warnings produce so much noise that it makes it +// impossible to see more useful warnings. + #define _SCL_SECURE_NO_WARNINGS +#endif + +#ifdef _MSC_VER + // counting_iterator generates a warning about truncating an integer + #pragma warning(push) + #pragma warning(disable : 4244) +#endif +#include +#ifdef _MSC_VER + template ::boost::counting_iterator; + #pragma warning(pop) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +/////////////////////////////////////////////////////////////////////////////// +// dummy function object, used with algorithms +// +struct null_fun +{ + template + void operator()(T const &t) const + { + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// dummy predicate, used with algorithms +// +struct null_pred +{ + template + bool operator()(T const &t) const + { + return t == T(); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// dummy unary op, used with algorithms +// +struct null_op1 +{ + template + T const & operator()(T const & t) const + { + return t; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// dummy binary op, used with algorithms +// +struct null_op2 +{ + template + T const & operator()(T const & t, U const & u) const + { + return t; + } +}; + +template +void test_random_algorithms(Rng & rng, std::random_access_iterator_tag) +{ + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iterator; + + typedef BOOST_DEDUCED_TYPENAME boost::range_value::type value_type; + + typedef BOOST_DEDUCED_TYPENAME boost::range_size::type + size_type BOOST_RANGE_UNUSED; + + typedef BOOST_DEDUCED_TYPENAME boost::iterator_category::type + iterator_category BOOST_RANGE_UNUSED; + + // just make sure these compile (for now) + if(0) + { + boost::random_shuffle(rng); + + // Must be a value since random_shuffle must take the generator by + // reference to match the standard. + null_op1 rng_generator; + boost::random_shuffle(rng, rng_generator); + + boost::sort(rng); + boost::sort(rng, std::less()); + + boost::stable_sort(rng); + boost::stable_sort(rng, std::less()); + + boost::partial_sort(rng, boost::begin(rng)); + boost::partial_sort(rng, boost::begin(rng), std::less()); + + boost::nth_element(rng, boost::begin(rng)); + boost::nth_element(rng, boost::begin(rng), std::less()); + + boost::push_heap(rng); + boost::push_heap(rng, std::less()); + + boost::pop_heap(rng); + boost::pop_heap(rng, std::less()); + + boost::make_heap(rng); + boost::make_heap(rng, std::less()); + + boost::sort_heap(rng); + boost::sort_heap(rng, std::less()); + } +} + +template +void test_random_algorithms(Rng & rng, std::input_iterator_tag) +{ + // no-op +} + +template +void test_algorithms(Rng & rng) +{ + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iterator; + typedef BOOST_DEDUCED_TYPENAME boost::range_value::type value_type; + typedef BOOST_DEDUCED_TYPENAME boost::range_size::type size_type; + typedef BOOST_DEDUCED_TYPENAME boost::iterator_category::type iterator_category; + + // just make sure these compile (for now) + if(0) + { + value_type val = value_type(); + + value_type rng2[] = {value_type(),value_type(),value_type()}; + typedef value_type* iterator2; + + value_type out[100] = {}; + typedef value_type* out_iterator; + + null_fun f = null_fun(); + iterator i = iterator(); + bool b = bool(); + out_iterator o = out_iterator(); + size_type s = size_type(); + + f = boost::for_each(rng, null_fun()); + + i = boost::find(rng, val); + i = boost::find_if(rng, null_pred()); + + i = boost::find_end(rng, rng2); + i = boost::find_end(rng, rng2, std::equal_to()); + + i = boost::find_first_of(rng, rng2); + i = boost::find_first_of(rng, rng2, std::equal_to()); + + i = boost::adjacent_find(rng); + i = boost::adjacent_find(rng, std::equal_to()); + + s = boost::count(rng, val); + s = boost::count_if(rng, null_pred()); + + std::pair p1; + p1 = boost::mismatch(rng, rng2); + p1 = boost::mismatch(rng, rng2, std::equal_to()); + + b = boost::equal(rng, rng2); + b = boost::equal(rng, rng2, std::equal_to()); + + i = boost::search(rng, rng2); + i = boost::search(rng, rng2, std::equal_to()); + + o = boost::copy(rng, boost::begin(out)); + o = boost::copy_backward(rng, boost::end(out)); + + o = boost::transform(rng, boost::begin(out), null_op1()); + o = boost::transform(rng, rng2, boost::begin(out), null_op2()); + + boost::replace(rng, val, val); + boost::replace_if(rng, null_pred(), val); + +/* + o = boost::replace_copy(rng, boost::begin(out), val, val); + o = boost::replace_copy_if(rng, boost::begin(out), null_pred(), val); +*/ + + boost::fill(rng, val); + // + // size requires RandomAccess + // + //boost::fill_n(rng, boost::size(rng), val); + //boost::fill_n(rng, std::distance(boost::begin(rng),boost::end(rng)),val); + + boost::generate(rng, &std::rand); + // + // size requires RandomAccess + // + //boost::generate_n(rng, boost::size(rng), &std::rand); + //boost::generate_n(rng,std::distance(boost::begin(rng),boost::end(rng)), &std::rand); + + i = boost::remove(rng, val); + i = boost::remove_if(rng, null_pred()); + +/* + o = boost::remove_copy(rng, boost::begin(out), val); + o = boost::remove_copy_if(rng, boost::begin(out), null_pred()); +*/ + + typename boost::range_return::type rrng = boost::unique(rng); + rrng = boost::unique(rng, std::equal_to()); + +/* + o = boost::unique_copy(rng, boost::begin(out)); + o = boost::unique_copy(rng, boost::begin(out), std::equal_to()); +*/ + + boost::reverse(rng); + +/* + o = boost::reverse_copy(rng, boost::begin(out)); +*/ + + boost::rotate(rng, boost::begin(rng)); + +/* + o = boost::rotate_copy(rng, boost::begin(rng), boost::begin(out)); +*/ + + i = boost::partition(rng, null_pred()); + i = boost::stable_partition(rng, null_pred()); + +/* + o = boost::partial_sort_copy(rng, out); + o = boost::partial_sort_copy(rng, out, std::less()); +*/ + + i = boost::lower_bound(rng, val); + i = boost::lower_bound(rng, val, std::less()); + + i = boost::upper_bound(rng, val); + i = boost::upper_bound(rng, val, std::less()); + + std::pair p2; + p2 = boost::equal_range(rng, val); + p2 = boost::equal_range(rng, val, std::less()); + + b = boost::binary_search(rng, val); + b = boost::binary_search(rng, val, std::less()); + + boost::inplace_merge(rng, boost::begin(rng)); + boost::inplace_merge(rng, boost::begin(rng), std::less()); + + b = boost::includes(rng, rng2); + b = boost::includes(rng, rng2, std::equal_to()); + + o = boost::set_union(rng, rng2, boost::begin(out)); + o = boost::set_union(rng, rng2, boost::begin(out), std::equal_to()); + + o = boost::set_intersection(rng, rng2, boost::begin(out)); + o = boost::set_intersection(rng, rng2, boost::begin(out), std::equal_to()); + + o = boost::set_difference(rng, rng2, boost::begin(out)); + o = boost::set_difference(rng, rng2, boost::begin(out), std::equal_to()); + + o = boost::set_symmetric_difference(rng, rng2, boost::begin(out)); + o = boost::set_symmetric_difference(rng, rng2, boost::begin(out), std::equal_to()); + + i = boost::min_element(rng); + i = boost::min_element(rng, std::less()); + + i = boost::max_element(rng); + i = boost::max_element(rng, std::less()); + + b = boost::lexicographical_compare(rng, rng); + b = boost::lexicographical_compare(rng, rng, std::equal_to()); + + b = boost::next_permutation(rng); + b = boost::next_permutation(rng, std::less()); + + b = boost::prev_permutation(rng); + b = boost::prev_permutation(rng, std::less()); + + ///////////////////////////////////////////////////////////////////// + // numeric algorithms + ///////////////////////////////////////////////////////////////////// + + val = boost::accumulate( rng, val ); + val = boost::accumulate( rng, val, null_op2() ); + val = boost::inner_product( rng, rng, val ); + val = boost::inner_product( rng, rng, val, + null_op2(), null_op2() ); + o = boost::partial_sum( rng, boost::begin(out) ); + o = boost::partial_sum( rng, boost::begin(out), null_op2() ); + o = boost::adjacent_difference( rng, boost::begin(out) ); + o = boost::adjacent_difference( rng, boost::begin(out), + null_op2() ); + + boost::ignore_unused_variable_warning(b); + + } + + // test the algorithms that require a random-access range + test_random_algorithms(rng, iterator_category()); +} + +int* addr(int &i) { return &i; } +bool true_(int) { return true; } + +/////////////////////////////////////////////////////////////////////////////// +// test_main +// +void simple_compile_test() +{ + // int_iterator + typedef ::boost::counting_iterator int_iterator; + + // define come containers + std::list my_list(int_iterator(1),int_iterator(6)); + + + std::vector my_vector(int_iterator(1),int_iterator(6)); + + std::pair::iterator,std::vector::iterator> my_pair(my_vector.begin(),my_vector.end()); + + // test the algorithms with list and const list + test_algorithms(my_list); + test_algorithms(my_vector); + test_algorithms(my_pair); + + + std::vector v; + std::vector& cv = v; + + using namespace boost; + +#define BOOST_RANGE_RETURNS_TEST( function_name, cont ) \ + function_name (cont); \ + function_name (cont); \ + function_name (cont); \ + function_name (cont); \ + function_name (cont); \ + function_name (cont); \ + function_name (cont); \ + function_name (cont); \ + function_name (cont); \ + function_name (cont); + + BOOST_RANGE_RETURNS_TEST( adjacent_find, cv ); + BOOST_RANGE_RETURNS_TEST( adjacent_find, v ); + BOOST_RANGE_RETURNS_TEST( max_element, cv ); + BOOST_RANGE_RETURNS_TEST( max_element, v ); + BOOST_RANGE_RETURNS_TEST( min_element, cv ); + BOOST_RANGE_RETURNS_TEST( min_element, v ); + BOOST_RANGE_RETURNS_TEST( unique, v ); +#undef BOOST_RANGE_RETURNS_TEST + +#define BOOST_RANGE_RETURNS_TEST1( function_name, cont, arg1 ) \ + function_name (cont, arg1); \ + function_name (cont, arg1); \ + function_name (cont, arg1); \ + function_name (cont, arg1); \ + function_name (cont, arg1); \ + function_name (cont, arg1); \ + function_name (cont, arg1); \ + function_name (cont, arg1); \ + function_name (cont, arg1); \ + function_name (cont, arg1); + + BOOST_RANGE_RETURNS_TEST1( adjacent_find, cv, std::less() ); + BOOST_RANGE_RETURNS_TEST1( adjacent_find, v, std::less() ); + BOOST_RANGE_RETURNS_TEST1( find, cv, 0 ); + BOOST_RANGE_RETURNS_TEST1( find, v, 0 ); + BOOST_RANGE_RETURNS_TEST1( find_end, cv, cv ); + BOOST_RANGE_RETURNS_TEST1( find_end, cv, v ); + BOOST_RANGE_RETURNS_TEST1( find_end, v, cv ); + BOOST_RANGE_RETURNS_TEST1( find_end, v, v ); + BOOST_RANGE_RETURNS_TEST1( find_first_of, cv, cv ); + BOOST_RANGE_RETURNS_TEST1( find_first_of, cv, v ); + BOOST_RANGE_RETURNS_TEST1( find_first_of, v, cv ); + BOOST_RANGE_RETURNS_TEST1( find_first_of, v, v ); + BOOST_RANGE_RETURNS_TEST1( find_if, cv, std::negate() ); + BOOST_RANGE_RETURNS_TEST1( find_if, v, std::negate() ); + BOOST_RANGE_RETURNS_TEST1( search, cv, cv ); + BOOST_RANGE_RETURNS_TEST1( search, cv, v ); + BOOST_RANGE_RETURNS_TEST1( search, v, cv ); + BOOST_RANGE_RETURNS_TEST1( search, v, v ); + + BOOST_RANGE_RETURNS_TEST1( remove, v, 0 ); + BOOST_RANGE_RETURNS_TEST1( remove_if, v, std::negate() ); + + BOOST_RANGE_RETURNS_TEST1( lower_bound, cv, 0 ); + BOOST_RANGE_RETURNS_TEST1( lower_bound, v, 0 ); + BOOST_RANGE_RETURNS_TEST1( max_element, cv, std::less() ); + BOOST_RANGE_RETURNS_TEST1( max_element, v, std::less() ); + BOOST_RANGE_RETURNS_TEST1( min_element, cv, std::less() ); + BOOST_RANGE_RETURNS_TEST1( min_element, v, std::less() ); + BOOST_RANGE_RETURNS_TEST1( upper_bound, cv, 0 ); + BOOST_RANGE_RETURNS_TEST1( upper_bound, v, 0 ); + BOOST_RANGE_RETURNS_TEST1( partition, cv, std::negate() ); + BOOST_RANGE_RETURNS_TEST1( partition, v, std::negate() ); + BOOST_RANGE_RETURNS_TEST1( stable_partition, cv, std::negate() ); + BOOST_RANGE_RETURNS_TEST1( stable_partition, v, std::negate() ); + +#undef BOOST_RANGE_RETURNS_TEST1 + +#define BOOST_RANGE_RETURNS_TEST2( function_name, arg1, arg2 ) \ + function_name (v, arg1, arg2); \ + function_name (v, arg1, arg2); \ + function_name (v, arg1, arg2); \ + function_name (v, arg1, arg2); \ + function_name (v, arg1, arg2); \ + function_name (v, arg1, arg2); \ + function_name (v, arg1, arg2); \ + function_name (v, arg1, arg2); \ + function_name (v, arg1, arg2); \ + function_name (v, arg1, arg2); + + BOOST_RANGE_RETURNS_TEST2( find_end, v, std::less() ); + BOOST_RANGE_RETURNS_TEST2( find_first_of, v, std::less() ); + BOOST_RANGE_RETURNS_TEST2( boost::search, v, std::less() ); + BOOST_RANGE_RETURNS_TEST2( lower_bound, 0, std::less() ); + BOOST_RANGE_RETURNS_TEST2( upper_bound, 0, std::less() ); + +#undef BOOST_RANGE_RETURNS_TEST2 +} + +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + using namespace boost; + + test_suite* test = BOOST_TEST_SUITE( "Range Test Suite - Algorithm" ); + + test->add( BOOST_TEST_CASE( &simple_compile_test ) ); + + return test; +} + diff --git a/libs/range/test/algorithm_example.cpp b/libs/range/test/algorithm_example.cpp new file mode 100644 index 00000000..bae29017 --- /dev/null +++ b/libs/range/test/algorithm_example.cpp @@ -0,0 +1,92 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + // + // example: extracting bounds in a generic algorithm + // + template< typename Range, typename T > + inline typename boost::range_iterator::type + find( Range& c, const T& value ) + { + return std::find( boost::begin( c ), boost::end( c ), value ); + } + + template< typename Range, typename T > + inline typename boost::range_iterator::type + find( const Range& c, const T& value ) + { + return std::find( boost::begin( c ), boost::end( c ), value ); + } + + // + // replace first value and return its index + // + template< class Range, class T > + inline typename boost::range_difference::type + my_generic_replace( Range& c, const T& value, const T& replacement ) + { + typename boost::range_iterator::type found = find( c, value ); + + if( found != boost::end( c ) ) + *found = replacement; + return std::distance( boost::begin( c ), found ); + } +} + + +void check_algorithm() +{ + // + // usage + // + const int N = 5; + std::vector my_vector; + int values[] = { 1,2,3,4,5,6,7,8,9 }; + my_vector.assign( values, values + 9 ); + typedef std::vector::iterator iterator; + std::pair my_view( boost::begin( my_vector ), + boost::begin( my_vector ) + N ); + BOOST_CHECK_EQUAL( my_generic_replace( my_vector, 4, 2 ), 3 ); + BOOST_CHECK_EQUAL( my_generic_replace( my_view, 4, 2 ), N ); + +} + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &check_algorithm ) ); + + return test; +} + + + diff --git a/libs/range/test/algorithm_ext_test/copy_n.cpp b/libs/range/test/algorithm_ext_test/copy_n.cpp new file mode 100644 index 00000000..854962fe --- /dev/null +++ b/libs/range/test/algorithm_ext_test/copy_n.cpp @@ -0,0 +1,60 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include + +namespace +{ + template< class Container > + void test_copy_n_impl() + { + std::vector source; + for (std::size_t i = 0; i < 10; ++i) + source.push_back(i); + + for (std::size_t k = 0; k < 10; ++k) + { + std::vector reference; + for (std::size_t j = 0; j < k; ++j) + reference.push_back(j); + + Container test; + boost::copy_n(source, k, std::back_inserter(test)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + } + + void test_copy_n() + { + test_copy_n_impl< std::vector >(); + test_copy_n_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.copy_n" ); + + test->add( BOOST_TEST_CASE( &test_copy_n ) ); + + return test; +} diff --git a/libs/range/test/algorithm_ext_test/erase.cpp b/libs/range/test/algorithm_ext_test/erase.cpp new file mode 100644 index 00000000..73de0433 --- /dev/null +++ b/libs/range/test/algorithm_ext_test/erase.cpp @@ -0,0 +1,188 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include + +namespace +{ + template< class Container > + void test_erase_impl() + { + Container source; + for (int i = 0; i < 10; ++i) + source.push_back(i); + + Container reference(source); + Container test(source); + + typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator_t; + + iterator_t first_ref = reference.begin(); + iterator_t last_ref = reference.end(); + + boost::iterator_range< iterator_t > test_range(test.begin(), test.end()); + + reference.erase(first_ref, last_ref); + boost::erase(test, test_range); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + void test_erase() + { + test_erase_impl >(); + test_erase_impl >(); + } + + template< class Container > + void test_remove_erase_impl() + { + Container source; + for (int i = 0; i < 10; ++i) + source.push_back(i); + + Container reference(source); + Container test(source); + + boost::remove_erase(test, 5); + + reference.erase( std::find(reference.begin(), reference.end(), 5) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + void test_remove_erase() + { + test_remove_erase_impl >(); + test_remove_erase_impl >(); + } + + struct is_even + { + typedef bool result_type; + typedef int argument_type; + bool operator()(int x) const { return x % 2 == 0; } + }; + + template< class Container > + void test_remove_erase_if_impl() + { + Container source; + for (int i = 0; i < 10; ++i) + source.push_back(i); + + Container reference; + typedef BOOST_DEDUCED_TYPENAME Container::const_iterator iterator_t; + iterator_t last_source = source.end(); + is_even pred; + for (iterator_t it_source = source.begin(); it_source != last_source; ++it_source) + { + if (!pred(*it_source)) + reference.push_back(*it_source); + } + + Container test(source); + boost::remove_erase_if(test, is_even()); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + } + + void test_remove_erase_if() + { + test_remove_erase_if_impl >(); + test_remove_erase_if_impl >(); + } + + template< class Container > + void test_unique_erase_impl() + { + Container source; + source.push_back(1); + source.push_back(1); + source.push_back(1); + source.push_back(2); + source.push_back(3); + source.push_back(3); + + Container reference; + reference.push_back(1); + reference.push_back(2); + reference.push_back(3); + + boost::unique_erase(source); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + source.begin(), source.end() ); + } + + void test_unique_erase() + { + test_unique_erase_impl >(); + test_unique_erase_impl >(); + } + + struct distance_smaller_2 + { + typedef bool result_type; + typedef int argument_type; + bool operator()(int x, int y) const { return std::abs(x - y) < 2; } + }; + + template< class Container > + void test_unique_erase_pred_impl() + { + Container source; + for (int i = 0; i < 10; ++i) + source.push_back(i); + + Container reference; + for (int i = 0; i < 10; i += 2) + reference.push_back(i); + + + boost::unique_erase(source, distance_smaller_2()); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + source.begin(), source.end() ); + } + + void test_unique_erase_pred() + { + test_unique_erase_pred_impl >(); + test_unique_erase_pred_impl >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.erase" ); + + test->add( BOOST_TEST_CASE( &test_erase ) ); + test->add( BOOST_TEST_CASE( &test_remove_erase ) ); + test->add( BOOST_TEST_CASE( &test_remove_erase_if ) ); + test->add( BOOST_TEST_CASE( &test_unique_erase ) ); + test->add( BOOST_TEST_CASE( &test_unique_erase_pred ) ); + + return test; +} diff --git a/libs/range/test/algorithm_ext_test/for_each_ext.cpp b/libs/range/test/algorithm_ext_test/for_each_ext.cpp new file mode 100644 index 00000000..9df16c59 --- /dev/null +++ b/libs/range/test/algorithm_ext_test/for_each_ext.cpp @@ -0,0 +1,98 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include + +namespace +{ + struct MockBinaryFn + { + typedef void result_type; + typedef int first_argument_type; + typedef int second_argument_type; + + void operator()(int x, int y) + { + xs.push_back(x); + ys.push_back(y); + } + + std::vector xs; + std::vector ys; + }; + + template< class Range1, class Range2 > + void test_for_each_impl( Range1& rng1, Range2& rng2 ) + { + MockBinaryFn fn = boost::range::for_each(rng1, rng2, MockBinaryFn()); + + BOOST_CHECK_EQUAL_COLLECTIONS( ::boost::begin(rng1), ::boost::end(rng1), + fn.xs.begin(), fn.xs.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( ::boost::begin(rng2), ::boost::end(rng2), + fn.ys.begin(), fn.ys.end() ); + } + + template< class Collection1, class Collection2 > + void test_for_each_impl(const int max_count) + { + Collection1 c1; + for (int i = 0; i < max_count; ++i) + c1.push_back(i); + + Collection2 c2; + for (int i = 0; i < max_count; ++i) + c2.push_back(i); + + test_for_each_impl(c1, c2); + + const Collection1& const_c1 = c1; + const Collection2& const_c2 = c2; + + test_for_each_impl(c1, const_c2); + test_for_each_impl(const_c1, c2); + test_for_each_impl(const_c1, const_c2); + } + + template< class Collection1, class Collection2 > + void test_for_each_impl() + { + test_for_each_impl< Collection1, Collection2 >(0); + test_for_each_impl< Collection1, Collection2 >(1); + test_for_each_impl< Collection1, Collection2 >(10); + } + + void test_for_each() + { + test_for_each_impl< std::vector, std::vector >(); + test_for_each_impl< std::list, std::list >(); + test_for_each_impl< std::vector, std::list >(); + test_for_each_impl< std::list, std::vector >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.for_each" ); + + test->add( BOOST_TEST_CASE( &test_for_each ) ); + + return test; +} diff --git a/libs/range/test/algorithm_ext_test/insert.cpp b/libs/range/test/algorithm_ext_test/insert.cpp new file mode 100644 index 00000000..ff1f706a --- /dev/null +++ b/libs/range/test/algorithm_ext_test/insert.cpp @@ -0,0 +1,72 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace +{ + template< class Container > + void test_insert_impl( int n ) + { + Container test; + boost::insert( test, test.end(), boost::irange(0, n) ); + + Container reference; + for (int i = 0; i < n; ++i) + reference.push_back(i); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + // Do it again so that we are inserting into a non-empty target + boost::insert( test, test.end(), boost::irange(0, n) ); + + for (int j = 0; j < n; ++j) + reference.push_back(j); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + template< class Container > + void test_insert_impl() + { + test_insert_impl< Container >(0); + test_insert_impl< Container >(1); + test_insert_impl< Container >(2); + test_insert_impl< Container >(100); + } + + void test_insert() + { + test_insert_impl< std::vector >(); + test_insert_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.insert" ); + + test->add( BOOST_TEST_CASE( &test_insert ) ); + + return test; +} diff --git a/libs/range/test/algorithm_ext_test/iota.cpp b/libs/range/test/algorithm_ext_test/iota.cpp new file mode 100644 index 00000000..64d9b0e7 --- /dev/null +++ b/libs/range/test/algorithm_ext_test/iota.cpp @@ -0,0 +1,70 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include + +namespace +{ + template< class Container > + void test_iota_impl(std::size_t n) + { + Container test; + test.resize( n ); + boost::iota( test, n ); + + Container reference; + reference.resize( n ); + std::size_t i = n; + typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator_t; + iterator_t last = reference.end(); + for (iterator_t it = reference.begin(); it != last; ++it, ++i) + { + *it = i; + } + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + } + + template< class Container > + void test_iota_impl() + { + test_iota_impl< Container >(0); + test_iota_impl< Container >(1); + test_iota_impl< Container >(2); + test_iota_impl< Container >(100); + } + + void test_iota() + { + test_iota_impl< std::vector >(); + test_iota_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.iota" ); + + test->add( BOOST_TEST_CASE( &test_iota ) ); + + return test; +} diff --git a/libs/range/test/algorithm_ext_test/is_sorted.cpp b/libs/range/test/algorithm_ext_test/is_sorted.cpp new file mode 100644 index 00000000..bddc5f89 --- /dev/null +++ b/libs/range/test/algorithm_ext_test/is_sorted.cpp @@ -0,0 +1,62 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include + +namespace +{ + template< class Container > + void test_is_sorted_impl() + { + Container ascending; + Container descending; + + // Empty ranges are regarded as sorted against any predicate. + BOOST_CHECK( boost::is_sorted(ascending) ); + BOOST_CHECK( boost::is_sorted(ascending, std::less()) ); + BOOST_CHECK( boost::is_sorted(ascending, std::greater()) ); + + for (std::size_t i = 0; i < 10; ++i) + { + ascending.push_back(i); + descending.push_back(9 - i); + } + + BOOST_CHECK( boost::is_sorted(ascending) ); + BOOST_CHECK( !boost::is_sorted(descending) ); + BOOST_CHECK( !boost::is_sorted(ascending, std::greater()) ); + BOOST_CHECK( boost::is_sorted(descending, std::greater()) ); + } + + void test_is_sorted() + { + test_is_sorted_impl< std::vector >(); + test_is_sorted_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.is_sorted" ); + + test->add( BOOST_TEST_CASE( &test_is_sorted ) ); + + return test; +} diff --git a/libs/range/test/algorithm_ext_test/overwrite.cpp b/libs/range/test/algorithm_ext_test/overwrite.cpp new file mode 100644 index 00000000..0d8604a3 --- /dev/null +++ b/libs/range/test/algorithm_ext_test/overwrite.cpp @@ -0,0 +1,74 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include + +namespace +{ + template< class Container > + void test_overwrite_impl(std::size_t n) + { + Container overwrite_source; + for (std::size_t i = 0; i < n; ++i) + overwrite_source.push_back(i); + + Container reference; + reference.resize(n); + std::copy(overwrite_source.begin(), overwrite_source.end(), reference.begin()); + + Container test; + test.resize(n); + boost::overwrite(overwrite_source, test); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + test.clear(); + test.resize(n); + const Container& const_overwrite_source = overwrite_source; + boost::overwrite(const_overwrite_source, test); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + template< class Container > + void test_overwrite_impl() + { + test_overwrite_impl(0); + test_overwrite_impl(1); + test_overwrite_impl(10); + } + + void test_overwrite() + { + test_overwrite_impl< std::vector >(); + test_overwrite_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.overwrite" ); + + test->add( BOOST_TEST_CASE( &test_overwrite ) ); + + return test; +} diff --git a/libs/range/test/algorithm_ext_test/push_back.cpp b/libs/range/test/algorithm_ext_test/push_back.cpp new file mode 100644 index 00000000..7e9d539f --- /dev/null +++ b/libs/range/test/algorithm_ext_test/push_back.cpp @@ -0,0 +1,72 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace +{ + template< class Container > + void test_push_back_impl(std::size_t n) + { + Container reference; + for (std::size_t i = 0; i < n; ++i) + reference.push_back(i); + + Container test; + boost::push_back(test, boost::irange(0, n)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + // Do it again to push onto non-empty container + for (std::size_t j = 0; j < n; ++j) + reference.push_back(j); + + boost::push_back(test, boost::irange(0, n)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + template< class Container > + void test_push_back_impl() + { + test_push_back_impl< Container >(0); + test_push_back_impl< Container >(1); + test_push_back_impl< Container >(2); + test_push_back_impl< Container >(100); + } + + void test_push_back() + { + test_push_back_impl< std::vector >(); + test_push_back_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.push_back" ); + + test->add( BOOST_TEST_CASE( &test_push_back ) ); + + return test; +} diff --git a/libs/range/test/algorithm_ext_test/push_front.cpp b/libs/range/test/algorithm_ext_test/push_front.cpp new file mode 100644 index 00000000..071a7cec --- /dev/null +++ b/libs/range/test/algorithm_ext_test/push_front.cpp @@ -0,0 +1,84 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace +{ + struct DoubleValue + { + template< class Value > + Value operator()(Value x) + { + return x * 2; + } + }; + + template< class Container > + void test_push_front_impl(std::size_t n) + { + Container reference; + for (std::size_t i = 0; i < n; ++i) + reference.push_back(i); + + Container test; + boost::push_front(test, boost::irange(0, n)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + // copy the original reference sequence + Container reference_copy(reference); + std::transform(reference.begin(), reference.end(), reference.begin(), DoubleValue()); + + // Do it again to push onto non-empty container + reference.insert(reference.end(), reference_copy.begin(), reference_copy.end()); + + boost::push_front(test, boost::irange(0, n * 2, 2)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + template< class Container > + void test_push_front_impl() + { + test_push_front_impl< Container >(0); + test_push_front_impl< Container >(1); + test_push_front_impl< Container >(2); + test_push_front_impl< Container >(100); + } + + void test_push_front() + { + test_push_front_impl< std::vector >(); + test_push_front_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm_ext.push_front" ); + + test->add( BOOST_TEST_CASE( &test_push_front ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/adjacent_find.cpp b/libs/range/test/algorithm_test/adjacent_find.cpp new file mode 100644 index 00000000..63b65e81 --- /dev/null +++ b/libs/range/test/algorithm_test/adjacent_find.cpp @@ -0,0 +1,95 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void test_adjacent_find_impl() + { + using namespace boost::assign; + + typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator_t; + typedef BOOST_DEDUCED_TYPENAME Container::const_iterator const_iterator_t; + + Container cont; + const Container& cref_cont = cont; + + std::equal_to pred; + + BOOST_CHECK( boost::adjacent_find(cont) == cont.end() ); + BOOST_CHECK( boost::adjacent_find(cref_cont) == cref_cont.end() ); + BOOST_CHECK( boost::adjacent_find(boost::make_iterator_range(cont)) == cont.end() ); + BOOST_CHECK( boost::adjacent_find(cont, pred) == cont.end() ); + BOOST_CHECK( boost::adjacent_find(cref_cont, pred) == cref_cont.end() ); + BOOST_CHECK( boost::adjacent_find(boost::make_iterator_range(cont), pred) == cont.end() ); + + cont += 1; + BOOST_CHECK( boost::adjacent_find(cont) == cont.end() ); + BOOST_CHECK( boost::adjacent_find(cref_cont) == cref_cont.end() ); + BOOST_CHECK( boost::adjacent_find(boost::make_iterator_range(cont)) == cont.end() ); + BOOST_CHECK( boost::adjacent_find(cont, pred) == cont.end() ); + BOOST_CHECK( boost::adjacent_find(cref_cont, pred) == cref_cont.end() ); + BOOST_CHECK( boost::adjacent_find(boost::make_iterator_range(cont), pred) == cont.end() ); + + cont += 2,3,4,5,5,5,6,7,8,9; + iterator_t it = boost::adjacent_find(cont); + iterator_t it_pred = boost::adjacent_find(cont, pred); + BOOST_CHECK( it == it_pred ); + BOOST_CHECK( it != cont.end() ); + BOOST_CHECK( it == std::adjacent_find(cont.begin(), cont.end()) ); + if (it != cont.end()) + { + BOOST_CHECK( *it == 5 ); + } + BOOST_CHECK( it == boost::adjacent_find(boost::make_iterator_range(cont)) ); + BOOST_CHECK( it_pred == boost::adjacent_find(boost::make_iterator_range(cont), pred) ); + const_iterator_t cit = boost::adjacent_find(cref_cont); + const_iterator_t cit_pred = boost::adjacent_find(cref_cont, pred); + BOOST_CHECK( cit == cit_pred ); + BOOST_CHECK( cit != cref_cont.end() ); + BOOST_CHECK( cit == std::adjacent_find(cref_cont.begin(), cref_cont.end()) ); + if (cit != cref_cont.end()) + { + BOOST_CHECK( *cit == 5 ); + } + } + + void test_adjacent_find() + { + test_adjacent_find_impl< std::vector >(); + test_adjacent_find_impl< std::list >(); + test_adjacent_find_impl< std::multiset >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.adjacent_find" ); + + test->add( BOOST_TEST_CASE( &boost::test_adjacent_find ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/binary_search.cpp b/libs/range/test/algorithm_test/binary_search.cpp new file mode 100644 index 00000000..7cf985d6 --- /dev/null +++ b/libs/range/test/algorithm_test/binary_search.cpp @@ -0,0 +1,125 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void test(Container& cont) + { + Container reference(cont); + Container test(cont); + + bool reference_result + = std::binary_search(reference.begin(), reference.end(), 5); + + bool test_result = boost::binary_search(test, 5); + + BOOST_CHECK( reference_result == test_result ); + + BOOST_CHECK( test_result == boost::binary_search(boost::make_iterator_range(test), 5) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + } + + template + void sort_container(Container& cont, BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector temp(cont.begin(), cont.end()); + std::sort(temp.begin(), temp.end(), pred); + cont.assign(temp.begin(), temp.end()); + } + + template + void test_pred(Container& cont, BinaryPredicate pred) + { + Container reference(cont); + Container test(cont); + + sort_container(reference, pred); + sort_container(test, pred); + + bool reference_result + = std::binary_search(reference.begin(), reference.end(), 5, + pred); + + bool test_result = boost::binary_search(test, 5, pred); + + BOOST_CHECK( test_result == boost::binary_search(boost::make_iterator_range(test), 5, pred) ); + + BOOST_CHECK( reference_result == test_result ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + } + + template + void test_binary_search_impl() + { + using namespace boost::assign; + + Container cont; + + test(cont); + test_pred(cont, std::less()); + test_pred(cont, std::greater()); + + cont.clear(); + cont += 1; + test(cont); + test_pred(cont, std::less()); + test_pred(cont, std::greater()); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test(cont); + test_pred(cont, std::less()); + test_pred(cont, std::greater()); + } + + void test_binary_search() + { + test_binary_search_impl< std::vector >(); + test_binary_search_impl< std::list >(); + test_binary_search_impl< std::deque >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.binary_search" ); + + test->add( BOOST_TEST_CASE( &boost::test_binary_search ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/copy.cpp b/libs/range/test/algorithm_test/copy.cpp new file mode 100644 index 00000000..4b9fcc2f --- /dev/null +++ b/libs/range/test/algorithm_test/copy.cpp @@ -0,0 +1,74 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void test_copy_impl() + { + Container source; + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector target; + target.resize(source.size()); + + typedef BOOST_DEDUCED_TYPENAME range_iterator< std::vector >::type iterator_t; + iterator_t it = boost::copy(source, target.begin()); + + BOOST_CHECK( it == target.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + target.begin(), target.end(), + source.begin(), source.end() + ); + + it = boost::copy(boost::make_iterator_range(source), target.begin()); + + BOOST_CHECK( it == target.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS(target.begin(), target.end(), + source.begin(), source.end()); + } + + void test_copy() + { + test_copy_impl< std::vector >(); + test_copy_impl< std::list >(); + test_copy_impl< std::set >(); + test_copy_impl< std::multiset >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.copy" ); + + test->add( BOOST_TEST_CASE( &boost::test_copy ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/copy_backward.cpp b/libs/range/test/algorithm_test/copy_backward.cpp new file mode 100644 index 00000000..4879c287 --- /dev/null +++ b/libs/range/test/algorithm_test/copy_backward.cpp @@ -0,0 +1,84 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +// Credits: +// awulkiew highlighted that this test was not successfully testing the +// algorithm. +// +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace boost_range_test +{ + namespace + { +template +void test_copy_backward_impl(std::size_t n) +{ + Container source; + typedef typename Container::value_type value_t; + for (std::size_t i = 0; i < n; ++i) + source.push_back(static_cast(i)); + + std::vector target(n); + + typedef typename boost::range_iterator< + std::vector + >::type iterator_t; + + iterator_t it = boost::copy_backward(source, target.end()); + + BOOST_CHECK(it == target.begin()); + + BOOST_CHECK_EQUAL_COLLECTIONS(target.begin(), target.end(), + source.begin(), source.end()); + + BOOST_CHECK(it == boost::copy_backward( + boost::make_iterator_range(source), target.end())); + + BOOST_CHECK_EQUAL_COLLECTIONS(target.begin(), target.end(), + source.begin(), source.end()); +} + +template +void test_copy_backward_impl() +{ + test_copy_backward_impl(0u); + test_copy_backward_impl(1u); + test_copy_backward_impl(100u); +} + +void test_copy_backward() +{ + test_copy_backward_impl >(); + test_copy_backward_impl >(); +} + } // anonymous namespace +} // namespace boost_range_test + + +boost::unit_test::test_suite* +init_unit_test_suite(int, char*[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE("RangeTestSuite.algorithm.copy_backward"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_copy_backward)); + + return test; +} diff --git a/libs/range/test/algorithm_test/copy_n.cpp b/libs/range/test/algorithm_test/copy_n.cpp new file mode 100644 index 00000000..230eb032 --- /dev/null +++ b/libs/range/test/algorithm_test/copy_n.cpp @@ -0,0 +1,70 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace +{ + template< class Container > + void test_copy_n_impl() + { + Container source; + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector target; + target.resize(source.size()); + + typedef BOOST_DEDUCED_TYPENAME range_iterator< std::vector >::type iterator_t; + iterator_t it = boost::copy(source, target.begin()); + + BOOST_CHECK( it == target.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + target.begin(), target.end(), + source.begin(), source.end() + ); + + it = boost::copy(boost::make_iterator_range(source), target.begin()); + + BOOST_CHECK( it == target.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS(target.begin(), target.end(), + source.begin(), source.end()); + } + + void test_copy_n() + { + test_copy_n_impl< std::vector >(); + test_copy_n_impl< std::list >(); + test_copy_n_impl< std::set >(); + test_copy_n_impl< std::multiset >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.copy_n" ); + + test->add( BOOST_TEST_CASE( &::test_copy_n ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/count.cpp b/libs/range/test/algorithm_test/count.cpp new file mode 100644 index 00000000..90b20903 --- /dev/null +++ b/libs/range/test/algorithm_test/count.cpp @@ -0,0 +1,85 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void test_count_impl() + { + using namespace boost::assign; + + Container cont; + const Container& cref_cont = cont; + + BOOST_CHECK_EQUAL( 0u, boost::count(cont, 0u) ); + BOOST_CHECK_EQUAL( 0u, boost::count(cref_cont, 0u) ); + BOOST_CHECK_EQUAL( 0u, boost::count(boost::make_iterator_range(cont), 0u) ); + + cont += 1; + BOOST_CHECK_EQUAL( 0u, boost::count(cont, 0u) ); + BOOST_CHECK_EQUAL( 0u, boost::count(cref_cont, 0u) ); + BOOST_CHECK_EQUAL( 0u, boost::count(boost::make_iterator_range(cont), 0u) ); + BOOST_CHECK_EQUAL( 1u, boost::count(cont, 1u) ); + BOOST_CHECK_EQUAL( 1u, boost::count(cref_cont, 1u) ); + BOOST_CHECK_EQUAL( 1u, boost::count(boost::make_iterator_range(cont), 1u) ); + + cont += 2,3,4,5,6,7,8,9; + BOOST_CHECK_EQUAL( 0u, boost::count(cont, 0u) ); + BOOST_CHECK_EQUAL( 0u, boost::count(cref_cont, 0u) ); + BOOST_CHECK_EQUAL( 0u, boost::count(boost::make_iterator_range(cont), 0u) ); + BOOST_CHECK_EQUAL( 1u, boost::count(cont, 1u) ); + BOOST_CHECK_EQUAL( 1u, boost::count(cref_cont, 1u) ); + BOOST_CHECK_EQUAL( 1u, boost::count(boost::make_iterator_range(cont), 1u) ); + + cont += 2; + BOOST_CHECK_EQUAL( 0u, boost::count(cont, 0u) ); + BOOST_CHECK_EQUAL( 0u, boost::count(cref_cont, 0u) ); + BOOST_CHECK_EQUAL( 0u, boost::count(boost::make_iterator_range(cont), 0u) ); + BOOST_CHECK_EQUAL( 1u, boost::count(cont, 1u) ); + BOOST_CHECK_EQUAL( 1u, boost::count(cref_cont, 1u) ); + BOOST_CHECK_EQUAL( 1u, boost::count(boost::make_iterator_range(cont), 1u) ); + BOOST_CHECK_EQUAL( 2u, boost::count(cont, 2u) ); + BOOST_CHECK_EQUAL( 2u, boost::count(cref_cont, 2u) ); + BOOST_CHECK_EQUAL( 2u, boost::count(boost::make_iterator_range(cont), 2u) ); + } + + void test_count() + { + test_count_impl< std::vector >(); + test_count_impl< std::list >(); + test_count_impl< std::multiset >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.count" ); + + test->add( BOOST_TEST_CASE( &boost::test_count ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/count_if.cpp b/libs/range/test/algorithm_test/count_if.cpp new file mode 100644 index 00000000..e028741c --- /dev/null +++ b/libs/range/test/algorithm_test/count_if.cpp @@ -0,0 +1,100 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include "../test_function/false_predicate.hpp" +#include "../test_function/true_predicate.hpp" +#include "../test_function/equal_to_x.hpp" +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void test_count_if_impl() + { + using namespace boost::range_test_function; + using namespace boost::assign; + + typedef equal_to_x pred_t; + typedef BOOST_DEDUCED_TYPENAME std::iterator_traits::difference_type diff_t; + + Container cont; + const Container& cref_cont = cont; + + BOOST_CHECK_EQUAL( 0u, boost::count_if(cont, pred_t(0)) ); + BOOST_CHECK_EQUAL( 0u, boost::count_if(cref_cont, pred_t(0)) ); + BOOST_CHECK_EQUAL( 0u, boost::count_if(boost::make_iterator_range(cont), pred_t(0)) ); + + cont += 1; + BOOST_CHECK_EQUAL( 0u, boost::count_if(cont, pred_t(0)) ); + BOOST_CHECK_EQUAL( 0u, boost::count_if(cref_cont, pred_t(0)) ); + BOOST_CHECK_EQUAL( 0u, boost::count_if(boost::make_iterator_range(cont), pred_t(0)) ); + BOOST_CHECK_EQUAL( 1u, boost::count_if(cont, pred_t(1)) ); + BOOST_CHECK_EQUAL( 1u, boost::count_if(cref_cont, pred_t(1)) ); + BOOST_CHECK_EQUAL( 1u, boost::count_if(boost::make_iterator_range(cont), pred_t(1)) ); + + cont += 2,3,4,5,6,7,8,9; + BOOST_CHECK_EQUAL( 0u, boost::count_if(cont, pred_t(0)) ); + BOOST_CHECK_EQUAL( 0u, boost::count_if(cref_cont, pred_t(0)) ); + BOOST_CHECK_EQUAL( 0u, boost::count_if(boost::make_iterator_range(cont), pred_t(0)) ); + BOOST_CHECK_EQUAL( 1u, boost::count_if(cont, pred_t(1)) ); + BOOST_CHECK_EQUAL( 1u, boost::count_if(cref_cont, pred_t(1)) ); + BOOST_CHECK_EQUAL( 1u, boost::count_if(boost::make_iterator_range(cont), pred_t(1)) ); + + cont += 2; + BOOST_CHECK_EQUAL( 0u, boost::count_if(cont, pred_t(0)) ); + BOOST_CHECK_EQUAL( 0u, boost::count_if(cref_cont, pred_t(0)) ); + BOOST_CHECK_EQUAL( 0u, boost::count_if(boost::make_iterator_range(cont), pred_t(0)) ); + BOOST_CHECK_EQUAL( 1u, boost::count_if(cont, pred_t(1)) ); + BOOST_CHECK_EQUAL( 1u, boost::count_if(cref_cont, pred_t(1)) ); + BOOST_CHECK_EQUAL( 1u, boost::count_if(boost::make_iterator_range(cont), pred_t(1)) ); + BOOST_CHECK_EQUAL( 2u, boost::count_if(cont, pred_t(2)) ); + BOOST_CHECK_EQUAL( 2u, boost::count_if(cref_cont, pred_t(2)) ); + BOOST_CHECK_EQUAL( 2u, boost::count_if(boost::make_iterator_range(cont), pred_t(2)) ); + + BOOST_CHECK_EQUAL( 0u, boost::count_if(cont, false_predicate()) ); + BOOST_CHECK_EQUAL( 0u, boost::count_if(cref_cont, false_predicate()) ); + BOOST_CHECK_EQUAL( 0u, boost::count_if(boost::make_iterator_range(cont), false_predicate()) ); + + BOOST_CHECK_EQUAL( static_cast(cont.size()), boost::count_if(cont, true_predicate()) ); + BOOST_CHECK_EQUAL( static_cast(cont.size()), boost::count_if(cref_cont, true_predicate()) ); + BOOST_CHECK_EQUAL( static_cast(cont.size()), boost::count_if(boost::make_iterator_range(cont), true_predicate()) ); + } + + void test_count_if() + { + test_count_if_impl< std::vector >(); + test_count_if_impl< std::list >(); + test_count_if_impl< std::multiset >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.count_if" ); + + test->add( BOOST_TEST_CASE( &boost::test_count_if ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/equal.cpp b/libs/range/test/algorithm_test/equal.cpp new file mode 100644 index 00000000..243f0645 --- /dev/null +++ b/libs/range/test/algorithm_test/equal.cpp @@ -0,0 +1,143 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container1, class Container2 > + void test_equal_impl() + { + using namespace boost::assign; + + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container1_t; + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container2_t; + + container1_t mcont1; + container2_t mcont2; + + Container1& cont1 = mcont1; + Container2& cont2 = mcont2; + + BOOST_CHECK( boost::equal(cont1, cont2) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), cont2) ); + BOOST_CHECK( boost::equal(cont1, boost::make_iterator_range(cont2)) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2)) ); + BOOST_CHECK( boost::equal(cont1, cont2, std::equal_to()) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), cont2, std::equal_to()) ); + BOOST_CHECK( boost::equal(cont1, boost::make_iterator_range(cont2), std::equal_to()) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2), std::equal_to()) ); + BOOST_CHECK( boost::equal(cont1, cont2, std::not_equal_to()) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), cont2, std::not_equal_to()) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2), std::not_equal_to()) ); + + mcont1 += 1; + BOOST_CHECK( !boost::equal(cont1, cont2) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), cont2) ); + BOOST_CHECK( !boost::equal(cont1, boost::make_iterator_range(cont2)) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2)) ); + BOOST_CHECK( !boost::equal(cont1, cont2, std::equal_to()) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), cont2, std::equal_to()) ); + BOOST_CHECK( !boost::equal(cont1, boost::make_iterator_range(cont2), std::equal_to()) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2), std::equal_to()) ); + BOOST_CHECK( !boost::equal(cont1, cont2, std::not_equal_to()) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), cont2, std::not_equal_to()) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2), std::not_equal_to()) ); + + mcont1.clear(); + mcont2 += 1; + BOOST_CHECK( !boost::equal(cont1, cont2) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), cont2) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2)) ); + BOOST_CHECK( !boost::equal(cont1, cont2, std::equal_to()) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), cont2, std::equal_to()) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2), std::equal_to()) ); + BOOST_CHECK( !boost::equal(cont1, cont2, std::not_equal_to()) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), cont2, std::not_equal_to()) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2), std::not_equal_to()) ); + + mcont1 += 1; + BOOST_CHECK( boost::equal(cont1, cont2) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), cont2) ); + BOOST_CHECK( boost::equal(cont1, boost::make_iterator_range(cont2)) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2)) ); + BOOST_CHECK( boost::equal(cont1, cont2, std::equal_to()) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), cont2, std::equal_to()) ); + BOOST_CHECK( boost::equal(cont1, boost::make_iterator_range(cont2), std::equal_to()) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2), std::equal_to()) ); + BOOST_CHECK( !boost::equal(cont1, cont2, std::not_equal_to()) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), cont2, std::not_equal_to()) ); + BOOST_CHECK( !boost::equal(cont1, boost::make_iterator_range(cont2), std::not_equal_to()) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2), std::not_equal_to()) ); + + mcont1 += 2,3,4,5,6,7,8,9; + mcont2 += 2,3,4,5,6,7,8,9; + BOOST_CHECK( boost::equal(cont1, cont2) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), cont2) ); + BOOST_CHECK( boost::equal(cont1, boost::make_iterator_range(cont2)) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2)) ); + BOOST_CHECK( boost::equal(cont1, cont2, std::equal_to()) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), cont2, std::equal_to()) ); + BOOST_CHECK( boost::equal(cont1, boost::make_iterator_range(cont2), std::equal_to()) ); + BOOST_CHECK( boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2), std::equal_to()) ); + BOOST_CHECK( !boost::equal(cont1, cont2, std::not_equal_to()) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), cont2, std::not_equal_to()) ); + BOOST_CHECK( !boost::equal(cont1, boost::make_iterator_range(cont2), std::not_equal_to()) ); + BOOST_CHECK( !boost::equal(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2), std::not_equal_to()) ); + } + + template< class Container1, class Container2 > + void test_driver() + { + typedef Container1 container1_t; + typedef Container2 container2_t; + typedef BOOST_DEDUCED_TYPENAME boost::add_const::type const_container1_t; + typedef BOOST_DEDUCED_TYPENAME boost::add_const::type const_container2_t; + + test_equal_impl< const_container1_t, const_container2_t >(); + test_equal_impl< const_container1_t, container2_t >(); + test_equal_impl< container1_t, const_container2_t >(); + test_equal_impl< container1_t, container2_t >(); + } + + void test_equal() + { + test_driver< std::list, std::list >(); + test_driver< std::vector, std::vector >(); + test_driver< std::set, std::set >(); + test_driver< std::multiset, std::multiset >(); + test_driver< std::list, std::vector >(); + test_driver< std::vector, std::list >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.equal" ); + + test->add( BOOST_TEST_CASE( &boost::test_equal ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/equal_range.cpp b/libs/range/test/algorithm_test/equal_range.cpp new file mode 100644 index 00000000..00b07a64 --- /dev/null +++ b/libs/range/test/algorithm_test/equal_range.cpp @@ -0,0 +1,180 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void check_result( + const Container& reference, + Pair reference_pair, + const Container& test, + Pair test_pair + ) + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type + const_iterator_t; + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + + BOOST_CHECK_EQUAL( + std::distance(reference.begin(), reference_pair.first), + std::distance(test.begin(), test_pair.first) + ); + + BOOST_CHECK_EQUAL( + std::distance(reference.begin(), reference_pair.second), + std::distance(test.begin(), test_pair.second) + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference_pair.first, reference_pair.second, + test_pair.first, test_pair.second + ); + } + + template + void test(Container& cont) + { + Container reference(cont); + Container test(cont); + + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; + typedef std::pair pair_t; + + pair_t reference_result + = std::equal_range(reference.begin(), reference.end(), 5); + + pair_t test_result = boost::equal_range(test, 5); + + check_result(reference, reference_result, test, test_result); + + pair_t test_result2 = boost::equal_range(boost::make_iterator_range(test), 5); + + check_result(reference, reference_result, test, test_result2); + } + + template + void sort_container(Container& cont, BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector temp(cont.begin(), cont.end()); + std::sort(temp.begin(), temp.end(), pred); + cont.assign(temp.begin(), temp.end()); + } + + template + void test_pred(Container& cont, BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container_t; + + container_t reference_temp(cont); + container_t test_temp(cont); + + sort_container(reference_temp, pred); + sort_container(test_temp, pred); + + Container reference(reference_temp); + Container test(test_temp); + + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; + typedef std::pair pair_t; + + pair_t reference_result + = std::equal_range(reference.begin(), reference.end(), 5, + BinaryPredicate()); + + pair_t test_result = boost::equal_range(test, 5, BinaryPredicate()); + + check_result(reference, reference_result, test, test_result); + + pair_t test_result2 = boost::equal_range(boost::make_iterator_range(test), 5, BinaryPredicate()); + + check_result(reference, reference_result, test, test_result2); + } + + template + void test_driver(const Container& cont) + { + Container mutable_cont(cont); + test(mutable_cont); + + test(cont); + } + + template + void test_pred_driver(const Container& cont, BinaryPredicate pred) + { + Container mutable_cont(cont); + test_pred(mutable_cont, pred); + + test_pred(cont, pred); + } + + template + void test_equal_range_impl() + { + using namespace boost::assign; + + Container cont; + + test_driver(cont); + test_pred_driver(cont, std::less()); + test_pred_driver(cont, std::greater()); + + cont.clear(); + cont += 1; + test_driver(cont); + test_pred_driver(cont, std::less()); + test_pred_driver(cont, std::greater()); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_driver(cont); + test_pred_driver(cont, std::less()); + test_pred_driver(cont, std::greater()); + } + + void test_equal_range() + { + test_equal_range_impl< std::vector >(); + test_equal_range_impl< std::list >(); + test_equal_range_impl< std::deque >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.equal_range" ); + + test->add( BOOST_TEST_CASE( &boost::test_equal_range ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/fill.cpp b/libs/range/test/algorithm_test/fill.cpp new file mode 100644 index 00000000..2f975c4c --- /dev/null +++ b/libs/range/test/algorithm_test/fill.cpp @@ -0,0 +1,86 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void test_fill_impl(Container& cont) + { + Container reference(cont); + std::fill(reference.begin(), reference.end(), 1); + + Container target(cont); + boost::fill(target, 1); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target.begin(), target.end() ); + + Container target2(cont); + boost::fill(boost::make_iterator_range(target2), 1); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target2.begin(), target2.end() ); + } + + template< class Container > + void test_fill_impl() + { + using namespace boost::assign; + + Container cont; + test_fill_impl(cont); + + cont.clear(); + cont += 2; + test_fill_impl(cont); + + cont.clear(); + cont += 1,2; + test_fill_impl(cont); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_fill_impl(cont); + } + + void test_fill() + { + test_fill_impl< std::vector >(); + test_fill_impl< std::list >(); + test_fill_impl< std::deque >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.fill" ); + + test->add( BOOST_TEST_CASE( &boost::test_fill ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/find.cpp b/libs/range/test/algorithm_test/find.cpp new file mode 100644 index 00000000..02c9f717 --- /dev/null +++ b/libs/range/test/algorithm_test/find.cpp @@ -0,0 +1,131 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include "../test_driver/range_return_test_driver.hpp" +#include +#include +#include +#include +#include +#include + +namespace boost_range_test_algorithm_find +{ + class find_test_policy + { + public: + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::find(cont, 3); + iter_t result2 = boost::find(boost::make_iterator_range(cont), 3); + BOOST_CHECK( result == result2 ); + return result; + } + + template + struct test_range + { + template + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy&, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + result_t result = boost::find(cont, 3); + result_t result2 = boost::find(boost::make_iterator_range(cont), 3); + BOOST_CHECK( result == result2 ); + return result; + } + }; + + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::find(cont.begin(), cont.end(), 3); + } + }; + + template + void test_find_container() + { + using namespace boost::assign; + + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container_t; + + boost::range_test::range_return_test_driver test_driver; + + container_t mcont; + Container& cont = mcont; + test_driver(cont, find_test_policy()); + + mcont.clear(); + mcont += 1; + test_driver(cont, find_test_policy()); + + mcont.clear(); + mcont += 1,2,3,4,5,6,7,8,9; + test_driver(cont, find_test_policy()); + } + + void test_find() + { + test_find_container< std::vector >(); + test_find_container< std::list >(); + test_find_container< std::deque >(); + + test_find_container< const std::vector >(); + test_find_container< const std::list >(); + test_find_container< const std::deque >(); + + std::vector vi; + const std::vector& cvi = vi; + std::vector::const_iterator it = boost::find(vi, 0); + std::vector::const_iterator it2 = boost::find(cvi, 0); + BOOST_CHECK( it == it2 ); + } + + // The find algorithm can be used like a "contains" algorithm + // since the returned iterator_range is convertible to bool. + // Therefore if the return value is an empty range it will + // convert to the equivalent to "false" whereas a range that + // is not empty will convert to "true". Therefore one can + // use the syntax boost::find(rng, x) + // as a contains function. + void test_find_as_contains() + { + std::list l; + for (int i = 0; i < 10; ++i) + l.push_back(i); + + BOOST_CHECK(boost::find(l, 3)); + BOOST_CHECK(!boost::find(l, 10)); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.find" ); + + test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_find::test_find ) ); + test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_find::test_find_as_contains ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/find_end.cpp b/libs/range/test/algorithm_test/find_end.cpp new file mode 100644 index 00000000..b4d77a08 --- /dev/null +++ b/libs/range/test/algorithm_test/find_end.cpp @@ -0,0 +1,200 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include "../test_driver/range_return_test_driver.hpp" +#include +#include +#include +#include +#include + +namespace boost_range_test_algorithm_find_end +{ + template + class find_end_test_policy + { + typedef Container2 container2_t; + public: + explicit find_end_test_policy(const Container2& cont) + : m_cont(cont) + { + } + + container2_t cont() { return m_cont; } + + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::find_end(cont, m_cont); + BOOST_CHECK( result == boost::find_end(boost::make_iterator_range(cont), m_cont) ); + BOOST_CHECK( result == boost::find_end(cont, boost::make_iterator_range(m_cont)) ); + BOOST_CHECK( result == boost::find_end(boost::make_iterator_range(cont), boost::make_iterator_range(m_cont)) ); + return result; + } + + template + struct test_range + { + template + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + result_t result = boost::find_end(cont, policy.cont()); + BOOST_CHECK( result == boost::find_end(boost::make_iterator_range(cont), policy.cont()) ); + BOOST_CHECK( result == boost::find_end(cont, boost::make_iterator_range(policy.cont())) ); + BOOST_CHECK( result == boost::find_end(boost::make_iterator_range(cont), + boost::make_iterator_range(policy.cont())) ); + return result; + } + }; + + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::find_end(cont.begin(), cont.end(), + m_cont.begin(), m_cont.end()); + } + + private: + Container2 m_cont; + }; + + template + class find_end_pred_test_policy + { + typedef Container2 container2_t; + public: + explicit find_end_pred_test_policy(const Container2& cont) + : m_cont(cont) + { + } + + container2_t& cont() { return m_cont; } + BinaryPredicate& pred() { return m_pred; } + + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t it = boost::find_end(cont, m_cont, m_pred); + BOOST_CHECK( it == boost::find_end(boost::make_iterator_range(cont), m_cont, m_pred) ); + BOOST_CHECK( it == boost::find_end(cont, boost::make_iterator_range(m_cont), m_pred) ); + BOOST_CHECK( it == boost::find_end(boost::make_iterator_range(cont), boost::make_iterator_range(m_cont), m_pred) ); + return it; + } + + template + struct test_range + { + template + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + result_t result = boost::find_end(cont, policy.cont(), policy.pred()); + BOOST_CHECK( result == boost::find_end(boost::make_iterator_range(cont), policy.cont(), policy.pred()) ); + BOOST_CHECK( result == boost::find_end(cont, boost::make_iterator_range(policy.cont()), policy.pred()) ); + BOOST_CHECK( result == boost::find_end(boost::make_iterator_range(cont), + boost::make_iterator_range(policy.cont()), policy.pred()) ); + return boost::find_end(cont, policy.cont(), policy.pred()); + } + }; + + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::find_end(cont.begin(), cont.end(), + m_cont.begin(), m_cont.end(), + m_pred); + } + + private: + Container2 m_cont; + BinaryPredicate m_pred; + }; + + template + void run_tests(Container1& cont1, Container2& cont2) + { + boost::range_test::range_return_test_driver test_driver; + test_driver(cont1, find_end_test_policy(cont2)); + test_driver(cont1, find_end_pred_test_policy >(cont2)); + test_driver(cont2, find_end_pred_test_policy >(cont2)); + } + + template + void test_find_end_impl() + { + using namespace boost::assign; + + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container1_t; + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container2_t; + + container1_t mcont1; + Container1& cont1 = mcont1; + container2_t mcont2; + Container2& cont2 = mcont2; + + run_tests(cont1, cont2); + + mcont1 += 1; + run_tests(cont1, cont2); + + mcont2 += 1; + run_tests(cont1, cont2); + + mcont1 += 2,3,4,5,6,7,8,9; + mcont2 += 2,3,4; + run_tests(cont1, cont2); + + mcont2.clear(); + mcont2 += 7,8,9; + run_tests(cont1, cont2); + } + + void test_find_end() + { + test_find_end_impl< std::vector, std::vector >(); + test_find_end_impl< std::list, std::list >(); + test_find_end_impl< std::deque, std::deque >(); + test_find_end_impl< const std::vector, const std::vector >(); + test_find_end_impl< const std::list, const std::list >(); + test_find_end_impl< const std::deque, const std::deque >(); + test_find_end_impl< const std::vector, const std::list >(); + test_find_end_impl< const std::list, const std::vector >(); + test_find_end_impl< const std::vector, std::list >(); + test_find_end_impl< const std::list, std::vector >(); + test_find_end_impl< std::vector, std::list >(); + test_find_end_impl< std::list, std::vector >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.find_end" ); + + test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_find_end::test_find_end ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/find_first_of.cpp b/libs/range/test/algorithm_test/find_first_of.cpp new file mode 100644 index 00000000..296b8fce --- /dev/null +++ b/libs/range/test/algorithm_test/find_first_of.cpp @@ -0,0 +1,198 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include "../test_driver/range_return_test_driver.hpp" +#include +#include +#include +#include +#include + +namespace boost_range_test_algorithm_find_first_of +{ + template + class find_first_of_test_policy + { + typedef Container2 container2_t; + public: + explicit find_first_of_test_policy(const Container2& cont) + : m_cont(cont) + { + } + + container2_t& cont() { return m_cont; } + + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::find_first_of(cont, m_cont); + BOOST_CHECK( result == boost::find_first_of(boost::make_iterator_range(cont), m_cont) ); + BOOST_CHECK( result == boost::find_first_of(cont, boost::make_iterator_range(m_cont)) ); + BOOST_CHECK( result == boost::find_first_of(boost::make_iterator_range(cont), boost::make_iterator_range(m_cont)) ); + return result; + } + + template + struct test_range + { + template + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + result_t result = boost::find_first_of(cont, policy.cont()); + BOOST_CHECK( result == boost::find_first_of(boost::make_iterator_range(cont), policy.cont()) ); + BOOST_CHECK( result == boost::find_first_of(cont, boost::make_iterator_range(policy.cont())) ); + BOOST_CHECK( result == boost::find_first_of(boost::make_iterator_range(cont), boost::make_iterator_range(policy.cont())) ); + return result; + } + }; + + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::find_first_of(cont.begin(), cont.end(), + m_cont.begin(), m_cont.end()); + } + + private: + Container2 m_cont; + }; + + template + class find_first_of_pred_test_policy + { + typedef Container2 container2_t; + public: + explicit find_first_of_pred_test_policy(const Container2& cont) + : m_cont(cont) + { + } + + container2_t& cont() { return m_cont; } + BinaryPredicate& pred() { return m_pred; } + + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::find_first_of(cont, m_cont, m_pred); + BOOST_CHECK( result == boost::find_first_of(boost::make_iterator_range(cont), m_cont, m_pred) ); + BOOST_CHECK( result == boost::find_first_of(cont, boost::make_iterator_range(m_cont), m_pred) ); + BOOST_CHECK( result == boost::find_first_of(boost::make_iterator_range(cont), boost::make_iterator_range(m_cont), m_pred) ); + return result; + } + + template + struct test_range + { + template + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + result_t result = boost::find_first_of(cont, policy.cont(), policy.pred()); + BOOST_CHECK( result == boost::find_first_of(boost::make_iterator_range(cont), policy.cont(), policy.pred()) ); + BOOST_CHECK( result == boost::find_first_of(cont, boost::make_iterator_range(policy.cont()), policy.pred()) ); + BOOST_CHECK( result == boost::find_first_of(boost::make_iterator_range(cont), boost::make_iterator_range(policy.cont()), policy.pred()) ); + return result; + } + }; + + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::find_first_of(cont.begin(), cont.end(), + m_cont.begin(), m_cont.end(), + m_pred); + } + + private: + Container2 m_cont; + BinaryPredicate m_pred; + }; + + template + void run_tests(Container1& cont1, Container2& cont2) + { + boost::range_test::range_return_test_driver test_driver; + test_driver(cont1, find_first_of_test_policy(cont2)); + test_driver(cont1, find_first_of_pred_test_policy >(cont2)); + test_driver(cont2, find_first_of_pred_test_policy >(cont2)); + } + + template + void test_find_first_of_impl() + { + using namespace boost::assign; + + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container1_t; + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container2_t; + + container1_t mcont1; + Container1& cont1 = mcont1; + container2_t mcont2; + Container2& cont2 = mcont2; + + run_tests(cont1, cont2); + + mcont1 += 1; + run_tests(cont1, cont2); + + mcont2 += 1; + run_tests(cont1, cont2); + + mcont1 += 2,3,4,5,6,7,8,9; + mcont2 += 2,3,4; + run_tests(cont1, cont2); + + mcont2.clear(); + mcont2 += 7,8,9; + run_tests(cont1, cont2); + } + + void test_find_first_of() + { + test_find_first_of_impl< std::vector, std::vector >(); + test_find_first_of_impl< std::list, std::list >(); + test_find_first_of_impl< std::deque, std::deque >(); + test_find_first_of_impl< const std::vector, const std::vector >(); + test_find_first_of_impl< const std::list, const std::list >(); + test_find_first_of_impl< const std::deque, const std::deque >(); + test_find_first_of_impl< const std::vector, const std::list >(); + test_find_first_of_impl< const std::list, const std::vector >(); + test_find_first_of_impl< const std::vector, std::list >(); + test_find_first_of_impl< const std::list, std::vector >(); + test_find_first_of_impl< std::vector, std::list >(); + test_find_first_of_impl< std::list, std::vector >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.find_first_of" ); + + test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_find_first_of::test_find_first_of ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/find_if.cpp b/libs/range/test/algorithm_test/find_if.cpp new file mode 100644 index 00000000..3ab22c93 --- /dev/null +++ b/libs/range/test/algorithm_test/find_if.cpp @@ -0,0 +1,126 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include "../test_driver/range_return_test_driver.hpp" +#include "../test_function/greater_than_x.hpp" +#include "../test_function/false_predicate.hpp" +#include +#include +#include +#include +#include + +namespace boost_range_test_algorithm_find_if +{ + template + class find_if_test_policy + { + public: + explicit find_if_test_policy(UnaryPredicate pred) + : m_pred(pred) {} + + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::find_if(cont, m_pred); + BOOST_CHECK( result == boost::find_if(boost::make_iterator_range(cont), m_pred) ); + return result; + } + + template + struct test_range + { + template + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(find_if_test_policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + result_t result = boost::find_if(cont, policy.pred()); + BOOST_CHECK( result == boost::find_if(boost::make_iterator_range(cont), policy.pred()) ); + return result; + } + }; + + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::find_if(cont.begin(), cont.end(), m_pred); + } + + UnaryPredicate& pred() { return m_pred; } + + private: + UnaryPredicate m_pred; + }; + + template + find_if_test_policy + make_policy(UnaryPredicate pred) + { + return find_if_test_policy(pred); + } + + template + void test_find_if_container() + { + using namespace boost::assign; + using namespace boost::range_test_function; + + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container_t; + + boost::range_test::range_return_test_driver test_driver; + + container_t mcont; + Container& cont = mcont; + test_driver(cont, make_policy(greater_than_x(5))); + test_driver(cont, make_policy(false_predicate())); + + mcont.clear(); + mcont += 1; + test_driver(cont, make_policy(greater_than_x(5))); + test_driver(cont, make_policy(false_predicate())); + + mcont.clear(); + mcont += 1,2,3,4,5,6,7,8,9; + test_driver(cont, make_policy(greater_than_x(5))); + test_driver(cont, make_policy(false_predicate())); + } + + void test_find_if() + { + test_find_if_container< std::vector >(); + test_find_if_container< std::list >(); + test_find_if_container< std::deque >(); + + test_find_if_container< const std::vector >(); + test_find_if_container< const std::list >(); + test_find_if_container< const std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.find_if" ); + + test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_find_if::test_find_if ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/for_each.cpp b/libs/range/test/algorithm_test/for_each.cpp new file mode 100644 index 00000000..701d676c --- /dev/null +++ b/libs/range/test/algorithm_test/for_each.cpp @@ -0,0 +1,95 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include "../test_function/check_equal_fn.hpp" + +namespace boost +{ + namespace + { + template< class Range > + unsigned int udistance(Range& rng) + { + return static_cast(boost::distance(rng)); + } + + template< class SinglePassRange > + void test_for_each_impl( SinglePassRange rng ) + { + using namespace boost::range_test_function; + + typedef check_equal_fn< SinglePassRange > fn_t; + + // Test the mutable version + fn_t result_fn = boost::for_each(rng, fn_t(rng)); + BOOST_CHECK_EQUAL( boost::udistance(rng), result_fn.invocation_count() ); + + fn_t result_fn2 = boost::for_each(boost::make_iterator_range(rng), fn_t(rng)); + BOOST_CHECK_EQUAL( boost::udistance(rng), result_fn2.invocation_count() ); + + // Test the constant version + const SinglePassRange& cref_rng = rng; + result_fn = boost::for_each(cref_rng, fn_t(cref_rng)); + BOOST_CHECK_EQUAL( boost::udistance(cref_rng), result_fn.invocation_count() ); + } + + template< class Container > + void test_for_each_t() + { + using namespace boost::assign; + + // Test empty + Container cont; + test_for_each_impl(cont); + + // Test one element + cont += 0; + test_for_each_impl(cont); + + // Test many elements + cont += 1,2,3,4,5,6,7,8,9; + test_for_each_impl(cont); + } + + void test_for_each() + { + boost::array a = {{ 0,1,2,3,4,5,6,7,8,9 }}; + test_for_each_impl(a); + + test_for_each_t< std::vector >(); + test_for_each_t< std::list >(); + test_for_each_t< std::set >(); + test_for_each_t< std::multiset >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.for_each" ); + + test->add( BOOST_TEST_CASE( &boost::test_for_each ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/generate.cpp b/libs/range/test/algorithm_test/generate.cpp new file mode 100644 index 00000000..907f9fbd --- /dev/null +++ b/libs/range/test/algorithm_test/generate.cpp @@ -0,0 +1,95 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + class generator_fn + { + public: + typedef int result_type; + + generator_fn() : m_count(0) {} + int operator()() { return ++m_count; } + + private: + int m_count; + }; + + template< class Container > + void test_generate_impl(Container& cont) + { + Container reference(cont); + std::generate(reference.begin(), reference.end(), generator_fn()); + + Container test(cont); + boost::generate(test, generator_fn()); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + Container test2(cont); + boost::generate(boost::make_iterator_range(test2), generator_fn()); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test2.begin(), test2.end() ); + } + + template< class Container > + void test_generate_impl() + { + using namespace boost::assign; + + Container cont; + test_generate_impl(cont); + + cont.clear(); + cont += 9; + test_generate_impl(cont); + + cont.clear(); + cont += 9,8,7,6,5,4,3,2,1; + test_generate_impl(cont); + } + + void test_generate() + { + test_generate_impl< std::vector >(); + test_generate_impl< std::list >(); + test_generate_impl< std::deque >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.generate" ); + + test->add( BOOST_TEST_CASE( &boost::test_generate ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/heap.cpp b/libs/range/test/algorithm_test/heap.cpp new file mode 100644 index 00000000..9c5b7c6e --- /dev/null +++ b/libs/range/test/algorithm_test/heap.cpp @@ -0,0 +1,144 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void check_equal(const Container1& cont1, const Container2& cont2) + { + BOOST_CHECK_EQUAL_COLLECTIONS( + cont1.begin(), cont1.end(), + cont2.begin(), cont2.end() + ); + } + + void test() + { + using namespace boost::assign; + + std::vector reference; + reference += 1,2,3,4,5,6,7,8,9; + + std::vector test_cont(reference); + std::vector test_cont2(reference); + + std::make_heap(reference.begin(), reference.end()); + boost::make_heap(test_cont); + check_equal(reference, test_cont); + boost::make_heap(boost::make_iterator_range(test_cont2)); + check_equal(reference, test_cont2); + + std::push_heap(reference.begin(), reference.end()); + boost::push_heap(test_cont); + check_equal(reference, test_cont); + boost::push_heap(boost::make_iterator_range(test_cont2)); + check_equal(reference, test_cont2); + + std::make_heap(reference.begin(), reference.end()); + boost::make_heap(test_cont); + boost::make_heap(boost::make_iterator_range(test_cont2)); + + std::sort_heap(reference.begin(), reference.end()); + boost::sort_heap(test_cont); + check_equal(reference, test_cont); + boost::sort_heap(boost::make_iterator_range(test_cont2)); + check_equal(reference, test_cont2); + + std::make_heap(reference.begin(), reference.end()); + boost::make_heap(test_cont); + boost::make_heap(boost::make_iterator_range(test_cont2)); + + std::pop_heap(reference.begin(), reference.end()); + boost::pop_heap(test_cont); + check_equal(reference, test_cont); + boost::pop_heap(boost::make_iterator_range(test_cont2)); + check_equal(reference, test_cont2); + } + + template + void test_pred(BinaryPredicate pred) + { + using namespace boost::assign; + + std::vector reference; + reference += 1,2,3,4,5,6,7,8,9; + std::sort(reference.begin(), reference.end(), pred); + + std::vector test_cont(reference); + std::vector test_cont2(reference); + + std::make_heap(reference.begin(), reference.end(), pred); + boost::make_heap(test_cont, pred); + check_equal(reference, test_cont); + boost::make_heap(boost::make_iterator_range(test_cont2), pred); + check_equal(reference, test_cont2); + + reference.push_back(5); + test_cont.push_back(5); + test_cont2.push_back(5); + std::push_heap(reference.begin(), reference.end(), pred); + boost::push_heap(test_cont, pred); + check_equal(reference, test_cont); + boost::push_heap(boost::make_iterator_range(test_cont2), pred); + check_equal(reference, test_cont2); + + std::make_heap(reference.begin(), reference.end(), pred); + boost::make_heap(test_cont, pred); + boost::make_heap(boost::make_iterator_range(test_cont2), pred); + + std::sort_heap(reference.begin(), reference.end(), pred); + boost::sort_heap(test_cont, pred); + check_equal(reference, test_cont); + boost::sort_heap(boost::make_iterator_range(test_cont2), pred); + check_equal(reference, test_cont2); + + std::make_heap(reference.begin(), reference.end(), pred); + boost::make_heap(test_cont, pred); + boost::make_heap(boost::make_iterator_range(test_cont2), pred); + + std::pop_heap(reference.begin(), reference.end(), pred); + boost::pop_heap(test_cont, pred); + check_equal(reference, test_cont); + boost::pop_heap(boost::make_iterator_range(test_cont2), pred); + check_equal(reference, test_cont2); + } + + void test_heap() + { + test(); + test_pred(std::less()); + test_pred(std::greater()); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.heap" ); + + test->add( BOOST_TEST_CASE( &boost::test_heap ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/includes.cpp b/libs/range/test/algorithm_test/includes.cpp new file mode 100644 index 00000000..ce28fac8 --- /dev/null +++ b/libs/range/test/algorithm_test/includes.cpp @@ -0,0 +1,164 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void test(Container1& cont1, Container2& cont2) + { + Container1 old_cont1(cont1); + Container2 old_cont2(cont2); + + bool reference_result + = std::includes(cont1.begin(), cont1.end(), + cont2.begin(), cont2.end()); + + bool test_result = boost::includes(cont1, cont2); + + BOOST_CHECK( reference_result == test_result ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + old_cont1.begin(), old_cont1.end(), + cont1.begin(), cont1.end() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + old_cont2.begin(), old_cont2.end(), + cont2.begin(), cont2.end() + ); + + BOOST_CHECK( test_result == boost::includes(boost::make_iterator_range(cont1), cont2) ); + BOOST_CHECK( test_result == boost::includes(cont1, boost::make_iterator_range(cont2)) ); + BOOST_CHECK( test_result == boost::includes(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2)) ); + } + + template + void sort_container(Container& cont, BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector temp(cont.begin(), cont.end()); + std::sort(temp.begin(), temp.end(), pred); + cont.assign(temp.begin(), temp.end()); + } + + template + void test_pred(Container1 cont1, Container2 cont2, + BinaryPredicate pred) + { + sort_container(cont1, pred); + sort_container(cont2, pred); + + Container1 old_cont1(cont1); + Container2 old_cont2(cont2); + + bool reference_result + = std::includes(cont1.begin(), cont1.end(), + cont2.begin(), cont2.end(), + pred); + + bool test_result = boost::includes(cont1, cont2, pred); + + BOOST_CHECK( reference_result == test_result ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + old_cont1.begin(), old_cont1.end(), + cont1.begin(), cont1.end() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + old_cont2.begin(), old_cont2.end(), + cont2.begin(), cont2.end() + ); + + BOOST_CHECK( test_result == boost::includes(boost::make_iterator_range(cont1), cont2, pred) ); + BOOST_CHECK( test_result == boost::includes(cont1, boost::make_iterator_range(cont2), pred) ); + BOOST_CHECK( test_result == boost::includes(boost::make_iterator_range(cont1), boost::make_iterator_range(cont2), pred) ); + } + + template + void test_includes_impl( + Container1& cont1, + Container2& cont2 + ) + { + test(cont1, cont2); + test_pred(cont1, cont2, std::less()); + test_pred(cont1, cont2, std::greater()); + } + + template + void test_includes_impl() + { + using namespace boost::assign; + + Container1 cont1; + Container2 cont2; + + test_includes_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1; + test_includes_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont2 += 1; + test_includes_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1,2,3,4,5,6,7,8,9; + cont2 += 2,3,4; + test_includes_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 2,3,4; + cont2 += 1,2,3,4,5,6,7,8,9; + test_includes_impl(cont1, cont2); + } + + void test_includes() + { + test_includes_impl< std::vector, std::vector >(); + test_includes_impl< std::list, std::list >(); + test_includes_impl< std::deque, std::deque >(); + test_includes_impl< std::vector, std::list >(); + test_includes_impl< std::list, std::vector >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.includes" ); + + test->add( BOOST_TEST_CASE( &boost::test_includes ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/inplace_merge.cpp b/libs/range/test/algorithm_test/inplace_merge.cpp new file mode 100644 index 00000000..3b2082a4 --- /dev/null +++ b/libs/range/test/algorithm_test/inplace_merge.cpp @@ -0,0 +1,166 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void test(Container1& cont1, Container2& cont2) + { + typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; + + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator + iterator_t BOOST_RANGE_UNUSED; + + std::vector reference_target(cont1.begin(), cont1.end()); + reference_target.insert(reference_target.end(), + cont2.begin(), cont2.end()); + + std::vector test_target(reference_target); + std::vector test_target2(reference_target); + + std::inplace_merge(reference_target.begin(), + reference_target.begin() + cont1.size(), + reference_target.end()); + + boost::inplace_merge(test_target, + test_target.begin() + cont1.size()); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference_target.begin(), reference_target.end(), + test_target.begin(), test_target.end() + ); + + boost::inplace_merge(boost::make_iterator_range(test_target2), + test_target2.begin() + cont1.size()); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference_target.begin(), reference_target.end(), + test_target2.begin(), test_target2.end() + ); + } + + template + void sort_container(Container& cont, BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector temp(cont.begin(), cont.end()); + std::sort(temp.begin(), temp.end(), pred); + cont.assign(temp.begin(), temp.end()); + } + + template + void test_pred(Container1 cont1, Container2 cont2, BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator + iterator_t BOOST_RANGE_UNUSED; + + sort_container(cont1, pred); + sort_container(cont2, pred); + + std::vector reference_target(cont1.begin(), cont1.end()); + reference_target.insert(reference_target.end(), + cont2.begin(), cont2.end()); + + std::vector test_target(reference_target); + std::vector test_target2(reference_target); + + std::inplace_merge(reference_target.begin(), + reference_target.begin() + cont1.size(), + reference_target.end(), pred); + + boost::inplace_merge(test_target, + test_target.begin() + cont1.size(), + pred); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference_target.begin(), reference_target.end(), + test_target.begin(), test_target.end() + ); + + boost::inplace_merge(boost::make_iterator_range(test_target2), + test_target2.begin() + cont1.size(), + pred); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference_target.begin(), reference_target.end(), + test_target2.begin(), test_target2.end() + ); + } + + template + void test_inplace_merge_impl(Container1& cont1, Container2& cont2) + { + test(cont1, cont2); + test_pred(cont1, cont2, std::less()); + test_pred(cont1, cont2, std::greater()); + } + + template + void test_inplace_merge_impl() + { + using namespace boost::assign; + + Container1 cont1; + Container2 cont2; + + test_inplace_merge_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1; + test_inplace_merge_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont2 += 1; + test_inplace_merge_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1,3,5,7,9,11,13,15,17,19; + cont2 += 2,4,6,8,10,12,14,16,18,20; + test_inplace_merge_impl(cont1, cont2); + } + + void test_inplace_merge() + { + test_inplace_merge_impl< std::vector, std::vector >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.inplace_merge" ); + + test->add( BOOST_TEST_CASE( &boost::test_inplace_merge ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/lexicographical_compare.cpp b/libs/range/test/algorithm_test/lexicographical_compare.cpp new file mode 100644 index 00000000..f724bd1e --- /dev/null +++ b/libs/range/test/algorithm_test/lexicographical_compare.cpp @@ -0,0 +1,157 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void test_lexicographical_compare_impl_nopred(ForwardRange1& rng1, + ForwardRange2& rng2) + { + const bool reference = std::lexicographical_compare( + boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2)); + + const bool test = boost::lexicographical_compare(rng1, rng2); + + BOOST_CHECK( reference == test ); + BOOST_CHECK( test == boost::lexicographical_compare(boost::make_iterator_range(rng1), rng2) ); + BOOST_CHECK( test == boost::lexicographical_compare(rng1, boost::make_iterator_range(rng2)) ); + BOOST_CHECK( test == boost::lexicographical_compare(boost::make_iterator_range(rng1), boost::make_iterator_range(rng2)) ); + } + + template + void test_lexicographical_compare_impl_pred(ForwardRange1& rng1, + ForwardRange2& rng2, + BinaryPredicate pred) + { + const bool reference = std::lexicographical_compare( + boost::begin(rng1), boost::end(rng1), + boost::begin(rng2), boost::end(rng2), + pred); + + const bool test = boost::lexicographical_compare(rng1, rng2, pred); + + BOOST_CHECK( reference == test ); + BOOST_CHECK( test == boost::lexicographical_compare(boost::make_iterator_range(rng1), rng2, pred) ); + BOOST_CHECK( test == boost::lexicographical_compare(rng1, boost::make_iterator_range(rng2), pred) ); + BOOST_CHECK( test == boost::lexicographical_compare(boost::make_iterator_range(rng1), boost::make_iterator_range(rng2), pred) ); + } + + template + void test_lexicographical_compare_impl(Container1& cont1, + Container2& cont2) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_value::type value_t; + + test_lexicographical_compare_impl_nopred(cont1, cont2); + test_lexicographical_compare_impl_pred(cont1, cont2, std::less()); + test_lexicographical_compare_impl_pred(cont1, cont2, std::greater()); + } + + template + void test_lexicographical_compare_impl() + { + using namespace boost::assign; + + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container1_t; + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container2_t; + + container1_t cont1; + container2_t cont2; + test_lexicographical_compare_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1.push_back(1); + cont2.push_back(1); + test_lexicographical_compare_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 2; + cont2 += 1; + test_lexicographical_compare_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1; + cont2 += 2; + test_lexicographical_compare_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1,2,3,4,5,6,7; + cont2 += 1,2,3,4,5,6,7; + test_lexicographical_compare_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1,2,3,4,5,6,7; + cont2 += 1,2,3,4,5,6; + test_lexicographical_compare_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1,2,3,4,5,6; + cont2 += 1,2,3,4,5,6,7; + test_lexicographical_compare_impl(cont1, cont2); + } + + template + void test_lexicographical_compare_rhs() + { + typedef BOOST_DEDUCED_TYPENAME range_value::type value_t; + + test_lexicographical_compare_impl >(); + test_lexicographical_compare_impl >(); + test_lexicographical_compare_impl >(); + test_lexicographical_compare_impl >(); + test_lexicographical_compare_impl >(); + test_lexicographical_compare_impl >(); + } + + void test_lexicographical_compare() + { + test_lexicographical_compare_rhs< const std::vector >(); + test_lexicographical_compare_rhs< const std::deque >(); + test_lexicographical_compare_rhs< const std::list >(); + test_lexicographical_compare_rhs< std::vector >(); + test_lexicographical_compare_rhs< std::deque >(); + test_lexicographical_compare_rhs< std::list >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.lexicographical_compare" ); + + test->add( BOOST_TEST_CASE( &boost::test_lexicographical_compare ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/lower_bound.cpp b/libs/range/test/algorithm_test/lower_bound.cpp new file mode 100644 index 00000000..d4b18cf3 --- /dev/null +++ b/libs/range/test/algorithm_test/lower_bound.cpp @@ -0,0 +1,180 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include "../test_driver/range_return_test_driver.hpp" +#include +#include +#include +#include +#include +#include + +namespace boost_range_test_algorithm_lower_bound +{ + class lower_bound_policy + { + public: + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::lower_bound(cont, 5); + BOOST_CHECK( result == boost::lower_bound(boost::make_iterator_range(cont), 5) ); + return result; + } + + template + struct test_range + { + template + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy&, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + result_t result = boost::lower_bound(cont, 5); + BOOST_CHECK( result == boost::lower_bound(boost::make_iterator_range(cont), 5) ); + return result; + } + }; + + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::lower_bound(cont.begin(), cont.end(), 5); + } + }; + + template< class BinaryPredicate > + struct lower_bound_pred_policy + { + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::lower_bound(cont, 5, m_pred); + BOOST_CHECK( result == boost::lower_bound( + boost::make_iterator_range(cont), 5, m_pred) ); + return result; + } + + template< boost::range_return_value return_type > + struct test_range + { + template + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + result_t result = boost::lower_bound(cont, 5, policy.pred()); + BOOST_CHECK( result == boost::lower_bound( + boost::make_iterator_range(cont), 5, policy.pred()) ); + return result; + } + }; + + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::lower_bound( + cont.begin(), cont.end(), 5, m_pred); + } + + BinaryPredicate& pred() { return m_pred; } + + private: + BinaryPredicate m_pred; + }; + + template + void test_lower_bound_impl(TestPolicy policy, BinaryPredicate pred) + { + using namespace boost::assign; + + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container_t; + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + boost::range_test::range_return_test_driver test_driver; + + container_t mcont; + Container& cont = mcont; + + test_driver(cont, policy); + + mcont.clear(); + mcont += 1; + + std::vector temp(mcont.begin(), mcont.end()); + std::sort(temp.begin(), temp.end(), pred); + mcont.assign(temp.begin(), temp.end()); + + test_driver(cont, policy); + + mcont.clear(); + mcont += 1,2,3,4,5,6,7,8,9; + + temp.assign(mcont.begin(), mcont.end()); + std::sort(temp.begin(), temp.end(), pred); + mcont.assign(temp.begin(), temp.end()); + + test_driver(cont, policy); + } + + template + void test_lower_bound_impl() + { + test_lower_bound_impl( + lower_bound_policy(), + std::less() + ); + + test_lower_bound_impl( + lower_bound_pred_policy >(), + std::less() + ); + + test_lower_bound_impl( + lower_bound_pred_policy >(), + std::greater() + ); + } + + void test_lower_bound() + { + test_lower_bound_impl< std::vector >(); + test_lower_bound_impl< std::list >(); + test_lower_bound_impl< std::deque >(); + + test_lower_bound_impl< const std::vector >(); + test_lower_bound_impl< const std::list >(); + test_lower_bound_impl< const std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.lower_bound" ); + + test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_lower_bound::test_lower_bound ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/max_element.cpp b/libs/range/test/algorithm_test/max_element.cpp new file mode 100644 index 00000000..f6092a2c --- /dev/null +++ b/libs/range/test/algorithm_test/max_element.cpp @@ -0,0 +1,164 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include "../test_driver/range_return_test_driver.hpp" +#include +#include +#include +#include +#include +#include + +namespace boost_range_test_algorithm_max_element +{ + class max_element_test_policy + { + public: + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::max_element(cont); + BOOST_CHECK( result == boost::max_element( + boost::make_iterator_range(cont)) ); + return result; + } + + template + struct test_range + { + template + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy&, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + result_t result = boost::max_element(cont); + BOOST_CHECK( result == boost::max_element( + boost::make_iterator_range(cont)) ); + return result; + } + }; + + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::max_element(cont.begin(), cont.end()); + } + }; + + template + class max_element_pred_test_policy + { + public: + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::max_element(cont, Pred()); + BOOST_CHECK( result == boost::max_element( + boost::make_iterator_range(cont), Pred()) ); + return result; + } + + Pred pred() const { return Pred(); } + + template< boost::range_return_value return_type > + struct test_range + { + template< class Container, class Policy > + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + result_t result = boost::max_element(cont, policy.pred()); + BOOST_CHECK( result == boost::max_element( + boost::make_iterator_range(cont), policy.pred()) ); + return result; + } + }; + + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::max_element(cont.begin(), cont.end(), Pred()); + } + }; + + template + void test_max_element_impl(TestPolicy policy) + { + using namespace boost::assign; + + typedef BOOST_DEDUCED_TYPENAME Container::value_type + value_t BOOST_RANGE_UNUSED; + + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type + container_t; + + boost::range_test::range_return_test_driver test_driver; + + container_t cont; + + test_driver(cont, policy); + + cont.clear(); + cont += 1; + + test_driver(cont, policy); + + cont.clear(); + cont += 1,2,2,2,3,4,5,6,7,8,9; + + test_driver(cont, policy); + } + + template + void test_max_element_impl() + { + test_max_element_impl(max_element_test_policy()); + + test_max_element_impl( + max_element_pred_test_policy >()); + + test_max_element_impl( + max_element_pred_test_policy >()); + } + + void test_max_element() + { + test_max_element_impl< const std::vector >(); + test_max_element_impl< const std::deque >(); + test_max_element_impl< const std::list >(); + + test_max_element_impl< std::vector >(); + test_max_element_impl< std::deque >(); + test_max_element_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.max_element" ); + + test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_max_element::test_max_element ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/merge.cpp b/libs/range/test/algorithm_test/merge.cpp new file mode 100644 index 00000000..b173019e --- /dev/null +++ b/libs/range/test/algorithm_test/merge.cpp @@ -0,0 +1,236 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void test(Container1& cont1, Container2& cont2) + { + typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + + std::vector reference_target( cont1.size() + cont2.size() ); + + iterator_t reference_it + = std::merge(cont1.begin(), cont1.end(), + cont2.begin(), cont2.end(), + reference_target.begin()); + + std::vector test_target( cont1.size() + cont2.size() ); + + iterator_t test_it + = boost::merge(cont1, cont2, test_target.begin()); + + BOOST_CHECK_EQUAL( + std::distance(reference_target.begin(), reference_it), + std::distance(test_target.begin(), test_it) + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference_target.begin(), reference_target.end(), + test_target.begin(), test_target.end() + ); + + test_it = boost::merge(boost::make_iterator_range(cont1), + cont2, test_target.begin()); + + BOOST_CHECK_EQUAL( + std::distance(reference_target.begin(), reference_it), + std::distance(test_target.begin(), test_it) + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference_target.begin(), reference_target.end(), + test_target.begin(), test_target.end() + ); + + test_it = boost::merge(cont1, boost::make_iterator_range(cont2), + test_target.begin()); + + BOOST_CHECK_EQUAL( + std::distance(reference_target.begin(), reference_it), + std::distance(test_target.begin(), test_it) + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference_target.begin(), reference_target.end(), + test_target.begin(), test_target.end() + ); + + test_it = boost::merge(boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2), + test_target.begin()); + + BOOST_CHECK_EQUAL( + std::distance(reference_target.begin(), reference_it), + std::distance(test_target.begin(), test_it) + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference_target.begin(), reference_target.end(), + test_target.begin(), test_target.end() + ); + } + + template + void sort_container(Container& cont, BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector temp(cont.begin(), cont.end()); + std::sort(temp.begin(), temp.end(), pred); + cont.assign(temp.begin(), temp.end()); + } + + template + void test_pred(Container1 cont1, Container2 cont2, BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + + sort_container(cont1, pred); + sort_container(cont2, pred); + + std::vector reference_target( cont1.size() + cont2.size() ); + + iterator_t reference_it + = std::merge(cont1.begin(), cont1.end(), + cont2.begin(), cont2.end(), + reference_target.begin(), pred); + + std::vector test_target( cont1.size() + cont2.size() ); + + iterator_t test_it + = boost::merge(cont1, cont2, test_target.begin(), pred); + + BOOST_CHECK_EQUAL( + std::distance(reference_target.begin(), reference_it), + std::distance(test_target.begin(), test_it) + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference_target.begin(), reference_target.end(), + test_target.begin(), test_target.end() + ); + + test_it = boost::merge(boost::make_iterator_range(cont1), cont2, + test_target.begin(), pred); + + BOOST_CHECK_EQUAL( + std::distance(reference_target.begin(), reference_it), + std::distance(test_target.begin(), test_it) + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference_target.begin(), reference_target.end(), + test_target.begin(), test_target.end() + ); + + test_it = boost::merge(cont1, boost::make_iterator_range(cont2), + test_target.begin(), pred); + + BOOST_CHECK_EQUAL( + std::distance(reference_target.begin(), reference_it), + std::distance(test_target.begin(), test_it) + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference_target.begin(), reference_target.end(), + test_target.begin(), test_target.end() + ); + + test_it = boost::merge(boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2), + test_target.begin(), pred); + + BOOST_CHECK_EQUAL( + std::distance(reference_target.begin(), reference_it), + std::distance(test_target.begin(), test_it) + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference_target.begin(), reference_target.end(), + test_target.begin(), test_target.end() + ); + } + + template + void test_merge_impl(Container1& cont1, Container2& cont2) + { + test(cont1, cont2); + test_pred(cont1, cont2, std::less()); + test_pred(cont1, cont2, std::greater()); + } + + template + void test_merge_impl() + { + using namespace boost::assign; + + Container1 cont1; + Container2 cont2; + + test_merge_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1; + test_merge_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont2 += 1; + test_merge_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1,3,5,7,9,11,13,15,17,19; + cont2 += 2,4,6,8,10,12,14,16,18,20; + test_merge_impl(cont1, cont2); + } + + void test_merge() + { + test_merge_impl< std::vector, std::vector >(); + test_merge_impl< std::list, std::list >(); + test_merge_impl< std::deque, std::deque >(); + + test_merge_impl< std::list, std::vector >(); + test_merge_impl< std::vector, std::list >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.merge" ); + + test->add( BOOST_TEST_CASE( &boost::test_merge ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/min_element.cpp b/libs/range/test/algorithm_test/min_element.cpp new file mode 100644 index 00000000..b545f667 --- /dev/null +++ b/libs/range/test/algorithm_test/min_element.cpp @@ -0,0 +1,162 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include "../test_driver/range_return_test_driver.hpp" +#include +#include +#include +#include +#include +#include + +namespace boost_range_test_algorithm_min_element +{ + class min_element_test_policy + { + public: + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::min_element(cont); + BOOST_CHECK( result == boost::min_element(boost::make_iterator_range(cont)) ); + return result; + } + + template< boost::range_return_value return_type > + struct test_range + { + template< class Container, class Policy > + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy&, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + result_t result = boost::min_element(cont); + BOOST_CHECK( result == boost::min_element(boost::make_iterator_range(cont)) ); + return result; + } + }; + + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::min_element(cont.begin(), cont.end()); + } + }; + + template + class min_element_pred_test_policy + { + public: + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::min_element(cont, Pred()); + BOOST_CHECK( result == boost::min_element( + boost::make_iterator_range(cont), Pred()) ); + return result; + } + + Pred pred() const { return Pred(); } + + template< boost::range_return_value return_type > + struct test_range + { + template< class Container, class Policy > + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + result_t result = boost::min_element(cont, policy.pred()); + BOOST_CHECK( result == boost::min_element( + boost::make_iterator_range(cont), policy.pred()) ); + return result; + } + }; + + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::min_element(cont.begin(), cont.end(), Pred()); + } + }; + + template + void test_min_element_impl(TestPolicy policy) + { + using namespace boost::assign; + + typedef BOOST_DEDUCED_TYPENAME Container::value_type + value_t BOOST_RANGE_UNUSED; + + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type + container_t; + + boost::range_test::range_return_test_driver test_driver; + + container_t cont; + + test_driver(cont, policy); + + cont.clear(); + cont += 1; + + test_driver(cont, policy); + + cont.clear(); + cont += 1,2,2,2,3,4,5,6,7,8,9; + + test_driver(cont, policy); + } + + template + void test_min_element_impl() + { + test_min_element_impl(min_element_test_policy()); + + test_min_element_impl( + min_element_pred_test_policy >()); + + test_min_element_impl( + min_element_pred_test_policy >()); + } + + void test_min_element() + { + test_min_element_impl< const std::vector >(); + test_min_element_impl< const std::deque >(); + test_min_element_impl< const std::list >(); + + test_min_element_impl< std::vector >(); + test_min_element_impl< std::deque >(); + test_min_element_impl< std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.min_element" ); + + test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_min_element::test_min_element ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/mismatch.cpp b/libs/range/test/algorithm_test/mismatch.cpp new file mode 100644 index 00000000..407b5fcb --- /dev/null +++ b/libs/range/test/algorithm_test/mismatch.cpp @@ -0,0 +1,242 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container1, class Container2 > + void eval_mismatch(Container1& cont1, + Container2& cont2, + BOOST_DEDUCED_TYPENAME range_iterator::type ref_it1, + BOOST_DEDUCED_TYPENAME range_iterator::type ref_it2 + ) + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iter1_t; + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iter2_t; + typedef std::pair result_pair_t; + + result_pair_t result = boost::mismatch(cont1, cont2); + BOOST_CHECK( result.first == ref_it1 ); + BOOST_CHECK( result.second == ref_it2 ); + + result = boost::mismatch(boost::make_iterator_range(cont1), + cont2); + BOOST_CHECK( result.first == ref_it1 ); + BOOST_CHECK( result.second == ref_it2 ); + + result = boost::mismatch(cont1, + boost::make_iterator_range(cont2)); + BOOST_CHECK( result.first == ref_it1 ); + BOOST_CHECK( result.second == ref_it2 ); + + result = boost::mismatch(boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2)); + BOOST_CHECK( result.first == ref_it1 ); + BOOST_CHECK( result.second == ref_it2 ); + } + + template< class Container1, class Container2, class Pred > + void eval_mismatch(Container1& cont1, + Container2& cont2, + Pred pred, + BOOST_DEDUCED_TYPENAME range_iterator::type ref_it1, + BOOST_DEDUCED_TYPENAME range_iterator::type ref_it2 + ) + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iter1_t; + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iter2_t; + typedef std::pair result_pair_t; + + result_pair_t result = boost::mismatch(cont1, cont2, pred); + BOOST_CHECK( result.first == ref_it1 ); + BOOST_CHECK( result.second == ref_it2 ); + + result = boost::mismatch(boost::make_iterator_range(cont1), + cont2, pred); + BOOST_CHECK( result.first == ref_it1 ); + BOOST_CHECK( result.second == ref_it2 ); + + result = boost::mismatch(cont1, + boost::make_iterator_range(cont2), pred); + BOOST_CHECK( result.first == ref_it1 ); + BOOST_CHECK( result.second == ref_it2 ); + + result = boost::mismatch(boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2), + pred); + BOOST_CHECK( result.first == ref_it1 ); + BOOST_CHECK( result.second == ref_it2 ); + } + + template< class Container1, class Container2 > + void eval_mismatch(Container1& cont1, + Container2& cont2, + const int ref1, + const int ref2) + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iter1_t; + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iter2_t; + typedef std::pair result_pair_t; + + result_pair_t result = boost::mismatch(cont1, cont2); + BOOST_CHECK_EQUAL( ref1, *result.first ); + BOOST_CHECK_EQUAL( ref2, *result.second ); + + result = boost::mismatch(boost::make_iterator_range(cont1), cont2); + BOOST_CHECK_EQUAL( ref1, *result.first ); + BOOST_CHECK_EQUAL( ref2, *result.second ); + + result = boost::mismatch(cont1, boost::make_iterator_range(cont2)); + BOOST_CHECK_EQUAL( ref1, *result.first ); + BOOST_CHECK_EQUAL( ref2, *result.second ); + + result = boost::mismatch(boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2)); + BOOST_CHECK_EQUAL( ref1, *result.first ); + BOOST_CHECK_EQUAL( ref2, *result.second ); + } + + template< class Container1, class Container2, class Pred > + void eval_mismatch(Container1& cont1, + Container2& cont2, + Pred pred, + const int ref1, + const int ref2) + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iter1_t; + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iter2_t; + typedef std::pair result_pair_t; + + result_pair_t result = boost::mismatch(cont1, cont2, pred); + BOOST_CHECK_EQUAL( ref1, *result.first ); + BOOST_CHECK_EQUAL( ref2, *result.second ); + + result = boost::mismatch(boost::make_iterator_range(cont1), + cont2, pred); + BOOST_CHECK_EQUAL( ref1, *result.first ); + BOOST_CHECK_EQUAL( ref2, *result.second ); + + result = boost::mismatch(cont1, boost::make_iterator_range(cont2), + pred); + BOOST_CHECK_EQUAL( ref1, *result.first ); + BOOST_CHECK_EQUAL( ref2, *result.second ); + + result = boost::mismatch(boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2), + pred); + BOOST_CHECK_EQUAL( ref1, *result.first ); + BOOST_CHECK_EQUAL( ref2, *result.second ); + } + + template< class Container1, class Container2 > + void test_mismatch_impl() + { + using namespace boost::assign; + + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type MutableContainer1; + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type MutableContainer2; + + MutableContainer1 cont1; + const Container1& cref_cont1 = cont1; + MutableContainer2 cont2; + const Container2& cref_cont2 = cont2; + + typedef BOOST_DEDUCED_TYPENAME Container1::iterator + iterator1_t BOOST_RANGE_UNUSED; + + typedef BOOST_DEDUCED_TYPENAME Container1::const_iterator + const_iterator1_t BOOST_RANGE_UNUSED; + + typedef BOOST_DEDUCED_TYPENAME Container2::iterator + iterator2_t BOOST_RANGE_UNUSED; + + typedef BOOST_DEDUCED_TYPENAME Container2::const_iterator + const_iterator2_t BOOST_RANGE_UNUSED; + + eval_mismatch(cont1, cont2, cont1.end(), cont2.end()); + eval_mismatch(cont1, cont2, std::equal_to(), cont1.end(), cont2.end()); + eval_mismatch(cref_cont1, cont2, cref_cont1.end(), cont2.end()); + eval_mismatch(cref_cont1, cont2, std::equal_to(), cref_cont1.end(), cont2.end()); + eval_mismatch(cont1, cref_cont2, cont1.end(), cref_cont2.end()); + eval_mismatch(cont1, cref_cont2, std::equal_to(), cont1.end(), cref_cont2.end()); + eval_mismatch(cref_cont1, cref_cont2, cref_cont1.end(), cref_cont2.end()); + eval_mismatch(cref_cont1, cref_cont2, std::equal_to(), cref_cont1.end(), cref_cont2.end()); + + cont1 += 1,2,3,4; + cont2 += 1,2,3,4; + eval_mismatch(cont1, cont2, cont1.end(), cont2.end()); + eval_mismatch(cont1, cont2, std::equal_to(), cont1.end(), cont2.end()); + eval_mismatch(cref_cont1, cont2, cref_cont1.end(), cont2.end()); + eval_mismatch(cref_cont1, cont2, std::equal_to(), cref_cont1.end(), cont2.end()); + eval_mismatch(cont1, cref_cont2, cont1.end(), cref_cont2.end()); + eval_mismatch(cont1, cref_cont2, std::equal_to(), cont1.end(), cref_cont2.end()); + eval_mismatch(cref_cont1, cref_cont2, cref_cont1.end(), cref_cont2.end()); + eval_mismatch(cref_cont1, cref_cont2, std::equal_to(), cref_cont1.end(), cref_cont2.end()); + + cont1.clear(); + cont2.clear(); + cont1 += 1,2,3,4; + cont2 += 1,2,5,4; + eval_mismatch(cont1, cont2, 3, 5); + eval_mismatch(cont1, cont2, std::equal_to(), 3, 5); + eval_mismatch(cont1, cont2, std::not_equal_to(), cont1.begin(), cont2.begin()); + eval_mismatch(cref_cont1, cont2, 3, 5); + eval_mismatch(cref_cont1, cont2, std::equal_to(), 3, 5); + eval_mismatch(cref_cont1, cont2, std::not_equal_to(), cref_cont1.begin(), cont2.begin()); + eval_mismatch(cont1, cref_cont2, 3, 5); + eval_mismatch(cont1, cref_cont2, std::equal_to(), 3, 5); + eval_mismatch(cont1, cref_cont2, std::not_equal_to(), cont1.begin(), cref_cont2.begin()); + eval_mismatch(cref_cont1, cref_cont2, 3, 5); + eval_mismatch(cref_cont1, cref_cont2, std::equal_to(), 3, 5); + eval_mismatch(cref_cont1, cref_cont2, std::not_equal_to(), cref_cont1.begin(), cref_cont2.begin()); + } + + void test_mismatch() + { + test_mismatch_impl< std::list, std::list >(); + test_mismatch_impl< const std::list, std::list >(); + test_mismatch_impl< std::list, const std::list >(); + test_mismatch_impl< const std::list, const std::list >(); + + test_mismatch_impl< std::vector, std::list >(); + test_mismatch_impl< const std::vector, std::list >(); + test_mismatch_impl< std::vector, const std::list >(); + test_mismatch_impl< const std::vector, const std::list >(); + + test_mismatch_impl< std::list, std::vector >(); + test_mismatch_impl< const std::list, std::vector >(); + test_mismatch_impl< std::list, const std::vector >(); + test_mismatch_impl< const std::list, const std::vector >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.mismatch" ); + + test->add( BOOST_TEST_CASE( &boost::test_mismatch ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/next_permutation.cpp b/libs/range/test/algorithm_test/next_permutation.cpp new file mode 100644 index 00000000..ee1c3716 --- /dev/null +++ b/libs/range/test/algorithm_test/next_permutation.cpp @@ -0,0 +1,125 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void test_next_permutation_impl(const Container& cont) + { + Container reference(cont); + Container test(cont); + + const bool reference_ret + = std::next_permutation(reference.begin(), reference.end()); + + const bool test_ret = boost::next_permutation(test); + + BOOST_CHECK( reference_ret == test_ret ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + + test = cont; + + BOOST_CHECK( test_ret == boost::next_permutation(boost::make_iterator_range(test)) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + } + + template + void test_next_permutation_pred_impl(const Container& cont, + BinaryPredicate pred) + { + Container reference(cont); + Container test(cont); + + const bool reference_ret + = std::next_permutation(reference.begin(), reference.end(), + pred); + + const bool test_ret + = boost::next_permutation(test, pred); + + BOOST_CHECK( reference_ret == test_ret ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + + test = cont; + + BOOST_CHECK( test_ret == boost::next_permutation(boost::make_iterator_range(test), pred) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + } + + template + void test_next_permutation_(const Container& cont) + { + test_next_permutation_impl(cont); + test_next_permutation_pred_impl(cont, std::less()); + test_next_permutation_pred_impl(cont, std::greater()); + } + + template + void run_tests() + { + using namespace boost::assign; + + Container cont; + test_next_permutation_(cont); + + cont.clear(); + cont += 1; + test_next_permutation_(cont); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_next_permutation_(cont); + } + + void test_next_permutation() + { + run_tests< std::vector >(); + run_tests< std::list >(); + run_tests< std::deque >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.next_permutation" ); + + test->add( BOOST_TEST_CASE( &boost::test_next_permutation ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/nth_element.cpp b/libs/range/test/algorithm_test/nth_element.cpp new file mode 100644 index 00000000..044e663b --- /dev/null +++ b/libs/range/test/algorithm_test/nth_element.cpp @@ -0,0 +1,174 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + struct nth_element_policy + { + template + void test_nth_element(Container& cont, Iterator mid) + { + const Container old_cont(cont); + + boost::nth_element(cont, mid); + + // Test the same operation on the container, for the + // case where a temporary is passed as the first + // argument. + Container cont2(old_cont); + const std::size_t index = std::distance(cont.begin(), mid); + Iterator mid2(cont2.begin()); + std::advance(mid2, index); + boost::nth_element(boost::make_iterator_range(cont2), mid2); + + BOOST_CHECK_EQUAL_COLLECTIONS( cont.begin(), cont.end(), + cont2.begin(), cont2.end() ); + } + + template + void reference_nth_element(Container& cont, Iterator mid) + { + std::nth_element(cont.begin(), mid, cont.end()); + } + }; + + template + struct nth_element_pred_policy + { + template + void test_nth_element(Container& cont, Iterator mid) + { + const Container old_cont(cont); + + boost::nth_element(cont, mid, BinaryPredicate()); + + Container cont2(old_cont); + const std::size_t index = std::distance(cont.begin(), mid); + Iterator mid2(cont2.begin()); + std::advance(mid2, index); + boost::nth_element(boost::make_iterator_range(cont2), mid2, + BinaryPredicate()); + + BOOST_CHECK_EQUAL_COLLECTIONS( cont.begin(), cont.end(), + cont2.begin(), cont2.end() ); + } + + template + void reference_nth_element(Container& cont, Iterator mid) + { + std::nth_element(cont.begin(), mid, cont.end(), BinaryPredicate()); + } + }; + + template + void test_nth_element_tp_impl(Container& cont, TestPolicy policy) + { + Container reference(cont); + Container test(cont); + + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; + + BOOST_CHECK_EQUAL( reference.size(), test.size() ); + if (reference.size() != test.size()) + return; + + iterator_t reference_mid = reference.begin(); + iterator_t test_mid = test.begin(); + + bool complete = false; + while (!complete) + { + if (reference_mid == reference.end()) + complete = true; + + policy.test_nth_element(test, test_mid); + policy.reference_nth_element(reference, reference_mid); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + + if (reference_mid != reference.end()) + { + ++reference_mid; + ++test_mid; + } + } + } + + template + void test_nth_element_impl(Container& cont) + { + test_nth_element_tp_impl(cont, nth_element_policy()); + } + + template + void test_nth_element_impl(Container& cont, BinaryPredicate pred) + { + test_nth_element_tp_impl(cont, nth_element_pred_policy()); + } + + template + void run_tests(Container& cont) + { + test_nth_element_impl(cont); + test_nth_element_impl(cont, std::less()); + test_nth_element_impl(cont, std::greater()); + } + + template + void test_nth_element_impl() + { + using namespace boost::assign; + + Container cont; + run_tests(cont); + + cont.clear(); + cont += 1; + run_tests(cont); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + run_tests(cont); + } + + void test_nth_element() + { + test_nth_element_impl< std::vector >(); + test_nth_element_impl< std::deque >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.nth_element" ); + + test->add( BOOST_TEST_CASE( &boost::test_nth_element ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/partial_sort.cpp b/libs/range/test/algorithm_test/partial_sort.cpp new file mode 100644 index 00000000..5fb26867 --- /dev/null +++ b/libs/range/test/algorithm_test/partial_sort.cpp @@ -0,0 +1,170 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + struct partial_sort_policy + { + template + void test_partial_sort(Container& cont, Iterator mid) + { + const Container old_cont(cont); + + boost::partial_sort(cont, mid); + + const std::size_t index = std::distance(cont.begin(), mid); + Container cont2(old_cont); + Iterator mid2(cont2.begin()); + std::advance(mid2, index); + boost::partial_sort(cont2, mid2); + + BOOST_CHECK_EQUAL_COLLECTIONS( cont.begin(), cont.end(), + cont2.begin(), cont2.end() ); + } + + template + void reference_partial_sort(Container& cont, Iterator mid) + { + std::partial_sort(cont.begin(), mid, cont.end()); + } + }; + + template + struct partial_sort_pred_policy + { + template + void test_partial_sort(Container& cont, Iterator mid) + { + const Container old_cont(cont); + + boost::partial_sort(cont, mid, BinaryPredicate()); + + const std::size_t index = std::distance(cont.begin(), mid); + Container cont2(old_cont); + Iterator mid2(cont2.begin()); + std::advance(mid2, index); + boost::partial_sort(cont2, mid2, BinaryPredicate()); + + BOOST_CHECK_EQUAL_COLLECTIONS( cont.begin(), cont.end(), + cont2.begin(), cont2.end() ); + } + + template + void reference_partial_sort(Container& cont, Iterator mid) + { + std::partial_sort(cont.begin(), mid, cont.end(), BinaryPredicate()); + } + }; + + template + void test_partial_sort_tp_impl(Container& cont, TestPolicy policy) + { + Container reference(cont); + Container test(cont); + + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; + + BOOST_CHECK_EQUAL( reference.size(), test.size() ); + if (reference.size() != test.size()) + return; + + iterator_t reference_mid = reference.begin(); + iterator_t test_mid = test.begin(); + + bool complete = false; + while (!complete) + { + if (reference_mid == reference.end()) + complete = true; + + policy.test_partial_sort(test, test_mid); + policy.reference_partial_sort(reference, reference_mid); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + + if (reference_mid != reference.end()) + { + ++reference_mid; + ++test_mid; + } + } + } + + template + void test_partial_sort_impl(Container& cont) + { + test_partial_sort_tp_impl(cont, partial_sort_policy()); + } + + template + void test_partial_sort_impl(Container& cont, BinaryPredicate pred) + { + test_partial_sort_tp_impl(cont, partial_sort_pred_policy()); + } + + template + void test_partial_sort_impl() + { + using namespace boost::assign; + + Container cont; + test_partial_sort_impl(cont); + test_partial_sort_impl(cont, std::less()); + test_partial_sort_impl(cont, std::greater()); + + cont.clear(); + cont += 1; + test_partial_sort_impl(cont); + test_partial_sort_impl(cont, std::less()); + test_partial_sort_impl(cont, std::greater()); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_partial_sort_impl(cont); + test_partial_sort_impl(cont, std::less()); + test_partial_sort_impl(cont, std::greater()); + } + + void test_partial_sort() + { + test_partial_sort_impl< std::vector >(); + test_partial_sort_impl< std::deque >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.partial_sort" ); + + test->add( BOOST_TEST_CASE( &boost::test_partial_sort ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/partition.cpp b/libs/range/test/algorithm_test/partition.cpp new file mode 100644 index 00000000..bdc45083 --- /dev/null +++ b/libs/range/test/algorithm_test/partition.cpp @@ -0,0 +1,135 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include "../test_driver/range_return_test_driver.hpp" +#include +#include +#include +#include +#include +#include + +namespace boost_range_test_algorithm_partition +{ + struct equal_to_5 + { + typedef bool result_type; + typedef int argument_type; + bool operator()(int x) const { return x == 5; } + }; + + // test the 'partition' algorithm + template + class partition_test_policy + { + public: + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + + const Container old_cont(cont); + Container cont2(old_cont); + iter_t result = boost::partition(cont, UnaryPredicate()); + + boost::partition(cont2, UnaryPredicate()); + cont2 = old_cont; + boost::partition( + boost::make_iterator_range(cont2), UnaryPredicate()); + + BOOST_CHECK_EQUAL_COLLECTIONS( cont.begin(), cont.end(), + cont2.begin(), cont2.end() ); + + return result; + } + + UnaryPredicate pred() const { return UnaryPredicate(); } + + template< boost::range_return_value return_type > + struct test_range + { + template< class Container, class Policy > + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + + const Container old_cont(cont); + Container cont2(old_cont); + result_t result = boost::partition(cont, policy.pred()); + + // Test that operation a temporary created by using + // make_iterator_range. + boost::partition( + boost::make_iterator_range(cont2), policy.pred()); + + BOOST_CHECK_EQUAL_COLLECTIONS( cont.begin(), cont.end(), + cont2.begin(), cont2.end() ); + + return result; + } + }; + + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::partition(cont.begin(), cont.end(), UnaryPredicate()); + } + }; + + template + void test_partition_impl() + { + using namespace boost::assign; + + boost::range_test::range_return_test_driver test_driver; + + partition_test_policy< equal_to_5 > policy; + + Container cont; + test_driver(cont, policy); + + cont.clear(); + cont += 1; + test_driver(cont, policy); + + cont.clear(); + cont += 1,2,2,2,2,2,3,4,5,6,7,8,9; + test_driver(cont, policy); + + cont.clear(); + cont += 1,2,2,2,2,2,3,3,3,3,4,4,4,4,4,4,4,5,6,7,8,9; + test_driver(cont, policy); + } + + void test_partition() + { + test_partition_impl< std::vector >(); + test_partition_impl< std::list >(); + test_partition_impl< std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.partition" ); + + test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_partition::test_partition ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/prev_permutation.cpp b/libs/range/test/algorithm_test/prev_permutation.cpp new file mode 100644 index 00000000..a4adc7b3 --- /dev/null +++ b/libs/range/test/algorithm_test/prev_permutation.cpp @@ -0,0 +1,124 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void test_prev_permutation_impl(const Container& cont) + { + Container reference(cont); + Container test(cont); + Container test2(cont); + + const bool reference_ret + = std::prev_permutation(reference.begin(), reference.end()); + + const bool test_ret = boost::prev_permutation(test); + + BOOST_CHECK( reference_ret == test_ret ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + + BOOST_CHECK( test_ret == boost::prev_permutation( + boost::make_iterator_range(test2)) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test2.begin(), test2.end() + ); + } + + template + void test_prev_permutation_pred_impl(const Container& cont, + BinaryPredicate pred) + { + Container reference(cont); + Container test(cont); + Container test2(cont); + + const bool reference_ret + = std::prev_permutation(reference.begin(), reference.end(), + pred); + + const bool test_ret = boost::prev_permutation(test, pred); + + BOOST_CHECK( reference_ret == test_ret ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + + BOOST_CHECK( test_ret == boost::prev_permutation( + boost::make_iterator_range(test2), pred) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test2.begin(), test2.end() + ); + } + + template + void test_prev_permutation_(const Container& cont) + { + test_prev_permutation_impl(cont); + test_prev_permutation_pred_impl(cont, std::less()); + test_prev_permutation_pred_impl(cont, std::greater()); + } + + template + void run_tests() + { + using namespace boost::assign; + + Container cont; + test_prev_permutation_(cont); + + cont.clear(); + cont += 1; + test_prev_permutation_(cont); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_prev_permutation_(cont); + } + + void test_prev_permutation() + { + run_tests< std::vector >(); + run_tests< std::list >(); + run_tests< std::deque >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.prev_permutation" ); + + test->add( BOOST_TEST_CASE( &boost::test_prev_permutation ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/random_shuffle.cpp b/libs/range/test/algorithm_test/random_shuffle.cpp new file mode 100644 index 00000000..6b3db1e2 --- /dev/null +++ b/libs/range/test/algorithm_test/random_shuffle.cpp @@ -0,0 +1,197 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include "../test_function/counted_function.hpp" +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + class counted_generator + : private range_test_function::counted_function + { + public: + typedef Int result_type; + typedef Int argument_type; + + using range_test_function::counted_function::invocation_count; + + result_type operator()(argument_type modulo_value) + { + invoked(); + return static_cast(std::rand() % modulo_value); + } + }; + + template + bool test_shuffle_result( + const Container& old_cont, + const Container& new_cont + ) + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; + + // The size must remain equal + BOOST_CHECK_EQUAL( old_cont.size(), new_cont.size() ); + if (old_cont.size() != new_cont.size()) + return false; + + if (new_cont.size() < 2) + { + BOOST_CHECK_EQUAL_COLLECTIONS( + old_cont.begin(), old_cont.end(), + new_cont.begin(), new_cont.end() + ); + + return std::equal(old_cont.begin(), old_cont.end(), + new_cont.begin()); + } + + // Elements must only be moved around. This is tested by + // ensuring the count of each element remains the + // same. + bool failed = false; + iterator_t last = old_cont.end(); + for (iterator_t it = old_cont.begin(); !failed && (it != last); ++it) + { + const std::size_t old_count + = std::count(old_cont.begin(), old_cont.end(), *it); + + const std::size_t new_count + = std::count(new_cont.begin(), new_cont.end(), *it); + + BOOST_CHECK_EQUAL( old_count, new_count ); + + failed = (old_count != new_count); + } + + return !failed; + } + + template + void test_random_shuffle_nogen_impl(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type + iterator_t BOOST_RANGE_UNUSED; + + const int MAX_RETRIES = 10000; + + bool shuffled = false; + for (int attempt = 0; !shuffled && (attempt < MAX_RETRIES); ++attempt) + { + Container test(cont); + boost::random_shuffle(test); + bool ok = test_shuffle_result(cont, test); + if (!ok) + break; + + // Since the counts are equal, then if they are + // not equal the contents must have been shuffled + if (cont.size() == test.size() + && !std::equal(cont.begin(), cont.end(), test.begin())) + { + shuffled = true; + } + + // Verify that the shuffle can be performed on a + // temporary range + Container test2(cont); + boost::random_shuffle(boost::make_iterator_range(test2)); + ok = test_shuffle_result(cont, test2); + if (!ok) + break; + } + } + + template + void test_random_shuffle_gen_impl(Container& cont) + { + RandomGenerator gen; + Container old_cont(cont); + boost::random_shuffle(cont, gen); + test_shuffle_result(cont, old_cont); + if (cont.size() > 2) + { + BOOST_CHECK( gen.invocation_count() > 0 ); + } + + // Test that random shuffle works when + // passed a temporary range + RandomGenerator gen2; + Container cont2(old_cont); + boost::random_shuffle(boost::make_iterator_range(cont2), gen2); + test_shuffle_result(cont2, old_cont); + if (cont2.size() > 2) + { + BOOST_CHECK( gen2.invocation_count() > 0 ); + } + } + + template + void test_random_shuffle_impl(Container& cont) + { + Container old_cont(cont); + boost::random_shuffle(cont); + test_shuffle_result(cont, old_cont); + } + + template + void test_random_shuffle_impl() + { + using namespace boost::assign; + + typedef counted_generator< + BOOST_DEDUCED_TYPENAME range_difference::type > generator_t; + + Container cont; + test_random_shuffle_nogen_impl(cont); + test_random_shuffle_gen_impl(cont); + + cont.clear(); + cont += 1; + test_random_shuffle_nogen_impl(cont); + test_random_shuffle_gen_impl(cont); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_random_shuffle_nogen_impl(cont); + test_random_shuffle_gen_impl(cont); + } + + void test_random_shuffle() + { + test_random_shuffle_impl< std::vector >(); + test_random_shuffle_impl< std::deque >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.random_shuffle" ); + + test->add( BOOST_TEST_CASE( &boost::test_random_shuffle ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/remove.cpp b/libs/range/test/algorithm_test/remove.cpp new file mode 100644 index 00000000..8312d9fd --- /dev/null +++ b/libs/range/test/algorithm_test/remove.cpp @@ -0,0 +1,100 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container, class Value > + void test_remove_impl( const Container& c, Value to_remove ) + { + Container reference(c); + + typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator_t; + + iterator_t reference_it + = std::remove(reference.begin(), reference.end(), to_remove); + + Container test(c); + iterator_t test_it = boost::remove(test, to_remove); + + BOOST_CHECK_EQUAL( std::distance(test.begin(), test_it), + std::distance(reference.begin(), reference_it) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + Container test2(c); + iterator_t test_it2 = boost::remove(test2, to_remove); + + BOOST_CHECK_EQUAL( std::distance(test2.begin(), test_it2), + std::distance(reference.begin(), reference_it) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test2.begin(), test2.end() ); + } + + template< class Container > + void test_remove_impl() + { + using namespace boost::assign; + + Container cont; + test_remove_impl(cont, 0); + + cont.clear(); + cont += 1; + test_remove_impl(cont, 0); + test_remove_impl(cont, 1); + + cont.clear(); + cont += 1,1,1,1,1; + test_remove_impl(cont, 0); + test_remove_impl(cont, 1); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_remove_impl(cont, 1); + test_remove_impl(cont, 9); + test_remove_impl(cont, 4); + } + + void test_remove() + { + test_remove_impl< std::vector >(); + test_remove_impl< std::list >(); + test_remove_impl< std::deque >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.remove" ); + + test->add( BOOST_TEST_CASE( &boost::test_remove ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/remove_copy.cpp b/libs/range/test/algorithm_test/remove_copy.cpp new file mode 100644 index 00000000..3065d9e3 --- /dev/null +++ b/libs/range/test/algorithm_test/remove_copy.cpp @@ -0,0 +1,107 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + template + void test_append(Iterator target, Value value) + { + *target++ = value; + } + + template< class Container, class Value > + void test_remove_copy_impl( const Container& c, Value to_remove ) + { + typedef typename boost::range_value::type value_type; + std::vector reference; + + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator + iterator_t BOOST_RANGE_UNUSED; + + test_append( + std::remove_copy(c.begin(), c.end(), + std::back_inserter(reference), to_remove), + to_remove); + + std::vector test; + test_append( + boost::remove_copy(c, std::back_inserter(test), to_remove), + to_remove); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + std::vector test2; + test_append( + boost::remove_copy(boost::make_iterator_range(c), + std::back_inserter(test2), to_remove), + to_remove); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test2.begin(), test2.end() ); + } + + template< class Container > + void test_remove_copy_impl() + { + using namespace boost::assign; + + Container cont; + test_remove_copy_impl(cont, 0); + + cont.clear(); + cont += 1; + test_remove_copy_impl(cont, 0); + test_remove_copy_impl(cont, 1); + + cont.clear(); + cont += 1,1,1,1,1; + test_remove_copy_impl(cont, 0); + test_remove_copy_impl(cont, 1); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_remove_copy_impl(cont, 1); + test_remove_copy_impl(cont, 9); + test_remove_copy_impl(cont, 4); + } + + void test_remove_copy() + { + test_remove_copy_impl< std::vector >(); + test_remove_copy_impl< std::list >(); + test_remove_copy_impl< std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.remove_copy" ); + + test->add( BOOST_TEST_CASE( &test_remove_copy ) ); + + return test; +} + diff --git a/libs/range/test/algorithm_test/remove_copy_if.cpp b/libs/range/test/algorithm_test/remove_copy_if.cpp new file mode 100644 index 00000000..8a5d2aeb --- /dev/null +++ b/libs/range/test/algorithm_test/remove_copy_if.cpp @@ -0,0 +1,115 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + template< class Iterator, class Value > + void test_append(Iterator target, Value value) + { + *target++ = value; + } + + template< class Container, class UnaryPredicate > + void test_remove_copy_if_impl( const Container& c, UnaryPredicate pred ) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_value::type value_type; + std::vector reference; + + test_append( + std::remove_copy_if(c.begin(), c.end(), std::back_inserter(reference), pred), + value_type() + ); + + std::vector test; + test_append( + boost::remove_copy_if(c, std::back_inserter(test), pred), + value_type() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + std::vector test2; + test_append( + boost::remove_copy_if(boost::make_iterator_range(c), + std::back_inserter(test2), pred), + value_type() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test2.begin(), test2.end() ); + } + + template< class Container > + void test_remove_copy_if_( const Container& c, int to_remove ) + { + using namespace boost::placeholders; + + test_remove_copy_if_impl(c, boost::bind(std::equal_to(), _1, to_remove)); + test_remove_copy_if_impl(c, boost::bind(std::not_equal_to(), _1, to_remove)); + } + + template< class Container > + void test_remove_copy_if_impl() + { + using namespace boost::assign; + + Container cont; + test_remove_copy_if_(cont, 0); + + cont.clear(); + cont += 1; + test_remove_copy_if_(cont, 0); + test_remove_copy_if_(cont, 1); + + cont.clear(); + cont += 1,1,1,1,1; + test_remove_copy_if_(cont, 0); + test_remove_copy_if_(cont, 1); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_remove_copy_if_(cont, 1); + test_remove_copy_if_(cont, 9); + test_remove_copy_if_(cont, 4); + } + + inline void test_remove_copy_if() + { + test_remove_copy_if_impl< std::vector >(); + test_remove_copy_if_impl< std::list >(); + test_remove_copy_if_impl< std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.remove_copy_if" ); + + test->add( BOOST_TEST_CASE( &test_remove_copy_if ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/remove_if.cpp b/libs/range/test/algorithm_test/remove_if.cpp new file mode 100644 index 00000000..226e74d4 --- /dev/null +++ b/libs/range/test/algorithm_test/remove_if.cpp @@ -0,0 +1,111 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container, class UnaryPredicate > + void test_remove_if_impl( const Container& c, UnaryPredicate pred ) + { + Container reference(c); + + typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator_t; + + iterator_t reference_it + = std::remove_if(reference.begin(), reference.end(), pred); + + Container test(c); + iterator_t test_it = boost::remove_if(test, pred); + + BOOST_CHECK_EQUAL( std::distance(test.begin(), test_it), + std::distance(reference.begin(), reference_it) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + Container test2(c); + iterator_t test_it2 = boost::remove_if( + boost::make_iterator_range(test2), pred); + + BOOST_CHECK_EQUAL( std::distance(test2.begin(), test_it2), + std::distance(reference.begin(), reference_it) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test2.begin(), test2.end() ); + } + + template< class Container > + void test_remove_if_( const Container& c, int to_remove ) + { + using namespace boost::placeholders; + + test_remove_if_impl(c, boost::bind(std::equal_to(), _1, to_remove)); + test_remove_if_impl(c, boost::bind(std::not_equal_to(), _1, to_remove)); + } + + template< class Container > + void test_remove_if_impl() + { + using namespace boost::assign; + + Container cont; + test_remove_if_(cont, 0); + + cont.clear(); + cont += 1; + test_remove_if_(cont, 0); + test_remove_if_(cont, 1); + + cont.clear(); + cont += 1,1,1,1,1; + test_remove_if_(cont, 0); + test_remove_if_(cont, 1); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_remove_if_(cont, 1); + test_remove_if_(cont, 9); + test_remove_if_(cont, 4); + } + + inline void test_remove_if() + { + test_remove_if_impl< std::vector >(); + test_remove_if_impl< std::list >(); + test_remove_if_impl< std::deque >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.remove_if" ); + + test->add( BOOST_TEST_CASE( &boost::test_remove_if ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/replace.cpp b/libs/range/test/algorithm_test/replace.cpp new file mode 100644 index 00000000..356024ff --- /dev/null +++ b/libs/range/test/algorithm_test/replace.cpp @@ -0,0 +1,86 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void test_replace_impl(Container& cont) + { + const int what = 2; + const int with_what = 5; + + std::vector reference(cont.begin(), cont.end()); + std::replace(reference.begin(), reference.end(), what, with_what); + + std::vector target(cont.begin(), cont.end()); + boost::replace(target, what, with_what); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target.begin(), target.end() ); + + std::vector target2(cont.begin(), cont.end()); + boost::replace(boost::make_iterator_range(target2), what, + with_what); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target2.begin(), target2.end() ); + + } + + template< class Container > + void test_replace_impl() + { + using namespace boost::assign; + + Container cont; + test_replace_impl(cont); + + cont.clear(); + cont += 1; + test_replace_impl(cont); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_replace_impl(cont); + } + + void test_replace() + { + test_replace_impl< std::vector >(); + test_replace_impl< std::list >(); + test_replace_impl< std::deque >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.replace" ); + + test->add( BOOST_TEST_CASE( &boost::test_replace ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/replace_copy.cpp b/libs/range/test/algorithm_test/replace_copy.cpp new file mode 100644 index 00000000..7d0ccd5f --- /dev/null +++ b/libs/range/test/algorithm_test/replace_copy.cpp @@ -0,0 +1,110 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + template + void test_append(Iterator target, Value value) + { + *target++ = value; + } + + template< class Container, class Value > + void test_replace_copy_impl( const Container& c, Value to_replace ) + { + const Value replace_with = to_replace * 2; + + typedef typename boost::range_value::type value_type; + std::vector reference; + + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator + iterator_t BOOST_RANGE_UNUSED; + + test_append( + std::replace_copy(c.begin(), c.end(), + std::back_inserter(reference), to_replace, replace_with), + to_replace); + + std::vector test; + test_append( + boost::replace_copy(c, std::back_inserter(test), to_replace, replace_with), + to_replace); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + std::vector test2; + test_append( + boost::replace_copy(boost::make_iterator_range(c), + std::back_inserter(test2), to_replace, + replace_with), + to_replace); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test2.begin(), test2.end() ); + } + + template< class Container > + void test_replace_copy_impl() + { + using namespace boost::assign; + + Container cont; + test_replace_copy_impl(cont, 0); + + cont.clear(); + cont += 1; + test_replace_copy_impl(cont, 0); + test_replace_copy_impl(cont, 1); + + cont.clear(); + cont += 1,1,1,1,1; + test_replace_copy_impl(cont, 0); + test_replace_copy_impl(cont, 1); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_replace_copy_impl(cont, 1); + test_replace_copy_impl(cont, 9); + test_replace_copy_impl(cont, 4); + } + + void test_replace_copy() + { + test_replace_copy_impl< std::vector >(); + test_replace_copy_impl< std::list >(); + test_replace_copy_impl< std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.replace_copy" ); + + test->add( BOOST_TEST_CASE( &test_replace_copy ) ); + + return test; +} + diff --git a/libs/range/test/algorithm_test/replace_copy_if.cpp b/libs/range/test/algorithm_test/replace_copy_if.cpp new file mode 100644 index 00000000..af342567 --- /dev/null +++ b/libs/range/test/algorithm_test/replace_copy_if.cpp @@ -0,0 +1,117 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + template< class Iterator, class Value > + void test_append(Iterator target, Value value) + { + *target++ = value; + } + + template< class Container, class UnaryPredicate > + void test_replace_copy_if_impl( const Container& c, UnaryPredicate pred ) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_value::type value_type; + const value_type replace_with = value_type(); + std::vector reference; + + test_append( + std::replace_copy_if(c.begin(), c.end(), std::back_inserter(reference), pred, replace_with), + value_type() + ); + + std::vector test; + test_append( + boost::replace_copy_if(c, std::back_inserter(test), pred, replace_with), + value_type() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + std::vector test2; + test_append( + boost::replace_copy_if(boost::make_iterator_range(c), + std::back_inserter(test2), pred, + replace_with), + value_type() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test2.begin(), test2.end() ); + } + + template< class Container > + void test_replace_copy_if_( const Container& c, int to_replace ) + { + using namespace boost::placeholders; + + test_replace_copy_if_impl(c, boost::bind(std::equal_to(), _1, to_replace)); + test_replace_copy_if_impl(c, boost::bind(std::not_equal_to(), _1, to_replace)); + } + + template< class Container > + void test_replace_copy_if_impl() + { + using namespace boost::assign; + + Container cont; + test_replace_copy_if_(cont, 0); + + cont.clear(); + cont += 1; + test_replace_copy_if_(cont, 0); + test_replace_copy_if_(cont, 1); + + cont.clear(); + cont += 1,1,1,1,1; + test_replace_copy_if_(cont, 0); + test_replace_copy_if_(cont, 1); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_replace_copy_if_(cont, 1); + test_replace_copy_if_(cont, 9); + test_replace_copy_if_(cont, 4); + } + + inline void test_replace_copy_if() + { + test_replace_copy_if_impl< std::vector >(); + test_replace_copy_if_impl< std::list >(); + test_replace_copy_if_impl< std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.replace_copy_if" ); + + test->add( BOOST_TEST_CASE( &test_replace_copy_if ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/replace_if.cpp b/libs/range/test/algorithm_test/replace_if.cpp new file mode 100644 index 00000000..ecd3a743 --- /dev/null +++ b/libs/range/test/algorithm_test/replace_if.cpp @@ -0,0 +1,98 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container, class UnaryPredicate > + void test_replace_if_impl(Container& cont, UnaryPredicate pred) + { + using namespace boost::placeholders; + + const int what = 2; + const int with_what = 5; + + std::vector reference(cont.begin(), cont.end()); + std::replace_if(reference.begin(), reference.end(), + boost::bind(pred, _1, what), with_what); + + std::vector target(cont.begin(), cont.end()); + boost::replace_if(target, boost::bind(pred, _1, what), with_what); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target.begin(), target.end() ); + + std::vector target2(cont.begin(), cont.end()); + boost::replace_if(boost::make_iterator_range(target2), + boost::bind(pred, _1, what), with_what); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target2.begin(), target2.end() ); + } + + template< class Container > + void test_replace_if_impl(Container& cont) + { + test_replace_if_impl(cont, std::equal_to()); + test_replace_if_impl(cont, std::not_equal_to()); + } + + template< class Container > + void test_replace_if_impl() + { + using namespace boost::assign; + + Container cont; + test_replace_if_impl(cont); + + cont.clear(); + cont += 1; + test_replace_if_impl(cont); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_replace_if_impl(cont); + } + + void test_replace_if() + { + test_replace_if_impl< std::vector >(); + test_replace_if_impl< std::list >(); + test_replace_if_impl< std::deque >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.replace_if" ); + + test->add( BOOST_TEST_CASE( &boost::test_replace_if ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/reverse.cpp b/libs/range/test/algorithm_test/reverse.cpp new file mode 100644 index 00000000..08ca2c58 --- /dev/null +++ b/libs/range/test/algorithm_test/reverse.cpp @@ -0,0 +1,79 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void test_reverse_impl(Container& cont) + { + Container reference(cont); + Container test(cont); + Container test2(cont); + + boost::reverse(test); + std::reverse(reference.begin(), reference.end()); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + boost::reverse(boost::make_iterator_range(test2)); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test2.begin(), test2.end() ); + } + + template + void test_reverse_impl() + { + using namespace boost::assign; + + Container cont; + test_reverse_impl(cont); + + cont.clear(); + cont += 1; + test_reverse_impl(cont); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_reverse_impl(cont); + } + + void test_reverse() + { + test_reverse_impl< std::vector >(); + test_reverse_impl< std::list >(); + test_reverse_impl< std::deque >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.reverse" ); + + test->add( BOOST_TEST_CASE( &boost::test_reverse ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/reverse_copy.cpp b/libs/range/test/algorithm_test/reverse_copy.cpp new file mode 100644 index 00000000..8edfcda4 --- /dev/null +++ b/libs/range/test/algorithm_test/reverse_copy.cpp @@ -0,0 +1,96 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + template + void test_append(OutputIterator out, Value value) + { + *out++ = value; + } + + template + void test_reverse_copy_impl(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_value::type value_type; + std::vector reference; + std::vector test; + + test_append( + std::reverse_copy(cont.begin(), cont.end(), std::back_inserter(reference)), + value_type() + ); + + test_append( + boost::reverse_copy(cont, std::back_inserter(test)), + value_type() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + test.clear(); + + test_append( + boost::reverse_copy(boost::make_iterator_range(cont), + std::back_inserter(test)), + value_type() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + template + void test_reverse_copy_impl() + { + using namespace boost::assign; + + Container cont; + test_reverse_copy_impl(cont); + + cont.clear(); + cont += 1; + test_reverse_copy_impl(cont); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_reverse_copy_impl(cont); + } + + void test_reverse_copy() + { + test_reverse_copy_impl< std::vector >(); + test_reverse_copy_impl< std::list >(); + test_reverse_copy_impl< std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.reverse_copy" ); + + test->add( BOOST_TEST_CASE( &::test_reverse_copy ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/rotate.cpp b/libs/range/test/algorithm_test/rotate.cpp new file mode 100644 index 00000000..6b487d7d --- /dev/null +++ b/libs/range/test/algorithm_test/rotate.cpp @@ -0,0 +1,106 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void test_rotate_impl(Container& cont, Iterator where_it) + { + Container reference(cont); + Container test(cont); + + Iterator reference_where_it = reference.begin(); + std::advance(reference_where_it, + std::distance(cont.begin(), where_it)); + + std::rotate(reference.begin(), reference_where_it, reference.end()); + + Iterator test_where_it = test.begin(); + std::advance(test_where_it, + std::distance(cont.begin(), where_it)); + + boost::rotate(test, test_where_it); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + test = cont; + test_where_it = test.begin(); + std::advance(test_where_it, + std::distance(cont.begin(), where_it)); + + boost::rotate(boost::make_iterator_range(test), test_where_it); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + template + void test_rotate_impl(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; + + iterator_t last = cont.end(); + for (iterator_t it = cont.begin(); it != last; ++it) + { + test_rotate_impl(cont, it); + } + } + + template + void test_rotate_impl() + { + using namespace boost::assign; + + Container cont; + test_rotate_impl(cont); + + cont.clear(); + cont += 1; + test_rotate_impl(cont); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_rotate_impl(cont); + } + + void test_rotate() + { + test_rotate_impl< std::vector >(); + test_rotate_impl< std::list >(); + test_rotate_impl< std::deque >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.rotate" ); + + test->add( BOOST_TEST_CASE( &boost::test_rotate ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/rotate_copy.cpp b/libs/range/test/algorithm_test/rotate_copy.cpp new file mode 100644 index 00000000..7f43fc0c --- /dev/null +++ b/libs/range/test/algorithm_test/rotate_copy.cpp @@ -0,0 +1,114 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + template + void test_append(OutputIterator target, Value value) + { + *target++ = value; + } + + template + void test_rotate_copy_impl(Container& cont, Iterator where_it) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_value::type + value_type; + + std::vector reference; + std::vector test; + + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type + iterator_t BOOST_RANGE_UNUSED; + + test_append( + std::rotate_copy(cont.begin(), where_it, cont.end(), + std::back_inserter(reference)), + value_type() + ); + + test_append( + boost::rotate_copy(cont, where_it, std::back_inserter(test)), + value_type() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + test.clear(); + + test_append( + boost::rotate_copy(boost::make_iterator_range(cont), where_it, + std::back_inserter(test)), + value_type() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + template + void test_rotate_copy_impl(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iterator_t; + + iterator_t last = cont.end(); + for (iterator_t it = cont.begin(); it != last; ++it) + { + test_rotate_copy_impl(cont, it); + } + } + + template + void test_rotate_copy_impl() + { + using namespace boost::assign; + + Container cont; + test_rotate_copy_impl(cont); + + cont.clear(); + cont += 1; + test_rotate_copy_impl(cont); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_rotate_copy_impl(cont); + } + + void test_rotate_copy() + { + test_rotate_copy_impl< std::vector >(); + test_rotate_copy_impl< std::list >(); + test_rotate_copy_impl< std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.rotate_copy" ); + + test->add( BOOST_TEST_CASE( &test_rotate_copy ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/search.cpp b/libs/range/test/algorithm_test/search.cpp new file mode 100644 index 00000000..91f19bd6 --- /dev/null +++ b/libs/range/test/algorithm_test/search.cpp @@ -0,0 +1,113 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container1, class Container2 > + void test_search_impl(Container1& cont1, Container2& cont2) + { + typedef BOOST_DEDUCED_TYPENAME Container1::const_iterator const_iterator1_t; + typedef BOOST_DEDUCED_TYPENAME Container1::iterator iterator1_t; + + const Container1& ccont1 = cont1; + const Container2& ccont2 = cont2; + + iterator1_t it = boost::search(cont1, cont2); + BOOST_CHECK( it == boost::search(boost::make_iterator_range(cont1), cont2) ); + BOOST_CHECK( it == boost::search(cont1, boost::make_iterator_range(cont2)) ); + BOOST_CHECK( it == boost::search(boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2)) ); + iterator1_t it2 = boost::search(cont1, ccont2); + BOOST_CHECK( it2 == boost::search(boost::make_iterator_range(cont1), ccont2) ); + BOOST_CHECK( it2 == boost::search(cont1, boost::make_iterator_range(ccont2)) ); + BOOST_CHECK( it2 == boost::search(boost::make_iterator_range(cont1), + boost::make_iterator_range(ccont2)) ); + const_iterator1_t cit = boost::search(ccont1, cont2); + BOOST_CHECK( cit == boost::search(boost::make_iterator_range(ccont1), cont2) ); + BOOST_CHECK( cit == boost::search(ccont1, boost::make_iterator_range(cont2)) ); + BOOST_CHECK( cit == boost::search(boost::make_iterator_range(ccont1), + boost::make_iterator_range(cont2)) ); + const_iterator1_t cit2 = boost::search(ccont1, ccont2); + BOOST_CHECK( cit2 == boost::search(boost::make_iterator_range(ccont1), ccont2) ); + BOOST_CHECK( cit2 == boost::search(ccont1, boost::make_iterator_range(ccont2)) ); + BOOST_CHECK( cit2 == boost::search(boost::make_iterator_range(ccont1), + boost::make_iterator_range(ccont2)) ); + + BOOST_CHECK( it == std::search(cont1.begin(), cont1.end(), cont2.begin(), cont2.end()) ); + BOOST_CHECK( it2 == std::search(cont1.begin(), cont1.end(), ccont2.begin(), ccont2.end()) ); + BOOST_CHECK( cit == std::search(ccont1.begin(), ccont1.end(), cont2.begin(), cont2.end()) ); + BOOST_CHECK( cit2 == std::search(ccont1.begin(), ccont1.end(), ccont2.begin(), ccont2.end()) ); + } + + template< class Container1, class Container2 > + void test_search_impl() + { + using namespace boost::assign; + + Container1 cont1; + Container2 cont2; + + test_search_impl(cont1, cont2); + + cont1 += 1; + test_search_impl(cont1, cont2); + + cont1.clear(); + cont2 += 1; + test_search_impl(cont1, cont2); + + cont1 += 1; + test_search_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1,2,3,4,5,6,7,8,9; + cont2 += 10,11,12; + test_search_impl(cont1, cont2); + + cont2.clear(); + cont2 += 4,5,6; + test_search_impl(cont1, cont2); + } + + void test_search() + { + test_search_impl< std::list, std::list >(); + test_search_impl< std::vector, std::vector >(); + test_search_impl< std::set, std::set >(); + test_search_impl< std::list, std::vector >(); + test_search_impl< std::vector, std::list >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.search" ); + + test->add( BOOST_TEST_CASE( &boost::test_search ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/search_n.cpp b/libs/range/test/algorithm_test/search_n.cpp new file mode 100644 index 00000000..76f5b784 --- /dev/null +++ b/libs/range/test/algorithm_test/search_n.cpp @@ -0,0 +1,198 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include + +namespace +{ + template + inline ForwardIterator + reference_search_n(ForwardIterator first, ForwardIterator last, + Integer count, const Value& value) + { + if (count <= 0) + return first; + else if (count == 1) + return std::find(first, last, value); + else + { + first = std::find(first, last, value); + while (first != last) + { + typename std::iterator_traits::difference_type n = count; + ForwardIterator i = first; + ++i; + while (i != last && n != 1 && *i==value) + { + ++i; + --n; + } + if (n == 1) + return first; + if (i == last) + return last; + first = std::find(++i, last, value); + } + } + return last; + } + + template + inline ForwardIterator + reference_search_n(ForwardIterator first, ForwardIterator last, + Integer count, const Value& value, + BinaryPredicate pred) + { + typedef typename std::iterator_traits< + ForwardIterator + >::iterator_category cat_t BOOST_RANGE_UNUSED; + + if (count <= 0) + return first; + if (count == 1) + { + while (first != last && !static_cast(pred(*first, value))) + ++first; + return first; + } + else + { + typedef typename std::iterator_traits::difference_type difference_t; + + while (first != last && !static_cast(pred(*first, value))) + ++first; + + while (first != last) + { + difference_t n = count; + ForwardIterator i = first; + ++i; + while (i != last && n != 1 && static_cast(pred(*i, value))) + { + ++i; + --n; + } + if (n == 1) + return first; + if (i == last) + return last; + first = ++i; + while (first != last && !static_cast(pred(*first, value))) + ++first; + } + } + return last; + } + + template< class Container1, class Value, class Pred > + void test_search_n_pred_impl(Container1& cont1, Value value, Pred pred) + { + typedef BOOST_DEDUCED_TYPENAME Container1::const_iterator const_iterator1_t; + typedef BOOST_DEDUCED_TYPENAME Container1::iterator iterator1_t; + + const Container1& ccont1 = cont1; + + for (std::size_t n = 0; n < cont1.size(); ++n) + { + iterator1_t it = boost::search_n(cont1, n, value, pred); + BOOST_CHECK( it == boost::search_n(boost::make_iterator_range(cont1), n, value, pred) ); + BOOST_CHECK( it == reference_search_n(cont1.begin(), cont1.end(), n, value, pred) ); + + const_iterator1_t cit = boost::search_n(ccont1, n, value, pred); + BOOST_CHECK( cit == boost::search_n(boost::make_iterator_range(ccont1), n, value, pred) ); + BOOST_CHECK( cit == reference_search_n(ccont1.begin(), ccont1.end(), n, value, pred) ); + } + } + + template< class Container1, class Value > + void test_search_n_impl(Container1& cont1, Value value) + { + typedef BOOST_DEDUCED_TYPENAME Container1::const_iterator const_iterator1_t; + typedef BOOST_DEDUCED_TYPENAME Container1::iterator iterator1_t; + + const Container1& ccont1 = cont1; + + for (std::size_t n = 0; n < cont1.size(); ++n) + { + iterator1_t it = boost::search_n(cont1, n, value); + BOOST_CHECK( it == boost::search_n(boost::make_iterator_range(cont1), n, value) ); + BOOST_CHECK( it == reference_search_n(cont1.begin(), cont1.end(), n, value) ); + + const_iterator1_t cit = boost::search_n(ccont1, n, value); + BOOST_CHECK( cit == boost::search_n(boost::make_iterator_range(ccont1), n, value) ); + BOOST_CHECK( cit == reference_search_n(ccont1.begin(), ccont1.end(), n, value) ); + } + + test_search_n_pred_impl(cont1, value, std::less()); + test_search_n_pred_impl(cont1, value, std::greater()); + test_search_n_pred_impl(cont1, value, std::equal_to()); + test_search_n_pred_impl(cont1, value, std::not_equal_to()); + } + + template< class Container1, class Container2 > + void test_search_n_impl() + { + using namespace boost::assign; + + Container1 cont1; + + test_search_n_impl(cont1, 1); + + cont1 += 1; + test_search_n_impl(cont1, 1); + test_search_n_impl(cont1, 0); + + cont1.clear(); + cont1 += 1,1; + test_search_n_impl(cont1, 1); + test_search_n_impl(cont1, 0); + + cont1 += 1,1,1; + test_search_n_impl(cont1, 1); + test_search_n_impl(cont1, 0); + + cont1.clear(); + cont1 += 1,2,3,4,5,6,7,8,9; + test_search_n_impl(cont1, 1); + test_search_n_impl(cont1, 2); + test_search_n_impl(cont1, 5); + test_search_n_impl(cont1, 9); + } + + void test_search_n() + { + test_search_n_impl< std::list, std::list >(); + test_search_n_impl< std::vector, std::vector >(); + test_search_n_impl< std::set, std::set >(); + test_search_n_impl< std::list, std::vector >(); + test_search_n_impl< std::vector, std::list >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.search_n" ); + + test->add( BOOST_TEST_CASE( &test_search_n ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/set_difference.cpp b/libs/range/test/algorithm_test/set_difference.cpp new file mode 100644 index 00000000..303fd58f --- /dev/null +++ b/libs/range/test/algorithm_test/set_difference.cpp @@ -0,0 +1,213 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void check_result( + Container1& reference, + Iterator reference_result, + Container2& test_cont, + Iterator test_result + ) + { + BOOST_CHECK_EQUAL( + std::distance(reference.begin(), reference_result), + std::distance(test_cont.begin(), test_result) + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test_cont.begin(), test_cont.end() + ); + } + + template + void test(Container1& cont1, Container2& cont2) + { + typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + + std::vector reference(cont1.size() + cont2.size()); + std::vector test_cont(reference); + + iterator_t reference_result + = std::set_difference(cont1.begin(), cont1.end(), + cont2.begin(), cont2.end(), + reference.begin()); + + iterator_t test_result + = boost::set_difference(cont1, cont2, test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_difference( + boost::make_iterator_range(cont1), cont2, + test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_difference( + cont1, boost::make_iterator_range(cont2), + test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_difference( + boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2), + test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + } + + template + void sort_container(Container& cont, BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector temp(cont.begin(), cont.end()); + std::sort(temp.begin(), temp.end(), pred); + cont.assign(temp.begin(), temp.end()); + } + + template + void test_pred(Container1 cont1, Container2 cont2, + BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + + sort_container(cont1, pred); + sort_container(cont2, pred); + + std::vector reference(cont1.size() + cont2.size()); + std::vector test_cont(reference); + + iterator_t reference_result + = std::set_difference(cont1.begin(), cont1.end(), + cont2.begin(), cont2.end(), + reference.begin(), + pred); + + iterator_t test_result + = boost::set_difference(cont1, cont2, test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_difference( + boost::make_iterator_range(cont1), cont2, + test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_difference( + cont1, boost::make_iterator_range(cont2), + test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_difference( + boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2), + test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + } + + template + void test_set_difference_impl( + Container1& cont1, + Container2& cont2 + ) + { + test(cont1, cont2); + test_pred(cont1, cont2, std::less()); + test_pred(cont1, cont2, std::greater()); + } + + template + void test_set_difference_impl() + { + using namespace boost::assign; + + Container1 cont1; + Container2 cont2; + + test_set_difference_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1; + test_set_difference_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont2 += 1; + test_set_difference_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1,2,3,4,5,6,7,8,9; + cont2 += 2,3,4; + test_set_difference_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 2,3,4; + cont2 += 1,2,3,4,5,6,7,8,9; + test_set_difference_impl(cont1, cont2); + } + + void test_set_difference() + { + test_set_difference_impl< std::vector, std::vector >(); + test_set_difference_impl< std::list, std::list >(); + test_set_difference_impl< std::deque, std::deque >(); + test_set_difference_impl< std::vector, std::list >(); + test_set_difference_impl< std::list, std::vector >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.set_difference" ); + + test->add( BOOST_TEST_CASE( &boost::test_set_difference ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/set_intersection.cpp b/libs/range/test/algorithm_test/set_intersection.cpp new file mode 100644 index 00000000..5e08e05f --- /dev/null +++ b/libs/range/test/algorithm_test/set_intersection.cpp @@ -0,0 +1,213 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void check_result( + Container1& reference, + Iterator reference_result, + Container2& test_cont, + Iterator test_result + ) + { + BOOST_CHECK_EQUAL( + std::distance(reference.begin(), reference_result), + std::distance(test_cont.begin(), test_result) + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test_cont.begin(), test_cont.end() + ); + } + + template + void test(Container1& cont1, Container2& cont2) + { + typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + + std::vector reference(cont1.size() + cont2.size()); + std::vector test_cont(reference); + + iterator_t reference_result + = std::set_intersection(cont1.begin(), cont1.end(), + cont2.begin(), cont2.end(), + reference.begin()); + + iterator_t test_result + = boost::set_intersection(cont1, cont2, test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_intersection( + boost::make_iterator_range(cont1), cont2, + test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_intersection( + cont1, boost::make_iterator_range(cont2), + test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_intersection( + boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2), + test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + } + + template + void sort_container(Container& cont, BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector temp(cont.begin(), cont.end()); + std::sort(temp.begin(), temp.end(), pred); + cont.assign(temp.begin(), temp.end()); + } + + template + void test_pred(Container1 cont1, Container2 cont2, + BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + + sort_container(cont1, pred); + sort_container(cont2, pred); + + std::vector reference(cont1.size() + cont2.size()); + std::vector test_cont(reference); + + iterator_t reference_result + = std::set_intersection(cont1.begin(), cont1.end(), + cont2.begin(), cont2.end(), + reference.begin(), + pred); + + iterator_t test_result + = boost::set_intersection(cont1, cont2, test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_intersection( + boost::make_iterator_range(cont1), cont2, + test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_intersection( + cont1, boost::make_iterator_range(cont2), + test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_intersection( + boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2), + test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + } + + template + void test_set_intersection_impl( + Container1& cont1, + Container2& cont2 + ) + { + test(cont1, cont2); + test_pred(cont1, cont2, std::less()); + test_pred(cont1, cont2, std::greater()); + } + + template + void test_set_intersection_impl() + { + using namespace boost::assign; + + Container1 cont1; + Container2 cont2; + + test_set_intersection_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1; + test_set_intersection_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont2 += 1; + test_set_intersection_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1,2,3,4,5,6,7,8,9; + cont2 += 2,3,4; + test_set_intersection_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 2,3,4; + cont2 += 1,2,3,4,5,6,7,8,9; + test_set_intersection_impl(cont1, cont2); + } + + void test_set_intersection() + { + test_set_intersection_impl< std::vector, std::vector >(); + test_set_intersection_impl< std::list, std::list >(); + test_set_intersection_impl< std::deque, std::deque >(); + test_set_intersection_impl< std::vector, std::list >(); + test_set_intersection_impl< std::list, std::vector >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.set_intersection" ); + + test->add( BOOST_TEST_CASE( &boost::test_set_intersection ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/set_symmetric_difference.cpp b/libs/range/test/algorithm_test/set_symmetric_difference.cpp new file mode 100644 index 00000000..e52b16e5 --- /dev/null +++ b/libs/range/test/algorithm_test/set_symmetric_difference.cpp @@ -0,0 +1,215 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void check_result( + Container1& reference, + Iterator reference_result, + Container2& test_cont, + Iterator test_result + ) + { + BOOST_CHECK_EQUAL( + std::distance(reference.begin(), reference_result), + std::distance(test_cont.begin(), test_result) + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test_cont.begin(), test_cont.end() + ); + } + + template + void test(Container1& cont1, Container2& cont2) + { + typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + + std::vector reference(cont1.size() + cont2.size()); + std::vector test_cont(reference); + + iterator_t reference_result + = std::set_symmetric_difference(cont1.begin(), cont1.end(), + cont2.begin(), cont2.end(), + reference.begin()); + + iterator_t test_result + = boost::set_symmetric_difference(cont1, cont2, + test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_symmetric_difference( + boost::make_iterator_range(cont1), cont2, + test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_symmetric_difference( + cont1, boost::make_iterator_range(cont2), + test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_symmetric_difference( + boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2), + test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + } + + template + void sort_container(Container& cont, BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector temp(cont.begin(), cont.end()); + std::sort(temp.begin(), temp.end(), pred); + cont.assign(temp.begin(), temp.end()); + } + + template + void test_pred(Container1 cont1, Container2 cont2, + BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + + sort_container(cont1, pred); + sort_container(cont2, pred); + + std::vector reference(cont1.size() + cont2.size()); + std::vector test_cont(reference); + + iterator_t reference_result + = std::set_symmetric_difference(cont1.begin(), cont1.end(), + cont2.begin(), cont2.end(), + reference.begin(), + pred); + + iterator_t test_result + = boost::set_symmetric_difference(cont1, cont2, + test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_symmetric_difference( + boost::make_iterator_range(cont1), cont2, + test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_symmetric_difference( + cont1, boost::make_iterator_range(cont2), + test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_symmetric_difference( + boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2), + test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + } + + template + void test_set_symmetric_difference_impl( + Container1& cont1, + Container2& cont2 + ) + { + test(cont1, cont2); + test_pred(cont1, cont2, std::less()); + test_pred(cont1, cont2, std::greater()); + } + + template + void test_set_symmetric_difference_impl() + { + using namespace boost::assign; + + Container1 cont1; + Container2 cont2; + + test_set_symmetric_difference_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1; + test_set_symmetric_difference_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont2 += 1; + test_set_symmetric_difference_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1,2,3,4,5,6,7,8,9; + cont2 += 2,3,4; + test_set_symmetric_difference_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 2,3,4; + cont2 += 1,2,3,4,5,6,7,8,9; + test_set_symmetric_difference_impl(cont1, cont2); + } + + void test_set_symmetric_difference() + { + test_set_symmetric_difference_impl< std::vector, std::vector >(); + test_set_symmetric_difference_impl< std::list, std::list >(); + test_set_symmetric_difference_impl< std::deque, std::deque >(); + test_set_symmetric_difference_impl< std::vector, std::list >(); + test_set_symmetric_difference_impl< std::list, std::vector >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.set_symmetric_difference" ); + + test->add( BOOST_TEST_CASE( &boost::test_set_symmetric_difference ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/set_union.cpp b/libs/range/test/algorithm_test/set_union.cpp new file mode 100644 index 00000000..6c7208bd --- /dev/null +++ b/libs/range/test/algorithm_test/set_union.cpp @@ -0,0 +1,209 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void check_result( + Container1& reference, + Iterator reference_result, + Container2& test_cont, + Iterator test_result + ) + { + BOOST_CHECK_EQUAL( + std::distance(reference.begin(), reference_result), + std::distance(test_cont.begin(), test_result) + ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test_cont.begin(), test_cont.end() + ); + } + + template + void test(Container1& cont1, Container2& cont2) + { + typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + + std::vector reference(cont1.size() + cont2.size()); + std::vector test_cont(reference); + + iterator_t reference_result + = std::set_union(cont1.begin(), cont1.end(), + cont2.begin(), cont2.end(), + reference.begin()); + + iterator_t test_result + = boost::set_union(cont1, cont2, test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_union(boost::make_iterator_range(cont1), + cont2, test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_union(cont1, + boost::make_iterator_range(cont2), + test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_union(boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2), + test_cont.begin()); + + check_result(reference, reference_result, + test_cont, test_result); + } + + template + void sort_container(Container& cont, BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector temp(cont.begin(), cont.end()); + std::sort(temp.begin(), temp.end(), pred); + cont.assign(temp.begin(), temp.end()); + } + + template + void test_pred(Container1 cont1, Container2 cont2, + BinaryPredicate pred) + { + typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + + sort_container(cont1, pred); + sort_container(cont2, pred); + + std::vector reference(cont1.size() + cont2.size()); + std::vector test_cont(reference); + + iterator_t reference_result + = std::set_union(cont1.begin(), cont1.end(), + cont2.begin(), cont2.end(), + reference.begin(), + pred); + + iterator_t test_result + = boost::set_union(cont1, cont2, test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_union(boost::make_iterator_range(cont1), + cont2, test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_union(cont1, + boost::make_iterator_range(cont2), + test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + + test_result = boost::set_union(boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2), + test_cont.begin(), pred); + + check_result(reference, reference_result, + test_cont, test_result); + } + + template + void test_set_union_impl( + Container1& cont1, + Container2& cont2 + ) + { + test(cont1, cont2); + test_pred(cont1, cont2, std::less()); + test_pred(cont1, cont2, std::greater()); + } + + template + void test_set_union_impl() + { + using namespace boost::assign; + + Container1 cont1; + Container2 cont2; + + test_set_union_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1; + test_set_union_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont2 += 1; + test_set_union_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 1,2,3,4,5,6,7,8,9; + cont2 += 2,3,4; + test_set_union_impl(cont1, cont2); + + cont1.clear(); + cont2.clear(); + cont1 += 2,3,4; + cont2 += 1,2,3,4,5,6,7,8,9; + test_set_union_impl(cont1, cont2); + } + + void test_set_union() + { + test_set_union_impl< std::vector, std::vector >(); + test_set_union_impl< std::list, std::list >(); + test_set_union_impl< std::deque, std::deque >(); + test_set_union_impl< std::vector, std::list >(); + test_set_union_impl< std::list, std::vector >(); + } + } +} + + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.set_union" ); + + test->add( BOOST_TEST_CASE( &boost::test_set_union ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/sort.cpp b/libs/range/test/algorithm_test/sort.cpp new file mode 100644 index 00000000..33a681aa --- /dev/null +++ b/libs/range/test/algorithm_test/sort.cpp @@ -0,0 +1,104 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void test_sort_impl(Container& cont) + { + Container reference(cont); + Container test(cont); + + boost::sort(test); + std::sort(reference.begin(), reference.end()); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + Container test2(cont); + boost::sort(boost::make_iterator_range(test2)); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test2.begin(), test2.end() ); + } + + template + void test_sort_impl(Container& cont, BinaryPredicate pred) + { + Container reference(cont); + Container test(cont); + + boost::sort(test, pred); + std::sort(reference.begin(), reference.end(), pred); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + + Container test2(cont); + boost::sort(boost::make_iterator_range(test2), pred); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test2.begin(), test2.end() ); + } + + template + void test_sort_impl() + { + using namespace boost::assign; + + Container cont; + test_sort_impl(cont); + test_sort_impl(cont, std::less()); + test_sort_impl(cont, std::greater()); + + cont.clear(); + cont += 1; + test_sort_impl(cont); + test_sort_impl(cont, std::less()); + test_sort_impl(cont, std::greater()); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_sort_impl(cont); + test_sort_impl(cont, std::less()); + test_sort_impl(cont, std::greater()); + } + + void test_sort() + { + test_sort_impl< std::vector >(); + test_sort_impl< std::deque >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.sort" ); + + test->add( BOOST_TEST_CASE( &boost::test_sort ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/stable_partition.cpp b/libs/range/test/algorithm_test/stable_partition.cpp new file mode 100644 index 00000000..b5b1538e --- /dev/null +++ b/libs/range/test/algorithm_test/stable_partition.cpp @@ -0,0 +1,133 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include "../test_driver/range_return_test_driver.hpp" +#include +#include +#include +#include +#include +#include + +namespace boost_range_test_algorithm_stable_partition +{ + struct equal_to_5 + { + typedef bool result_type; + typedef int argument_type; + bool operator()(int x) const { return x == 5; } + }; + + // test the 'partition' algorithm + template + class stable_partition_test_policy + { + public: + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + Container cont2(cont); + + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::stable_partition(cont, UnaryPredicate()); + + iter_t temp_result = boost::stable_partition( + boost::make_iterator_range(cont2), UnaryPredicate()); + + BOOST_CHECK_EQUAL( std::distance(cont.begin(), result), + std::distance(cont2.begin(), temp_result) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( cont.begin(), cont.end(), + cont2.begin(), cont2.end() ); + + return result; + } + + UnaryPredicate pred() const { return UnaryPredicate(); } + + template< boost::range_return_value return_type > + struct test_range + { + template< class Container, class Policy > + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + Container cont2(cont); + result_t result = boost::stable_partition(cont, policy.pred()); + + result_t result2 = boost::stable_partition( + boost::make_iterator_range(cont2), policy.pred()); + + boost::ignore_unused_variable_warning(result2); + + BOOST_CHECK_EQUAL_COLLECTIONS( cont2.begin(), cont2.end(), + cont.begin(), cont.end() ); + + return result; + } + }; + + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::stable_partition(cont.begin(), cont.end(), UnaryPredicate()); + } + }; + + template + void test_stable_partition_impl() + { + using namespace boost::assign; + + boost::range_test::range_return_test_driver test_driver; + + stable_partition_test_policy< equal_to_5 > policy; + + Container cont; + test_driver(cont, policy); + + cont.clear(); + cont += 1; + test_driver(cont, policy); + + cont.clear(); + cont += 1,2,2,2,2,2,3,4,5,6,7,8,9; + test_driver(cont, policy); + + cont.clear(); + cont += 1,2,2,2,2,2,3,3,3,3,4,4,4,4,4,4,4,5,6,7,8,9; + test_driver(cont, policy); + } + + void test_stable_partition() + { + test_stable_partition_impl< std::vector >(); + test_stable_partition_impl< std::list >(); + test_stable_partition_impl< std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.stable_partition" ); + + test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_stable_partition::test_stable_partition ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/stable_sort.cpp b/libs/range/test/algorithm_test/stable_sort.cpp new file mode 100644 index 00000000..1c339639 --- /dev/null +++ b/libs/range/test/algorithm_test/stable_sort.cpp @@ -0,0 +1,102 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template + void test_stable_sort_impl(Container& cont) + { + Container reference(cont); + Container test(cont); + + boost::stable_sort(test); + std::stable_sort(reference.begin(), reference.end()); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + test = cont; + boost::stable_sort(boost::make_iterator_range(test)); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + template + void test_stable_sort_impl(Container& cont, BinaryPredicate pred) + { + Container reference(cont); + Container test(cont); + + boost::stable_sort(test, pred); + std::stable_sort(reference.begin(), reference.end(), pred); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + test = cont; + boost::stable_sort(boost::make_iterator_range(test), pred); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + } + + template + void test_stable_sort_impl() + { + using namespace boost::assign; + + Container cont; + test_stable_sort_impl(cont); + test_stable_sort_impl(cont, std::less()); + test_stable_sort_impl(cont, std::greater()); + + cont.clear(); + cont += 1; + test_stable_sort_impl(cont); + test_stable_sort_impl(cont, std::less()); + test_stable_sort_impl(cont, std::greater()); + + cont.clear(); + cont += 1,2,3,4,5,6,7,8,9; + test_stable_sort_impl(cont); + test_stable_sort_impl(cont, std::less()); + test_stable_sort_impl(cont, std::greater()); + } + + void test_stable_sort() + { + test_stable_sort_impl< std::vector >(); + test_stable_sort_impl< std::deque >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.stable_sort" ); + + test->add( BOOST_TEST_CASE( &boost::test_stable_sort ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/swap_ranges.cpp b/libs/range/test/algorithm_test/swap_ranges.cpp new file mode 100644 index 00000000..02a44449 --- /dev/null +++ b/libs/range/test/algorithm_test/swap_ranges.cpp @@ -0,0 +1,115 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + template + void test_swap_ranges_impl(const Container1& source1, const Container2& source2) + { + Container1 reference1(source1); + Container2 reference2(source2); + std::swap_ranges(reference1.begin(), reference1.end(), reference2.begin()); + + Container1 test1(source1); + Container2 test2(source2); + boost::swap_ranges(test1, test2); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference1.begin(), reference1.end(), + test1.begin(), test1.end() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference2.begin(), reference2.end(), + test2.begin(), test2.end() ); + + test1 = source1; + test2 = source2; + boost::swap_ranges(boost::make_iterator_range(test1), test2); + BOOST_CHECK_EQUAL_COLLECTIONS( reference1.begin(), reference1.end(), + test1.begin(), test1.end() ); + BOOST_CHECK_EQUAL_COLLECTIONS( reference2.begin(), reference2.end(), + test2.begin(), test2.end() ); + + test1 = source1; + test2 = source2; + boost::swap_ranges(test1, boost::make_iterator_range(test2)); + BOOST_CHECK_EQUAL_COLLECTIONS( reference1.begin(), reference1.end(), + test1.begin(), test1.end() ); + BOOST_CHECK_EQUAL_COLLECTIONS( reference2.begin(), reference2.end(), + test2.begin(), test2.end() ); + + test1 = source1; + test2 = source2; + boost::swap_ranges(boost::make_iterator_range(test1), + boost::make_iterator_range(test2)); + BOOST_CHECK_EQUAL_COLLECTIONS( reference1.begin(), reference1.end(), + test1.begin(), test1.end() ); + BOOST_CHECK_EQUAL_COLLECTIONS( reference2.begin(), reference2.end(), + test2.begin(), test2.end() ); + } + + template + void test_swap_ranges_impl() + { + using namespace boost::assign; + + Container1 c1; + Container2 c2; + + test_swap_ranges_impl(c1, c2); + + c1.clear(); + c1 += 1; + c2.clear(); + c2 += 2; + test_swap_ranges_impl(c1, c2); + + c1.clear(); + c1 += 1,2,3,4,5,6,7,8,9,10; + c2.clear(); + c2 += 10,9,8,7,6,5,4,3,2,1; + test_swap_ranges_impl(c1, c2); + } + + inline void test_swap_ranges() + { + test_swap_ranges_impl< std::vector, std::vector >(); + test_swap_ranges_impl< std::vector, std::list >(); + test_swap_ranges_impl< std::vector, std::deque >(); + test_swap_ranges_impl< std::list, std::vector >(); + test_swap_ranges_impl< std::list, std::list >(); + test_swap_ranges_impl< std::list, std::deque >(); + test_swap_ranges_impl< std::deque, std::vector >(); + test_swap_ranges_impl< std::deque, std::list >(); + test_swap_ranges_impl< std::deque, std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.swap_ranges" ); + + test->add( BOOST_TEST_CASE( &test_swap_ranges ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/transform.cpp b/libs/range/test/algorithm_test/transform.cpp new file mode 100644 index 00000000..11ac5f0f --- /dev/null +++ b/libs/range/test/algorithm_test/transform.cpp @@ -0,0 +1,184 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include "../test_function/multiply_by_x.hpp" +#include +#include +#include +#include + +namespace boost +{ + namespace + { + template< class Container > + void test_transform_impl1(Container& cont) + { + using namespace boost::range_test_function; + + const Container& ccont = cont; + + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + std::vector target(cont.size()); + std::vector reference(cont.size()); + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + + multiply_by_x fn(2); + + iterator_t reference_it + = std::transform(cont.begin(), cont.end(), reference.begin(), fn); + + boost::ignore_unused_variable_warning(reference_it); + + iterator_t test_it + = boost::transform(cont, target.begin(), fn); + + BOOST_CHECK( test_it == target.end() ); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target.begin(), target.end() ); + + BOOST_CHECK( test_it == boost::transform(boost::make_iterator_range(cont), target.begin(), fn) ); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target.begin(), target.end() ); + + target.clear(); + target.resize(ccont.size()); + + test_it = boost::transform(ccont, target.begin(), fn); + + BOOST_CHECK( test_it == target.end() ); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target.begin(), target.end() ); + BOOST_CHECK( test_it == boost::transform(boost::make_iterator_range(ccont), target.begin(), fn) ); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target.begin(), target.end() ); + } + + template< class Container > + void test_transform_impl1() + { + using namespace boost::assign; + + Container cont; + + test_transform_impl1(cont); + + cont += 1; + test_transform_impl1(cont); + + cont += 2,3,4,5,6,7; + test_transform_impl1(cont); + } + + template< class Container1, class Container2 > + void test_transform_impl2(Container1& cont1, Container2& cont2) + { + const Container1& ccont1 = cont1; + const Container2& ccont2 = cont2; + + BOOST_CHECK_EQUAL( cont1.size(), cont2.size() ); + + typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_t; + + std::vector target(cont1.size()); + std::vector reference(cont1.size()); + typedef BOOST_DEDUCED_TYPENAME std::vector::iterator iterator_t; + + std::multiplies fn; + + iterator_t reference_it + = std::transform(cont1.begin(), cont1.end(), + cont2.begin(), reference.begin(), fn); + + boost::ignore_unused_variable_warning(reference_it); + + iterator_t test_it + = boost::transform(cont1, cont2, target.begin(), fn); + + BOOST_CHECK( test_it == target.end() ); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target.begin(), target.end() ); + + BOOST_CHECK( test_it == boost::transform(boost::make_iterator_range(cont1), cont2, target.begin(), fn) ); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target.begin(), target.end() ); + + BOOST_CHECK( test_it == boost::transform(cont1, boost::make_iterator_range(cont2), target.begin(), fn) ); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target.begin(), target.end() ); + + BOOST_CHECK( test_it == boost::transform(boost::make_iterator_range(cont1), + boost::make_iterator_range(cont2), + target.begin(), fn) ); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target.begin(), target.end() ); + + + target.clear(); + target.resize(ccont1.size()); + + test_it = boost::transform(ccont1, ccont2, target.begin(), fn); + + BOOST_CHECK( test_it == target.end() ); + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target.begin(), target.end() ); + } + + template< class Container1, class Container2 > + void test_transform_impl2() + { + using namespace boost::assign; + + Container1 cont1; + Container2 cont2; + + test_transform_impl2(cont1, cont2); + + cont1 += 1; + cont2 += 2; + test_transform_impl2(cont1, cont2); + + cont1 += 2,3,4,5,6,7; + cont2 += 4,6,8,10,12,14; + test_transform_impl2(cont1, cont2); + } + + void test_transform() + { + test_transform_impl1< std::vector >(); + test_transform_impl1< std::list >(); + test_transform_impl1< std::set >(); + test_transform_impl1< std::multiset >(); + + test_transform_impl2< std::vector, std::list >(); + test_transform_impl2< std::list, std::vector >(); + test_transform_impl2< std::set, std::set >(); + test_transform_impl2< std::multiset, std::list >(); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.transform" ); + + test->add( BOOST_TEST_CASE( &boost::test_transform ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/unique.cpp b/libs/range/test/algorithm_test/unique.cpp new file mode 100644 index 00000000..8d7752af --- /dev/null +++ b/libs/range/test/algorithm_test/unique.cpp @@ -0,0 +1,262 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include + +#include +#include + +#include +#include +#include "../test_driver/range_overload_test_driver.hpp" +#include +#include +#include +#include +#include +#include + +namespace boost_range_test_algorithm_unique +{ + // test the 'unique' algorithm without a predicate + class unique_test_policy + { + public: + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + // There isn't an iterator return version of boost::unique, so just + // perform the standard algorithm + return std::unique(cont.begin(), cont.end()); + } + + template< boost::range_return_value return_type > + struct test_range + { + template< class Container, class Policy > + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy&, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + + Container cont2(cont); + + result_t result = boost::unique(cont); + + boost::unique(boost::make_iterator_range(cont2)); + + BOOST_CHECK_EQUAL_COLLECTIONS( cont.begin(), cont.end(), + cont2.begin(), cont2.end() ); + + return result; + } + }; + + template + struct test_range_overload + { + BOOST_STATIC_CONSTANT( + ::boost::range_return_value, + result_type = ::boost::return_begin_found); + + template + BOOST_DEDUCED_TYPENAME boost::range_return< + Container, result_type + >::type + operator()(Policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return< + Container,result_type>::type result_t; + + Container cont2(cont); + + result_t result = boost::unique(cont); + + boost::unique(boost::make_iterator_range(cont2)); + + BOOST_CHECK_EQUAL_COLLECTIONS( + cont.begin(), cont.end(), + cont2.begin(), cont2.end()); + + return result; + } + }; + + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::unique(cont.begin(), cont.end()); + } + }; + + // test the 'unique' algorithm with a predicate + template + class unique_pred_test_policy + { + public: + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + // There isn't an iterator return version of boost::unique, so just + // perform the standard algorithm + return std::unique(cont.begin(), cont.end(), Pred()); + } + + Pred pred() const { return Pred(); } + + template< boost::range_return_value return_type > + struct test_range + { + template< class Container, class Policy > + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + + Container cont2(cont); + + result_t result = boost::unique(cont, policy.pred()); + + boost::unique(boost::make_iterator_range(cont2), policy.pred()); + + BOOST_CHECK_EQUAL_COLLECTIONS( cont.begin(), cont.end(), + cont2.begin(), cont2.end() ); + + return result; + } + }; + + template + struct test_range_overload + { + BOOST_STATIC_CONSTANT( + ::boost::range_return_value, + result_type = ::boost::return_begin_found); + + template + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return< + Container,result_type>::type result_t; + + Container cont2(cont); + + result_t result = boost::unique(cont, policy.pred()); + + boost::unique(boost::make_iterator_range(cont2), policy.pred()); + + BOOST_CHECK_EQUAL_COLLECTIONS( + cont.begin(), cont.end(), + cont2.begin(), cont2.end()); + + return result; + } + }; + + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::unique(cont.begin(), cont.end(), Pred()); + } + }; + + template + void test_unique_impl(TestPolicy policy, Pred pred) + { + using namespace boost::assign; + + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + boost::range_test::range_overload_test_driver test_driver; + + Container cont; + + test_driver(cont, policy); + + cont.clear(); + cont += 1; + + std::vector temp(cont.begin(), cont.end()); + std::sort(temp.begin(), temp.end(), pred); + cont.assign(temp.begin(), temp.end()); + + test_driver(cont, policy); + + cont.clear(); + cont += 1,2,2,2,2,3,4,5,6,7,8,9; + + temp.assign(cont.begin(), cont.end()); + std::sort(temp.begin(), temp.end(), pred); + cont.assign(temp.begin(), temp.end()); + + test_driver(cont, policy); + } + + template + struct equal_div_2 + { + typedef bool result_type; + typedef const T& first_argument_type; + typedef const T& second_argument_type; + + bool operator()(const T& left, const T& right) const + { + return left / 2 == right / 2; + } + }; + + template + void test_unique_impl() + { + test_unique_impl( + unique_test_policy(), + std::less() + ); + + test_unique_impl( + unique_pred_test_policy >(), + std::less() + ); + + test_unique_impl( + unique_pred_test_policy >(), + std::greater() + ); + + test_unique_impl( + unique_pred_test_policy >(), + std::less() + ); + } + + void test_unique() + { + test_unique_impl< std::vector >(); + test_unique_impl< std::list >(); + test_unique_impl< std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.unique" ); + + test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_unique::test_unique ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/unique_copy.cpp b/libs/range/test/algorithm_test/unique_copy.cpp new file mode 100644 index 00000000..cd251627 --- /dev/null +++ b/libs/range/test/algorithm_test/unique_copy.cpp @@ -0,0 +1,157 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + template + void test_append(OutputIterator target, Value value) + { + *target++ = value; + } + + template + void test_unique_copy_impl(Container& c) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_value::type value_type; + std::vector reference; + std::vector test; + + test_append( + std::unique_copy(c.begin(), c.end(), std::back_inserter(reference)), + value_type() + ); + + test_append( + boost::unique_copy(c, std::back_inserter(test)), + value_type() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS(reference.begin(), reference.end(), + test.begin(), test.end()); + + test.clear(); + + test_append( + boost::unique_copy(boost::make_iterator_range(c), + std::back_inserter(test)), + value_type() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS(reference.begin(), reference.end(), + test.begin(), test.end()); + } + + template + void test_unique_copy_impl(Container& c, Pred pred) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_value::type value_type; + std::vector reference; + std::vector test; + + test_append( + std::unique_copy(c.begin(), c.end(), std::back_inserter(reference), pred), + value_type() + ); + + test_append( + boost::unique_copy(c, std::back_inserter(test), pred), + value_type() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS(reference.begin(), reference.end(), + test.begin(), test.end()); + + test.clear(); + + test_append( + boost::unique_copy(boost::make_iterator_range(c), + std::back_inserter(test), pred), + value_type() + ); + + BOOST_CHECK_EQUAL_COLLECTIONS(reference.begin(), reference.end(), + test.begin(), test.end()); + } + + template + void test_unique_copy_driver(Pred pred) + { + using namespace boost::assign; + + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + Container cont; + + test_unique_copy_impl(cont); + test_unique_copy_impl(cont, pred); + + cont.clear(); + cont += 1; + + std::vector temp(cont.begin(), cont.end()); + std::sort(temp.begin(), temp.end()); + cont.assign(temp.begin(), temp.end()); + test_unique_copy_impl(cont); + + std::sort(temp.begin(), temp.end(), pred); + cont.assign(temp.begin(), temp.end()); + test_unique_copy_impl(cont, pred); + + cont.clear(); + cont += 1,2,2,2,2,3,4,5,6,7,8,9; + + temp.assign(cont.begin(), cont.end()); + std::sort(temp.begin(), temp.end()); + cont.assign(temp.begin(), temp.end()); + test_unique_copy_impl(cont); + + std::sort(temp.begin(), temp.end(), pred); + cont.assign(temp.begin(), temp.end()); + test_unique_copy_impl(cont, pred); + } + + template + void test_unique_copy_impl() + { + test_unique_copy_driver(std::less()); + test_unique_copy_driver(std::greater()); + } + + void test_unique_copy() + { + test_unique_copy_impl< std::vector >(); + test_unique_copy_impl< std::list >(); + test_unique_copy_impl< std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.unique_copy" ); + + test->add( BOOST_TEST_CASE( &test_unique_copy ) ); + + return test; +} diff --git a/libs/range/test/algorithm_test/upper_bound.cpp b/libs/range/test/algorithm_test/upper_bound.cpp new file mode 100644 index 00000000..0dff22fd --- /dev/null +++ b/libs/range/test/algorithm_test/upper_bound.cpp @@ -0,0 +1,181 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include + +#include +#include "../test_driver/range_return_test_driver.hpp" +#include +#include +#include +#include +#include +#include + +namespace boost_range_test_algorithm_upper_bound +{ + class upper_bound_policy + { + public: + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::upper_bound(cont, 5); + BOOST_CHECK( result == boost::upper_bound(boost::make_iterator_range(cont), 5) ); + return result; + } + + template + struct test_range + { + template + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy&, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + result_t result = boost::upper_bound(cont, 5); + BOOST_CHECK( result == boost::upper_bound(boost::make_iterator_range(cont), 5) ); + return result; + } + }; + + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::upper_bound(cont.begin(), cont.end(), 5); + } + }; + + template< class BinaryPredicate > + struct upper_bound_pred_policy + { + template< class Container > + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + test_iter(Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type iter_t; + iter_t result = boost::upper_bound(cont, 5, BinaryPredicate()); + BOOST_CHECK( result == boost::upper_bound(boost::make_iterator_range(cont), 5, BinaryPredicate()) ); + return result; + } + + template< boost::range_return_value result_type> + struct test_range + { + template< class Container, class Policy > + BOOST_DEDUCED_TYPENAME boost::range_return::type + operator()(Policy& policy, Container& cont) + { + typedef BOOST_DEDUCED_TYPENAME boost::range_return::type result_t; + + result_t result = boost::upper_bound(cont, 5, policy.pred()); + + BOOST_CHECK( result == boost::upper_bound( + boost::make_iterator_range(cont), 5, policy.pred()) ); + + return result; + } + }; + + template + BOOST_DEDUCED_TYPENAME boost::range_iterator::type + reference(Container& cont) + { + return std::upper_bound( + cont.begin(), cont.end(), 5, BinaryPredicate()); + } + + BinaryPredicate& pred() { return m_pred; } + + private: + BinaryPredicate m_pred; + }; + + template + void test_upper_bound_impl(TestPolicy policy, BinaryPredicate pred) + { + using namespace boost::assign; + + typedef BOOST_DEDUCED_TYPENAME boost::remove_const::type container_t; + typedef BOOST_DEDUCED_TYPENAME Container::value_type value_t; + + boost::range_test::range_return_test_driver test_driver; + + container_t mcont; + Container& cont = mcont; + + test_driver(cont, policy); + + mcont.clear(); + mcont += 1; + + std::vector temp(mcont.begin(), mcont.end()); + std::sort(temp.begin(), temp.end(), pred); + mcont.assign(temp.begin(), temp.end()); + + test_driver(cont, policy); + + mcont.clear(); + mcont += 1,2,3,4,5,6,7,8,9; + + temp.assign(mcont.begin(), mcont.end()); + std::sort(temp.begin(), temp.end(), pred); + mcont.assign(temp.begin(), temp.end()); + + test_driver(cont, policy); + } + + template + void test_upper_bound_impl() + { + test_upper_bound_impl( + upper_bound_policy(), + std::less() + ); + + test_upper_bound_impl( + upper_bound_pred_policy >(), + std::less() + ); + + test_upper_bound_impl( + upper_bound_pred_policy >(), + std::greater() + ); + } + + void test_upper_bound() + { + test_upper_bound_impl< std::vector >(); + test_upper_bound_impl< std::list >(); + test_upper_bound_impl< std::deque >(); + + test_upper_bound_impl< const std::vector >(); + test_upper_bound_impl< const std::list >(); + test_upper_bound_impl< const std::deque >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.algorithm.upper_bound" ); + + test->add( BOOST_TEST_CASE( &boost_range_test_algorithm_upper_bound::test_upper_bound ) ); + + return test; +} diff --git a/libs/range/test/array.cpp b/libs/range/test/array.cpp new file mode 100644 index 00000000..a9bd170d --- /dev/null +++ b/libs/range/test/array.cpp @@ -0,0 +1,83 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include +#include +#include + +using namespace boost; +using namespace std; + +void check_array() +{ + const int sz = 9; + typedef int array_t[sz]; + int my_array[sz] = { 1,2,3,4,5,6,7,8,9 }; + const array_t ca = { 1,2,3,4,5,6,7,8,10 }; + + +// BOOST_RANGE_NO_STATIC_ASSERT +#if !defined( BOOST_BORLANDC ) +#else + BOOST_STATIC_ASSERT(( is_same< range_value::type, int >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, int* >::value )); + BOOST_STATIC_ASSERT(( is_same< range_const_iterator::type, const int* >::value )); + BOOST_STATIC_ASSERT(( is_same< range_difference::type, std::ptrdiff_t >::value )); + BOOST_STATIC_ASSERT(( is_same< range_size::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, int* >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, const int* >::value )); + + BOOST_STATIC_ASSERT(( is_same< range_value::type, const int >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, const int* >::value )); + BOOST_STATIC_ASSERT(( is_same< range_const_iterator::type, const int* >::value )); + BOOST_STATIC_ASSERT(( is_same< range_difference::type, std::ptrdiff_t >::value )); + BOOST_STATIC_ASSERT(( is_same< range_size::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, const int* >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, const int* >::value )); +#endif + + BOOST_CHECK_EQUAL( begin( my_array ), my_array ); + BOOST_CHECK_EQUAL( end( my_array ), my_array + size( my_array ) ); + BOOST_CHECK_EQUAL( empty( my_array ), false ); + + BOOST_CHECK_EQUAL( begin( ca ), ca ); + BOOST_CHECK_EQUAL( end( ca ), ca + size( ca ) ); + BOOST_CHECK_EQUAL( empty( ca ),false ); + + const char A[] = "\0A"; + BOOST_CHECK_EQUAL( boost::size(A), 3 ); +} + +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &check_array ) ); + + return test; +} + + + + + diff --git a/libs/range/test/atl.cpp b/libs/range/test/atl.cpp new file mode 100644 index 00000000..50905b16 --- /dev/null +++ b/libs/range/test/atl.cpp @@ -0,0 +1,623 @@ + + +// Boost.Range ATL Extension +// +// Copyright Shunsuke Sogame 2005-2006. +// 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) + + +// #include + +#include +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS +#define _ATL_NO_AUTOMATIC_NAMESPACE + +#define BOOST_LIB_NAME boost_test_exec_monitor +#include + +#define BOOST_RANGE_DETAIL_MICROSOFT_TEST +#include // can be placed first + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + + +#include // for ATL3 CSimpleArray/CSimpleValArray +#if !(_ATL_VER < 0x0700) + #include + #include + #include + #include +#endif + + +namespace brdm = boost::range_detail_microsoft; + + +#if !(_ATL_VER < 0x0700) + + +template< class ArrayT, class SampleRange > +bool test_init_auto_ptr_array(ArrayT& arr, SampleRange& sample) +{ + typedef typename boost::range_iterator::type iter_t; + + for (iter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) { + arr.Add(*it); // moves ownership + } + + return boost::distance(arr) == boost::distance(sample); +} + + +template< class ListT, class SampleRange > +bool test_init_auto_ptr_list(ListT& lst, SampleRange& sample) +{ + typedef typename boost::range_iterator::type iter_t; + typedef typename boost::range_value::type val_t; + + for (iter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) { + lst.AddTail(*it); // moves ownership + } + + return boost::distance(lst) == boost::distance(sample); +} + + +// Workaround: +// CRBTree provides no easy access function, but yes, it is the range! +// +template< class AtlMapT, class KeyT, class MappedT > +bool test_atl_map_has(AtlMapT& map, const KeyT& k, const MappedT m) +{ + typedef typename boost::range_iterator::type iter_t; + + for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) { + if (it->m_key == k && it->m_value == m) + return true; + } + + return false; +} + + +template< class AtlMapT, class MapT > +bool test_atl_map(AtlMapT& map, const MapT& sample) +{ + typedef typename boost::range_iterator::type iter_t; + typedef typename boost::range_const_iterator::type siter_t; + + bool result = true; + + result = result && (boost::distance(map) == boost::distance(sample)); + if (!result) + return false; + + { + for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) { + result = result && brdm::test_find_key_and_mapped(sample, std::make_pair(it->m_key, it->m_value)); + } + } + + { + for (siter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) { + result = result && (test_atl_map_has)(map, it->first, it->second); + } + } + + return result; +} + + +template< class MapT, class SampleMap > +bool test_init_atl_multimap(MapT& map, const SampleMap& sample) +{ + typedef typename boost::range_const_iterator::type iter_t; + + for (iter_t it = boost::const_begin(sample), last = boost::const_end(sample); it != last; ++it) { + map.Insert(it->first, it->second); + } + + return boost::distance(map) == boost::distance(sample); +} + + +// arrays +// + +template< class Range > +void test_CAtlArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ATL::CAtlArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class ValT, class Range > +void test_CAutoPtrArray(Range& sample) +{ + typedef ValT val_t; + + typedef ATL::CAutoPtrArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter *> >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter const*> >::value )); + + rng_t rng; + BOOST_CHECK( ::test_init_auto_ptr_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class I, class Range > +void test_CInterfaceArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ATL::CInterfaceArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter * >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter const* >::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// lists +// + +template< class Range > +void test_CAtlList(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ATL::CAtlList rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class ValT, class Range > +void test_CAutoPtrList(Range& sample) +{ + typedef ValT val_t; + + typedef ATL::CAutoPtrList rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, boost::indirect_iterator< brdm::list_iterator > > >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, boost::indirect_iterator< brdm::list_iterator const> > >::value )); + + rng_t rng; + BOOST_CHECK( ::test_init_auto_ptr_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class ValT, class Range > +void test_CHeapPtrList(const Range& sample) +{ + typedef ValT val_t; + + typedef ATL::CHeapPtrList rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, boost::indirect_iterator< brdm::list_iterator > > >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, boost::indirect_iterator< brdm::list_iterator const> > >::value )); + + rng_t rng; + BOOST_CHECK( ::test_init_auto_ptr_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class I, class Range > +void test_CInterfaceList(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ATL::CInterfaceList rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator > >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator const> >::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// strings +// + +template< class Range > +void test_CSimpleStringT(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef typename boost::mpl::if_< boost::is_same, + ATL::CAtlStringA, + ATL::CAtlStringW + >::type derived_t; + + typedef ATL::CSimpleStringT rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + derived_t drng; + rng_t& rng = drng; + BOOST_CHECK( brdm::test_init_string(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + // BOOST_CHECK( brdm::test_emptiness(rng) ); no default constructible +} + + +template< int n, class Range > +void test_CFixedStringT(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef typename boost::mpl::if_< boost::is_same, + ATL::CAtlStringA, + ATL::CAtlStringW + >::type base_t; + + typedef ATL::CFixedStringT rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_string(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CStringT(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef typename boost::mpl::if_< boost::is_same, + ATL::CAtlStringA, // == CStringT + ATL::CAtlStringW // == CStringT + >::type rng_t; + + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_string(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CStaticString(const Range& sample) +{ +#if !defined(BOOST_RANGE_ATL_NO_TEST_UNDOCUMENTED_RANGE) + { + typedef ATL::CStaticString rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng("hello static string"); + BOOST_CHECK( *(boost::begin(rng)+4) == 'o' ); + BOOST_CHECK( *(boost::end(rng)-3) == 'i' ); + } + + { + typedef ATL::CStaticString rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng(L"hello static string"); + BOOST_CHECK( *(boost::begin(rng)+4) == L'o' ); + BOOST_CHECK( *(boost::end(rng)-3) == L'i' ); + } +#endif + + (void)sample; // unused +} + + +#endif // !(_ATL_VER < 0x0700) + + +template< class Range > +void test_CComBSTR(const Range& sample) +{ + typedef ATL::CComBSTR rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng(OLESTR("hello CComBSTR range!")); + BOOST_CHECK( brdm::test_equals(rng, std::string("hello CComBSTR range!")) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); + + (void)sample; // unused +} + + +// simples +// + +template< class Range > +void test_CSimpleArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ATL::CSimpleArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CSimpleMap(const Range& sample) +{ +#if !defined(BOOST_RANGE_ATL_NO_TEST_UNDOCUMENTED_RANGE) + + typedef ATL::CSimpleMap rng_t; + + rng_t rng; + rng.Add(3, 3.0); + rng.Add(4, 2.0); + + BOOST_CHECK( boost::begin(rng)->get<0>() == 3.0 ); + BOOST_CHECK( (boost::end(rng)-1)->get<1>() == 2.0 ); + +#endif + + (void)sample; // unused +} + + +template< class Range > +void test_CSimpleValArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ATL::CSimpleArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// maps +// + +template< class MapT > +void test_CAtlMap(const MapT& sample) +{ + typedef typename MapT::key_type k_t; + typedef typename MapT::mapped_type m_t; + + typedef ATL::CAtlMap rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_atl_map(rng, sample) ); +} + + +template< class MapT > +void test_CRBTree(const MapT& sample) +{ + typedef typename MapT::key_type k_t; + typedef typename MapT::mapped_type m_t; + + typedef ATL::CRBMap derived_t; + typedef ATL::CRBTree rng_t; + + derived_t drng; + rng_t& rng = drng; + + boost::function_requires< boost::BidirectionalRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(drng, sample) ); + BOOST_CHECK( ::test_atl_map(rng, sample) ); +} + + +template< class MapT > +void test_CRBMap(const MapT& sample) +{ + typedef typename MapT::key_type k_t; + typedef typename MapT::mapped_type m_t; + + typedef ATL::CRBMap rng_t; + + rng_t rng; + boost::function_requires< boost::BidirectionalRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_atl_map(rng, sample) ); +} + + +template< class MapT > +void test_CRBMultiMap(const MapT& sample) +{ + typedef typename MapT::key_type k_t; + typedef typename MapT::mapped_type m_t; + + typedef ATL::CRBMultiMap rng_t; + + rng_t rng; + boost::function_requires< boost::BidirectionalRangeConcept >(); + BOOST_CHECK( ::test_init_atl_multimap(rng, sample) ); + BOOST_CHECK( ::test_atl_map(rng, sample) ); +} + + +// main test +// + +void test_atl() +{ + + // ordinary ranges + // + { + std::string sample("rebecca judy and mary whiteberry chat monchy"); +#if !(_ATL_VER < 0x0700) + ::test_CAtlArray(sample); + ::test_CAtlList(sample); + ::test_CSimpleStringT(sample); + ::test_CFixedStringT<44>(sample); + ::test_CStringT(sample); + ::test_CStaticString(sample); +#endif + ::test_CComBSTR(sample); + ::test_CSimpleArray(sample); + ::test_CSimpleMap(sample); + ::test_CSimpleValArray(sample); + } + + + { + std::wstring sample(L"rebecca judy and mary whiteberry chat monchy"); +#if !(_ATL_VER < 0x0700) + ::test_CAtlArray(sample); + ::test_CAtlList(sample); + ::test_CSimpleStringT(sample); + ::test_CFixedStringT<44>(sample); + ::test_CStringT(sample); + ::test_CStaticString(sample); +#endif + ::test_CComBSTR(sample); + ::test_CSimpleArray(sample); + ::test_CSimpleMap(sample); + ::test_CSimpleValArray(sample); + } + + // pointer ranges + // +#if !(_ATL_VER < 0x0700) + { + typedef ATL::CAutoPtr ptr_t; + ptr_t + ptr0(new int(3)), ptr1(new int(4)), ptr2(new int(5)), ptr3(new int(4)), + ptr4(new int(1)), ptr5(new int(2)), ptr6(new int(4)), ptr7(new int(0)); + + ptr_t ptrs[8] = { + ptr0, ptr1, ptr2, ptr3, ptr4, ptr5, ptr6, ptr7 + }; + + boost::iterator_range< ptr_t * > workaround(ptrs, ptrs+8); + ::test_CAutoPtrArray(workaround); + } + + { + typedef ATL::CAutoPtr ptr_t; + ptr_t + ptr0(new int(3)), ptr1(new int(4)), ptr2(new int(5)), ptr3(new int(4)), + ptr4(new int(1)), ptr5(new int(2)), ptr6(new int(4)), ptr7(new int(0)); + + ptr_t ptrs[8] = { + ptr0, ptr1, ptr2, ptr3, ptr4, ptr5, ptr6, ptr7 + }; + + boost::iterator_range< ptr_t * > workaround(ptrs, ptrs+8); + ::test_CAutoPtrList(workaround); + } + + { + typedef ATL::CHeapPtr ptr_t; + ptr_t ptrs[5]; { + ptrs[0].AllocateBytes(sizeof(int)); + ptrs[1].AllocateBytes(sizeof(int)); + ptrs[2].AllocateBytes(sizeof(int)); + ptrs[3].AllocateBytes(sizeof(int)); + ptrs[4].AllocateBytes(sizeof(int)); + } + + boost::iterator_range< ptr_t * > workaround(ptrs, ptrs+5); + ::test_CHeapPtrList(workaround); + } + + + { + typedef ATL::CComQIPtr ptr_t; + ptr_t ptrs[8]; + + boost::iterator_range< ptr_t * > workaround(ptrs, ptrs+8); + ::test_CInterfaceArray(workaround); + ::test_CInterfaceList(workaround); + } +#endif + + // maps + // + { +#if !(_ATL_VER < 0x0700) + std::map sample; { + sample[0] = "hello"; + sample[1] = "range"; + sample[2] = "atl"; + sample[3] = "mfc"; + sample[4] = "collections"; + } + + ::test_CAtlMap(sample); + ::test_CRBTree(sample); + ::test_CRBMap(sample); + ::test_CRBMultiMap(sample); +#endif + } + + +} // test_atl + + +#include +using boost::unit_test::test_suite; + + +test_suite * +init_unit_test_suite(int argc, char* argv[]) +{ + test_suite *test = BOOST_TEST_SUITE("ATL Range Test Suite"); + test->add(BOOST_TEST_CASE(&test_atl)); + + (void)argc, (void)argv; // unused + return test; +} diff --git a/libs/range/test/begin.cpp b/libs/range/test/begin.cpp new file mode 100644 index 00000000..91f50cee --- /dev/null +++ b/libs/range/test/begin.cpp @@ -0,0 +1,119 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include + +namespace mock_std +{ + template + inline BOOST_DEDUCED_TYPENAME boost::range_iterator::type + begin(SinglePassRange& rng) + { + return rng.begin(); + } + + template + inline BOOST_DEDUCED_TYPENAME boost::range_iterator::type + begin(const SinglePassRange& rng) + { + return rng.begin(); + } + + template + void mock_algorithm_using_begin(const SinglePassRange& rng) + { + BOOST_CHECK( begin(rng) == rng.begin() ); + } + + template + void mock_algorithm_using_begin(SinglePassRange& rng) + { + BOOST_CHECK( begin(rng) == rng.begin() ); + } +} + +namespace boost +{ +#ifdef BOOST_RANGE_SIMULATE_BEGIN_WITHOUT_ADL_NAMESPACE_BARRIER + template + inline BOOST_DEDUCED_TYPENAME range_iterator::type + begin(SinglePassRange& rng) + { + return rng.begin(); + } + + template + inline BOOST_DEDUCED_TYPENAME range_iterator::type + begin(const SinglePassRange& rng) + { + return rng.begin(); + } +#endif + + class MockTestBeginCollection + { + public: + typedef char value_type; + typedef const char* const_pointer; + typedef char* pointer; + typedef const_pointer const_iterator; + typedef pointer iterator; + + MockTestBeginCollection() + : m_first() + , m_last() + { + } + + const_iterator begin() const { return m_first; } + iterator begin() { return m_first; } + const_iterator end() const { return m_last; } + iterator end() { return m_last; } + + private: + iterator m_first; + iterator m_last; + }; +} + +namespace +{ + void test_range_begin() + { + boost::MockTestBeginCollection c; + const boost::MockTestBeginCollection& const_c = c; + mock_std::mock_algorithm_using_begin(const_c); + mock_std::mock_algorithm_using_begin(c); + } +} + +using boost::unit_test::test_suite; + +boost::unit_test::test_suite* +init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = BOOST_TEST_SUITE( "Range Test Suite - begin() ADL namespace barrier" ); + + test->add( BOOST_TEST_CASE( &test_range_begin ) ); + + return test; +} + + diff --git a/libs/range/test/category.cpp b/libs/range/test/category.cpp new file mode 100644 index 00000000..154c411e --- /dev/null +++ b/libs/range/test/category.cpp @@ -0,0 +1,61 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_category() +{ + typedef std::vector cont; + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::iterator_category::type, + boost::range_category::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::iterator_category::type, + boost::range_category::type + >::value)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::iterator_category::type, + boost::range_category::type + >::value)); +#endif +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range range_category meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_category)); + + return test; +} diff --git a/libs/range/test/combine.cpp b/libs/range/test/combine.cpp new file mode 100644 index 00000000..11f674b5 --- /dev/null +++ b/libs/range/test/combine.cpp @@ -0,0 +1,160 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014 +// +// Copyright Thorsten Ottosen 2006. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include + +#include +#include +#include +#include + +namespace boost_range_test +{ + namespace + { + +template +void test_combine2() +{ + std::vector v; + std::list l; + + for (int i = 0; i < 10; ++i) + { + v.push_back(i); + l.push_back(i * 2); + } + + ContRef1& in1 = v; + ContRef2& in2 = l; + + std::vector > output; + boost::push_back(output, boost::combine(in1, in2)); + + int index = 0; + int i1, i2; + BOOST_FOREACH(boost::tie(i1,i2), output) + { + BOOST_CHECK_EQUAL(i1, index); + BOOST_CHECK_EQUAL(i2, index * 2); + ++index; + } +} + +template +void test_combine3() +{ + std::vector v1; + std::vector v2; + std::vector v3; + + for (int i = 0; i < 10; ++i) + { + v1.push_back(i); + v2.push_back(i * 2); + v3.push_back(i * 3); + } + + ContRef1& in1 = v1; + ContRef2& in2 = v2; + ContRef3& in3 = v3; + + std::vector > output; + boost::push_back(output, boost::combine(in1, in2, in3)); + + int index = 0; + int i1, i2, i3; + + BOOST_FOREACH(boost::tie(i1,i2,i3), output) + { + BOOST_CHECK_EQUAL(i1, index); + BOOST_CHECK_EQUAL(i2, index * 2); + BOOST_CHECK_EQUAL(i3, index * 3); + ++index; + } +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite(int, char*[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE( "Boost.Range combine() test suite" ); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine2< + const std::vector, const std::list >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine2< + const std::vector, std::list >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine2< + std::vector, const std::list >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine2< + std::vector, std::list >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + std::vector, + std::vector, + std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + std::vector, + std::vector, + const std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + std::vector, + const std::vector, + std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + std::vector, + const std::vector, + const std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + const std::vector, + std::vector, + std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + const std::vector, + std::vector, + const std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + const std::vector, + const std::vector, + std::vector >))); + + test->add(BOOST_TEST_CASE(( + &boost_range_test::test_combine3< + const std::vector, + const std::vector, + const std::vector >))); + + return test; +} diff --git a/libs/range/test/compat2.cpp b/libs/range/test/compat2.cpp new file mode 100644 index 00000000..feaa047b --- /dev/null +++ b/libs/range/test/compat2.cpp @@ -0,0 +1,75 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include +#include + +enum Container {}; +enum String {}; + +template< typename T > +struct range_iterator; + +template<> +struct range_iterator +{ + template< typename C > + struct pts + { + typedef BOOST_DEDUCED_TYPENAME C::iterator type; + }; +}; + +template<> +struct range_iterator +{ + template< typename C > + struct pts + { + typedef C type; + }; +}; + +template< typename C > +class iterator_of +{ +public: + typedef BOOST_DEDUCED_TYPENAME range_iterator::BOOST_NESTED_TEMPLATE pts::type type; +}; + +#include + +void compat1() +{ + std::vector v; + iterator_of< std::vector >::type i = v.begin(); + boost::ignore_unused_variable_warning(i); +} + +#include + +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &compat1 ) ); + + return test; +} + + + + + + diff --git a/libs/range/test/compat3.cpp b/libs/range/test/compat3.cpp new file mode 100644 index 00000000..e4e4c834 --- /dev/null +++ b/libs/range/test/compat3.cpp @@ -0,0 +1,75 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include +#include + +enum Container {}; +enum String {}; + +template< typename T > +struct range_iterator; + +template<> +struct range_iterator +{ + template< typename C > + struct pts + { + typedef BOOST_DEDUCED_TYPENAME C::iterator type; + }; +}; + +template<> +struct range_iterator +{ + template< typename C > + struct pts + { + typedef C type; + }; +}; + +template< typename C > +class iterator_of +{ +public: + typedef BOOST_DEDUCED_TYPENAME range_iterator:: template pts::type type; +}; + +#include + +void compat1() +{ + std::vector v; + iterator_of< std::vector >::type i = v.begin(); + boost::ignore_unused_variable_warning(i); +} + +#include + +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &compat1 ) ); + + return test; +} + + + + + + diff --git a/libs/range/test/compile_fail/adaptor/adjacent_filtered_concept.cpp b/libs/range/test/compile_fail/adaptor/adjacent_filtered_concept.cpp new file mode 100644 index 00000000..e67215df --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/adjacent_filtered_concept.cpp @@ -0,0 +1,39 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +namespace +{ + +struct always_true +{ + typedef bool result_type; + + bool operator()(int, int) const + { + return true; + } +}; + +} // anonymous namespace + +int main(int, const char**) +{ + using boost::range::unit_test::mock_range; + using boost::adaptors::adjacent_filtered; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adjacent_filtered adaptor takes at least a + // ForwardRange. + return (mock_range() | + adjacent_filtered(always_true())).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/adjacent_filtered_concept2.cpp b/libs/range/test/compile_fail/adaptor/adjacent_filtered_concept2.cpp new file mode 100644 index 00000000..160f7c9d --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/adjacent_filtered_concept2.cpp @@ -0,0 +1,39 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +namespace +{ + +struct always_true +{ + typedef bool result_type; + + bool operator()(int, int) const + { + return true; + } +}; + +} // anonymous namespace + +int main(int, const char**) +{ + using boost::range::unit_test::mock_const_range; + using boost::adaptors::adjacent_filtered; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adjacent_filtered adaptor takes at least a + // ForwardRange. + return (mock_const_range() | + adjacent_filtered(always_true())).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/adjacent_filtered_concept3.cpp b/libs/range/test/compile_fail/adaptor/adjacent_filtered_concept3.cpp new file mode 100644 index 00000000..310ac21c --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/adjacent_filtered_concept3.cpp @@ -0,0 +1,40 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +namespace +{ + +struct always_true +{ + typedef bool result_type; + + bool operator()(int, int) const + { + return true; + } +}; + +} // anonymous namespace + +int main(int, const char**) +{ + using boost::range::unit_test::mock_range; + using boost::adaptors::adjacent_filter; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adjacent_filtered adaptor takes at least a + // ForwardRange. + return adjacent_filter( + mock_range(), + always_true()).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/adjacent_filtered_concept4.cpp b/libs/range/test/compile_fail/adaptor/adjacent_filtered_concept4.cpp new file mode 100644 index 00000000..f84b31ec --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/adjacent_filtered_concept4.cpp @@ -0,0 +1,40 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +namespace +{ + +struct always_true +{ + typedef bool result_type; + + bool operator()(int, int) const + { + return true; + } +}; + +} // anonymous namespace + +int main(int, const char**) +{ + using boost::range::unit_test::mock_const_range; + using boost::adaptors::adjacent_filter; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adjacent_filtered adaptor takes at least a + // ForwardRange. + return adjacent_filter( + mock_const_range(), + always_true()).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/copied_concept.cpp b/libs/range/test/compile_fail/adaptor/copied_concept.cpp new file mode 100644 index 00000000..27e7f72d --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/copied_concept.cpp @@ -0,0 +1,24 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_range; + using boost::adaptors::copied; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a RandomAccessRange. + return (mock_range() | + copied(0,1)).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/copied_concept2.cpp b/libs/range/test/compile_fail/adaptor/copied_concept2.cpp new file mode 100644 index 00000000..5df8ab6b --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/copied_concept2.cpp @@ -0,0 +1,24 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_const_range; + using boost::adaptors::copied; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a RandomAccessRange. + return (mock_const_range() | + copied(0,1)).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/copied_concept3.cpp b/libs/range/test/compile_fail/adaptor/copied_concept3.cpp new file mode 100644 index 00000000..da1659fb --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/copied_concept3.cpp @@ -0,0 +1,23 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_range; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a RandomAccessRange. + return boost::adaptors::copy( + mock_range(), 0, 1).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/copied_concept4.cpp b/libs/range/test/compile_fail/adaptor/copied_concept4.cpp new file mode 100644 index 00000000..3df0a6c4 --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/copied_concept4.cpp @@ -0,0 +1,24 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_const_range; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a RandomAccessRange. + return boost::adaptors::copy( + mock_const_range(), + 0, 1).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/mock_iterator.hpp b/libs/range/test/compile_fail/adaptor/mock_iterator.hpp new file mode 100644 index 00000000..97f67a91 --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/mock_iterator.hpp @@ -0,0 +1,82 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// +#ifndef BOOST_RANGE_UNIT_TEST_ADAPTOR_MOCK_ITERATOR_HPP_INCLUDED +#define BOOST_RANGE_UNIT_TEST_ADAPTOR_MOCK_ITERATOR_HPP_INCLUDED + +#include + +namespace boost +{ + namespace range + { + namespace unit_test + { + +template +class mock_iterator + : public boost::iterator_facade< + mock_iterator, + int, + TraversalTag, + const int& + > +{ +public: + mock_iterator() + : m_value(0) + { + } + + explicit mock_iterator(int value) + : m_value(value) + { + } + +private: + + void increment() + { + ++m_value; + } + + void decrement() + { + --m_value; + } + + bool equal(const mock_iterator& other) const + { + return m_value == other.m_value; + } + + void advance(std::ptrdiff_t offset) + { + m_value += offset; + } + + std::ptrdiff_t distance_to(const mock_iterator& other) const + { + return other.m_value - m_value; + } + + const int& dereference() const + { + return m_value; + } + + int m_value; + friend class boost::iterator_core_access; +}; + + } // namespace unit_test + } // namespace range +} // namespace boost + +#endif // include guard diff --git a/libs/range/test/compile_fail/adaptor/mock_range.hpp b/libs/range/test/compile_fail/adaptor/mock_range.hpp new file mode 100644 index 00000000..18fe2fa3 --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/mock_range.hpp @@ -0,0 +1,50 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// +#ifndef BOOST_RANGE_UNIT_TEST_ADAPTOR_MOCK_RANGE_HPP_INCLUDED +#define BOOST_RANGE_UNIT_TEST_ADAPTOR_MOCK_RANGE_HPP_INCLUDED + +#include "mock_iterator.hpp" +#include + +namespace boost +{ + namespace range + { + namespace unit_test + { + +// Make a non-empty range that models the corresponding range concept. +// This is only useful in unit tests. It is main use is to help test concepts +// assertions are present. +template +iterator_range >& + mock_range() +{ + static iterator_range > instance( + mock_iterator(0), + mock_iterator(1)); + return instance; +} + +template +const iterator_range >& + mock_const_range() +{ + static iterator_range > instance( + mock_iterator(0), + mock_iterator(1)); + return instance; +} + + } // namespace unit_test + } // namespace range +} // namespace boost + +#endif // include guard diff --git a/libs/range/test/compile_fail/adaptor/reversed_concept.cpp b/libs/range/test/compile_fail/adaptor/reversed_concept.cpp new file mode 100644 index 00000000..5ad00419 --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/reversed_concept.cpp @@ -0,0 +1,23 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_range; + using boost::adaptors::reversed; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a BidirectionalRange. + return (mock_range() | reversed).front(); +} + diff --git a/libs/range/test/compile_fail/adaptor/reversed_concept2.cpp b/libs/range/test/compile_fail/adaptor/reversed_concept2.cpp new file mode 100644 index 00000000..e2b8cb6f --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/reversed_concept2.cpp @@ -0,0 +1,23 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_const_range; + using boost::adaptors::reversed; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a BidirectionalRange. + return (mock_const_range() | reversed).front(); +} + diff --git a/libs/range/test/compile_fail/adaptor/reversed_concept3.cpp b/libs/range/test/compile_fail/adaptor/reversed_concept3.cpp new file mode 100644 index 00000000..619dfa8a --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/reversed_concept3.cpp @@ -0,0 +1,23 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_range; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a BidirectionalRange. + return boost::adaptors::reverse( + mock_range()).front(); +} + diff --git a/libs/range/test/compile_fail/adaptor/reversed_concept4.cpp b/libs/range/test/compile_fail/adaptor/reversed_concept4.cpp new file mode 100644 index 00000000..0e183eea --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/reversed_concept4.cpp @@ -0,0 +1,23 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_const_range; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a BidirectionalRange. + return boost::adaptors::reverse( + mock_const_range()).front(); +} + diff --git a/libs/range/test/compile_fail/adaptor/sliced_concept.cpp b/libs/range/test/compile_fail/adaptor/sliced_concept.cpp new file mode 100644 index 00000000..08a653f4 --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/sliced_concept.cpp @@ -0,0 +1,23 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_range; + using boost::adaptors::sliced; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a RandomAccessRange. + return (mock_range() | + sliced(0,1)).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/sliced_concept2.cpp b/libs/range/test/compile_fail/adaptor/sliced_concept2.cpp new file mode 100644 index 00000000..99650203 --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/sliced_concept2.cpp @@ -0,0 +1,23 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_const_range; + using boost::adaptors::sliced; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a RandomAccessRange. + return (mock_const_range() | + sliced(0,1)).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/sliced_concept3.cpp b/libs/range/test/compile_fail/adaptor/sliced_concept3.cpp new file mode 100644 index 00000000..12749113 --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/sliced_concept3.cpp @@ -0,0 +1,22 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_range; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a RandomAccessRange. + return boost::adaptors::slice( + mock_range(), 0, 1).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/sliced_concept4.cpp b/libs/range/test/compile_fail/adaptor/sliced_concept4.cpp new file mode 100644 index 00000000..c7f8206a --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/sliced_concept4.cpp @@ -0,0 +1,22 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_const_range; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a RandomAccessRange. + return boost::adaptors::slice( + mock_const_range(), 0, 1).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/uniqued_concept.cpp b/libs/range/test/compile_fail/adaptor/uniqued_concept.cpp new file mode 100644 index 00000000..bbaaf118 --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/uniqued_concept.cpp @@ -0,0 +1,22 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_range; + using boost::adaptors::uniqued; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a ForwardRange. + return (mock_range() | uniqued).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/uniqued_concept2.cpp b/libs/range/test/compile_fail/adaptor/uniqued_concept2.cpp new file mode 100644 index 00000000..a390d136 --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/uniqued_concept2.cpp @@ -0,0 +1,23 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_const_range; + using boost::adaptors::uniqued; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a ForwardRange. + return (mock_const_range() | + uniqued).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/uniqued_concept3.cpp b/libs/range/test/compile_fail/adaptor/uniqued_concept3.cpp new file mode 100644 index 00000000..fea058cc --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/uniqued_concept3.cpp @@ -0,0 +1,22 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_range; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a ForwardRange. + return boost::adaptors::unique( + mock_range()).front(); +} diff --git a/libs/range/test/compile_fail/adaptor/uniqued_concept4.cpp b/libs/range/test/compile_fail/adaptor/uniqued_concept4.cpp new file mode 100644 index 00000000..1e023904 --- /dev/null +++ b/libs/range/test/compile_fail/adaptor/uniqued_concept4.cpp @@ -0,0 +1,22 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include "mock_range.hpp" +#include + +int main(int, const char**) +{ + using boost::range::unit_test::mock_const_range; + + // This next line should fail when Boost.Range concept checking is + // enabled since the adaptor takes at least a ForwardRange. + return boost::adaptors::unique( + mock_const_range()).front(); +} diff --git a/libs/range/test/compile_fail/iterator_range1.cpp b/libs/range/test/compile_fail/iterator_range1.cpp new file mode 100644 index 00000000..2e5eec37 --- /dev/null +++ b/libs/range/test/compile_fail/iterator_range1.cpp @@ -0,0 +1,22 @@ +// Boost.Range library +// +// Copyright Neil Groves 2011. Use, modification and distribution is subject +// to 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) +// +// For more information, see http://www.boost.org/libs/range +// + +#include + +namespace iterator_range_test_detail +{ + void check_iterator_range_doesnt_convert_pointers() + { + double source[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 }; + boost::iterator_range rng = boost::make_iterator_range(source); + boost::ignore_unused_variable_warning(rng); + } +} + diff --git a/libs/range/test/const_iterator.cpp b/libs/range/test/const_iterator.cpp new file mode 100644 index 00000000..63238c88 --- /dev/null +++ b/libs/range/test/const_iterator.cpp @@ -0,0 +1,61 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_const_iterator() +{ + typedef std::vector cont; + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::const_iterator, + boost::range_const_iterator::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::const_iterator, + boost::range_const_iterator::type + >::value)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::const_iterator, + boost::range_const_iterator::type + >::value)); +#endif +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range range_const_iterator meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_const_iterator)); + + return test; +} diff --git a/libs/range/test/const_ranges.cpp b/libs/range/test/const_ranges.cpp new file mode 100644 index 00000000..24108698 --- /dev/null +++ b/libs/range/test/const_ranges.cpp @@ -0,0 +1,59 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include + +template< class T > +const T& as_const( const T& r ) +{ + return r; +} + +void check_const_ranges() +{ + std::string foo( "foo" ); + const std::string bar( "bar" ); + + BOOST_CHECK( boost::const_begin( foo ) == boost::begin( as_const( foo ) ) ); + BOOST_CHECK( boost::const_end( foo ) == boost::end( as_const( foo ) ) ); + BOOST_CHECK( boost::const_rbegin( foo ) == boost::rbegin( as_const( foo ) ) ); + BOOST_CHECK( boost::const_rend( foo ) == boost::rend( as_const( foo ) ) ); + + BOOST_CHECK( boost::const_begin( bar ) == boost::begin( as_const( bar ) ) ); + BOOST_CHECK( boost::const_end( bar ) == boost::end( as_const( bar ) ) ); + BOOST_CHECK( boost::const_rbegin( bar ) == boost::rbegin( as_const( bar ) ) ); + BOOST_CHECK( boost::const_rend( bar ) == boost::rend( as_const( bar ) ) ); + +} + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &check_const_ranges ) ); + + return test; +} + + + + + diff --git a/libs/range/test/const_reverse_iterator.cpp b/libs/range/test/const_reverse_iterator.cpp new file mode 100644 index 00000000..4fb484f3 --- /dev/null +++ b/libs/range/test/const_reverse_iterator.cpp @@ -0,0 +1,63 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#define BOOST_ALLOW_DEPRECATED_HEADERS +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_const_reverse_iterator() +{ + typedef std::vector cont; + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::reverse_iterator, + boost::range_const_reverse_iterator::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::reverse_iterator, + boost::range_const_reverse_iterator::type + >::value)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::reverse_iterator, + boost::range_const_reverse_iterator::type + >::value)); +#endif +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE( + "Boost.Range range_const_reverse_iterator meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_const_reverse_iterator)); + + return test; +} diff --git a/libs/range/test/counting_range.cpp b/libs/range/test/counting_range.cpp new file mode 100644 index 00000000..d1f1d3f5 --- /dev/null +++ b/libs/range/test/counting_range.cpp @@ -0,0 +1,90 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +// Disable a warning from since this noise might +// stop us detecting a problem in our code. +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +namespace boost +{ + namespace + { + template + void counting_range_test_impl(int first, int last) + { + Container reference; + for (int i = first; i < last; ++i) + reference.push_back(i); + + Container test; + push_back( test, counting_range(first, last) ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end()); + } + + template + void counting_range_test_impl() + { + counting_range_test_impl(0, 0); + counting_range_test_impl(-1, -1); + counting_range_test_impl(-1, 0); + counting_range_test_impl(0, 1); + counting_range_test_impl(-100, 100); + counting_range_test_impl(50, 55); + } + + void counting_range_test_range() + { + std::vector v; + for (int i = 0; i < 10; ++i) + v.push_back(i); + + std::vector::iterator> x; + push_back(x, counting_range(v)); + + std::vector t; + push_back(t, x | boost::adaptors::indirected); + + BOOST_CHECK_EQUAL_COLLECTIONS(t.begin(), t.end(), + v.begin(), v.end()); + } + } + + void counting_range_test() + { + counting_range_test_impl >(); + counting_range_test_impl >(); + counting_range_test_impl >(); + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.counting_range" ); + + test->add( BOOST_TEST_CASE( &boost::counting_range_test ) ); + + return test; +} diff --git a/libs/range/test/difference_type.cpp b/libs/range/test/difference_type.cpp new file mode 100644 index 00000000..556250ac --- /dev/null +++ b/libs/range/test/difference_type.cpp @@ -0,0 +1,61 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_difference() +{ + typedef std::vector cont; + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::difference_type, + boost::range_difference::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::difference_type, + boost::range_difference::type + >::value)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::difference_type, + boost::range_difference::type + >::value)); +#endif +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range range_difference meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_difference)); + + return test; +} diff --git a/libs/range/test/end.cpp b/libs/range/test/end.cpp new file mode 100644 index 00000000..b73a5320 --- /dev/null +++ b/libs/range/test/end.cpp @@ -0,0 +1,119 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include + +namespace mock_std +{ + template + inline BOOST_DEDUCED_TYPENAME boost::range_iterator::type + end(SinglePassRange& rng) + { + return rng.end(); + } + + template + inline BOOST_DEDUCED_TYPENAME boost::range_iterator::type + end(const SinglePassRange& rng) + { + return rng.end(); + } + + template + void mock_algorithm_using_end(const SinglePassRange& rng) + { + BOOST_CHECK( end(rng) == rng.end() ); + } + + template + void mock_algorithm_using_end(SinglePassRange& rng) + { + BOOST_CHECK( end(rng) == rng.end() ); + } +} + +namespace boost +{ +#ifdef BOOST_RANGE_SIMULATE_END_WITHOUT_ADL_NAMESPACE_BARRIER + template + inline BOOST_DEDUCED_TYPENAME range_iterator::type + end(SinglePassRange& rng) + { + return rng.end(); + } + + template + inline BOOST_DEDUCED_TYPENAME range_iterator::type + end(const SinglePassRange& rng) + { + return rng.end(); + } +#endif + + class MockTestEndCollection + { + public: + typedef char value_type; + typedef const char* const_pointer; + typedef char* pointer; + typedef const_pointer const_iterator; + typedef pointer iterator; + + MockTestEndCollection() + : m_first() + , m_last() + { + } + + const_iterator begin() const { return m_first; } + iterator begin() { return m_first; } + const_iterator end() const { return m_last; } + iterator end() { return m_last; } + + private: + iterator m_first; + iterator m_last; + }; +} + +namespace +{ + void test_range_end_adl_avoidance() + { + boost::MockTestEndCollection c; + const boost::MockTestEndCollection& const_c = c; + mock_std::mock_algorithm_using_end(const_c); + mock_std::mock_algorithm_using_end(c); + } +} + +using boost::unit_test::test_suite; + +boost::unit_test::test_suite* +init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = BOOST_TEST_SUITE( "Range Test Suite - end() ADL namespace barrier" ); + + test->add( BOOST_TEST_CASE( &test_range_end_adl_avoidance ) ); + + return test; +} + + diff --git a/libs/range/test/extension_mechanism.cpp b/libs/range/test/extension_mechanism.cpp new file mode 100644 index 00000000..7c735c3e --- /dev/null +++ b/libs/range/test/extension_mechanism.cpp @@ -0,0 +1,109 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include + +// +// Generic range algorithm +// +template< class Rng > +typename boost::range_iterator::type foo_algo( Rng& r ) +{ + // + // This will only compile for Rng = UDT if the qualified calls + // find boost_range_XXX via ADL. + // + return boost::size(r) == 0u ? boost::begin(r) : boost::end(r); +} + +namespace Foo +{ + // + // Our sample UDT + // + struct X + { + X() : vec() { } + + typedef std::vector data_t; + typedef data_t::iterator iterator; + typedef data_t::const_iterator const_iterator; + + data_t vec; + + void push_back( int i ) + { vec.push_back(i); } + }; + + // + // The required functions. No type-traits need + // to be defined because X defines the proper set of + // nested types. + // + inline X::iterator range_begin( X& x ) + { + return x.vec.begin(); + } + + + inline X::const_iterator range_begin( const X& x ) + { + return x.vec.begin(); + } + + + inline X::iterator range_end( X& x ) + { + return x.vec.end(); + } + + inline X::const_iterator range_end( const X& x ) + { + return x.vec.end(); + } + +} + +void check_extension() +{ + Foo::X x; + x.push_back(3); + const Foo::X x2; + + foo_algo( x ); + foo_algo( x2 ); +} + +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &check_extension ) ); + + return test; +} + + + + + diff --git a/libs/range/test/extension_size.cpp b/libs/range/test/extension_size.cpp new file mode 100644 index 00000000..dbff55b4 --- /dev/null +++ b/libs/range/test/extension_size.cpp @@ -0,0 +1,224 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include +#include +#include +#include + +namespace boost_range_extension_size_test +{ + class FooWithoutSize + { + typedef std::list impl_t; + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::range_size >::type, + std::list::size_type + >::value)); + + typedef impl_t::const_iterator const_iterator; + typedef impl_t::iterator iterator; + + public: + friend inline const_iterator range_begin(const FooWithoutSize& obj) { return obj.m_impl.begin(); } + friend inline iterator range_begin(FooWithoutSize& obj) { return obj.m_impl.begin(); } + friend inline const_iterator range_end(const FooWithoutSize& obj) { return obj.m_impl.end(); } + friend inline iterator range_end(FooWithoutSize& obj){ return obj.m_impl.end(); } + + private: + impl_t m_impl; + }; + + template + class FooWithSize + { + public: + typedef SizeType size_type; + typedef boost::uint8_t* iterator; + typedef const boost::uint8_t* const_iterator; + + const_iterator begin() const; + iterator begin(); + const_iterator end() const; + iterator end(); + }; + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::uint8_t, + boost::range_size >::type + >::value + )); + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::uint16_t, + boost::range_size >::type + >::value + )); + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::uint32_t, + boost::range_size >::type + >::value + )); + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::uint64_t, + boost::range_size >::type + >::value + )); + + class UdtSizeType + { + public: + typedef boost::uint16_t value_type; + + UdtSizeType() : value_(0) { } + UdtSizeType(value_type value) : value_(value) { } + + operator value_type() const { return value_; } + + private: + value_type value_; + }; + + BOOST_STATIC_ASSERT(( + boost::is_same< + UdtSizeType, + boost::range_size >::type + >::value + )); + + class Foo2WithoutSize + { + public: + struct const_iterator + { + typedef std::forward_iterator_tag iterator_category; + typedef boost::int8_t difference_type; + typedef boost::int16_t value_type; + typedef value_type* pointer; + typedef value_type& reference; + + reference operator*() const; + pointer operator->() const; + const_iterator& operator++(); + const_iterator operator++(int); + bool operator==(const const_iterator&) const; + bool operator!=(const const_iterator&) const; + }; + + struct iterator : const_iterator + { + typedef const value_type* pointer; + typedef const value_type& reference; + + reference operator*() const; + pointer operator->() const; + + iterator& operator++(); + iterator operator++(int); + + bool operator==(const iterator&) const; + bool operator!=(const iterator&) const; + }; + + const_iterator begin() const; + iterator begin(); + const_iterator end() const; + iterator end(); + }; + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::uint8_t, + boost::range_size< + ::boost_range_extension_size_test::Foo2WithoutSize>::type + >::value + )); +} + +namespace boost +{ + template<> struct range_iterator + { + typedef std::list::const_iterator type; + }; + + template<> struct range_iterator< ::boost_range_extension_size_test::FooWithoutSize> + { + typedef std::list::iterator type; + }; +} + +namespace boost_range_extension_size_test +{ + inline boost::range_size::type + range_calculate_size(const FooWithoutSize& rng) + { + return 2u; + } +} + +BOOST_STATIC_ASSERT(( + boost::is_same< + boost::make_unsigned::type, + boost::range_size< + boost_range_extension_size_test::FooWithoutSize>::type + >::value +)); + +typedef boost::make_unsigned::type t1; +typedef boost::range_size::type t1; + +namespace +{ + +void check_size_works_with_random_access() +{ + std::vector container; + container.push_back(1); + BOOST_CHECK_EQUAL( boost::size(container), 1u ); +} + +void check_extension_size() +{ + BOOST_CHECK_EQUAL( boost::size(boost_range_extension_size_test::FooWithoutSize()), 2u ); +} + +} // anonymous namespace + +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &check_size_works_with_random_access )); + test->add( BOOST_TEST_CASE( &check_extension_size ) ); + + return test; +} diff --git a/libs/range/test/has_range_iterator.cpp b/libs/range/test/has_range_iterator.cpp new file mode 100644 index 00000000..2efc88b0 --- /dev/null +++ b/libs/range/test/has_range_iterator.cpp @@ -0,0 +1,68 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include + +#include +#include + +#include + +namespace +{ + class MockClassWithoutIterators {}; + + template + void test_has_range_iterator_impl(const bool expected_value) + { + BOOST_CHECK_EQUAL( boost::has_range_iterator::value, expected_value ); + } + + template + void test_has_range_const_iterator_impl(const bool expected_value) + { + BOOST_CHECK_EQUAL( boost::has_range_const_iterator::value, expected_value ); + } + + void test_has_range_iterator() + { + test_has_range_iterator_impl< std::vector >(true); + test_has_range_iterator_impl< MockClassWithoutIterators >(false); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + test_has_range_iterator_impl&&>(true); + test_has_range_iterator_impl(false); +#endif + } + + void test_has_range_const_iterator() + { + test_has_range_const_iterator_impl< std::vector >(true); + test_has_range_const_iterator_impl< MockClassWithoutIterators >(false); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + test_has_range_const_iterator_impl&&>(true); + test_has_range_const_iterator_impl(false); +#endif + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.has_range_iterator" ); + + test->add(BOOST_TEST_CASE(&test_has_range_iterator)); + test->add(BOOST_TEST_CASE(&test_has_range_const_iterator)); + + return test; +} diff --git a/libs/range/test/irange.cpp b/libs/range/test/irange.cpp new file mode 100644 index 00000000..7e1a5644 --- /dev/null +++ b/libs/range/test/irange.cpp @@ -0,0 +1,191 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include +#include +#include +#include + +namespace boost +{ + // Test an integer range with a step size of 1. + template + void test_irange_impl(Integer last) + { + std::vector reference; + for (Integer i = static_cast(0); i < last; ++i) + { + reference.push_back(i); + } + + std::vector test; + boost::push_back(test, boost::irange(last)); + + BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), + reference.begin(), reference.end() ); + } + + // Test an integer range with a step size of 1. + template + void test_irange_impl(Integer first, Integer last) + { + std::vector reference; + for (Integer i = first; i < last; ++i) + { + reference.push_back(i); + } + + std::vector test; + boost::push_back(test, boost::irange(first, last)); + + BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), + reference.begin(), reference.end() ); + } + + // Test an integer range with a runtime specified step size. + template + void test_irange_impl(IntegerInput first, IntegerInput last, int step) + { + BOOST_ASSERT( step != 0 ); + + // Skip tests that have negative values if the type is + // unsigned + if ((static_cast(static_cast(first)) != first) + || (static_cast(static_cast(last)) != last)) + return; + + std::vector reference; + + const std::ptrdiff_t first_p = static_cast(first); + const std::ptrdiff_t last_p = static_cast(last); + const std::ptrdiff_t step_p = static_cast(step); + for (std::ptrdiff_t current_value = first_p; + step_p >= 0 ? current_value < last_p : current_value > last_p; + current_value += step_p) + reference.push_back(current_value); + + std::vector test; + boost::push_back(test, boost::irange(first, last, step)); + + BOOST_CHECK_EQUAL_COLLECTIONS( test.begin(), test.end(), + reference.begin(), reference.end() ); + } + + // Test driver function that for an integer range [first, last) + // drives the test implementation through various integer + // types. + void test_irange(int last) + { + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + test_irange_impl(last); + } + + + // Test driver function that for an integer range [first, last) + // drives the test implementation through various integer + // types. + void test_irange(int first, int last) + { + test_irange_impl(first,last); + test_irange_impl(first, last); + test_irange_impl(first, last); + test_irange_impl(first, last); + test_irange_impl(first, last); + test_irange_impl(first, last); + test_irange_impl(first, last); + test_irange_impl(first, last); + } + + // Test driver function that for an integer range [first, last) + // drives the test implementation through various integer + // types step_size items at a time. + void test_irange(int first, int last, int step_size) + { + BOOST_ASSERT( step_size != 0 ); + test_irange_impl(first, last, step_size); + test_irange_impl(first, last, step_size); + test_irange_impl(first, last, step_size); + test_irange_impl(first, last, step_size); + test_irange_impl(first, last, step_size); + test_irange_impl(first, last, step_size); + test_irange_impl(first, last, step_size); + test_irange_impl(first, last, step_size); + } + + // Implementation of the unit test for the integer range + // function. + // This starts the test drivers to drive a set of integer types + // for a combination of range values chosen to exercise a large + // number of implementation branches. + void irange_unit_test() + { + // Test the single-step version of irange(last) + test_irange(0); + test_irange(1); + test_irange(10); + + // Test the single-step version of irange(first, last) + test_irange(0, 0); + test_irange(0, 1); + test_irange(0, 10); + test_irange(1, 1); + test_irange(1, 2); + test_irange(1, 11); + + // Test the n-step version of irange(first, last, step-size) + test_irange(0, 0, 1); + test_irange(0, 0, -1); + test_irange(0, 10, 1); + test_irange(10, 0, -1); + test_irange(0, 2, 2); + test_irange(2, 0, -2); + test_irange(0, 9, 2); + test_irange(9, 0, -2); + test_irange(-9, 0, 2); + test_irange(-9, 9, 2); + test_irange(9, -9, -2); + test_irange(10, 20, 5); + test_irange(20, 10, -5); + + test_irange(0, 0, 3); + test_irange(0, 1, 3); + test_irange(0, 2, 3); + test_irange(0, 3, 3); + test_irange(0, 4, 3); + test_irange(0, 10, 3); + + test_irange(0, 0, -3); + test_irange(0, -1, -3); + test_irange(0, -2, -3); + test_irange(0, -3, -3); + test_irange(0, -4, -3); + test_irange(0, -10, -3); + } +} // namespace boost + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.irange" ); + + test->add(BOOST_TEST_CASE( &boost::irange_unit_test )); + + return test; +} diff --git a/libs/range/test/istream_range.cpp b/libs/range/test/istream_range.cpp new file mode 100644 index 00000000..7d10313f --- /dev/null +++ b/libs/range/test/istream_range.cpp @@ -0,0 +1,58 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + template + void test_istream_range_impl() + { + std::basic_stringstream s; + std::vector reference; + for (int i = 0; i < 10; ++i) + { + reference.push_back(i); + s << i << CharT(' '); + } + + std::vector target; + boost::push_back(target, boost::range::istream_range(s)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + target.begin(), target.end() ); + } + + // Test an istream range. + void test_istream_range() + { + test_istream_range_impl(); + test_istream_range_impl(); + } + +} // namespace anonymous namespace + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.istream_range" ); + + test->add(BOOST_TEST_CASE( &test_istream_range )); + + return test; +} diff --git a/libs/range/test/iterator.cpp b/libs/range/test/iterator.cpp new file mode 100644 index 00000000..76c915a9 --- /dev/null +++ b/libs/range/test/iterator.cpp @@ -0,0 +1,61 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_iterator() +{ + typedef std::vector cont; + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::iterator, + boost::range_iterator::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::const_iterator, + boost::range_iterator::type + >::value)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::iterator, + boost::range_iterator::type + >::value)); +#endif +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range range_iterator meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_iterator)); + + return test; +} diff --git a/libs/range/test/iterator_ext.cpp b/libs/range/test/iterator_ext.cpp new file mode 100644 index 00000000..820bf2a4 --- /dev/null +++ b/libs/range/test/iterator_ext.cpp @@ -0,0 +1,153 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + +struct point +{ + int x; + int y; +}; + +class shape +{ +public: + virtual ~shape() + { + } + + const std::vector& points() const + { + return m_points; + } + +private: + std::vector m_points; +}; + +class rectangle : public shape +{ +}; + +class circle : public shape +{ +}; + +class container +{ + typedef std::vector impl_t; +}; + +} // namespace boost_range_test + +namespace boost +{ + template + struct range_mutable_iterator< + T, + typename boost::enable_if< + boost::is_base_of< + boost_range_test::shape, + typename boost::remove_reference< + typename boost::remove_cv::type + >::type + > + >::type + > + { + typedef std::vector::iterator type; + }; + + template + struct range_const_iterator< + T, + typename boost::enable_if< + boost::is_base_of< + boost_range_test::shape, + typename boost::remove_reference< + typename boost::remove_cv::type + >::type + > + >::type + > + { + typedef std::vector::const_iterator type; + }; + + template<> + struct range_mutable_iterator + { + typedef std::vector::iterator type; + }; + + template<> + struct range_const_iterator + { + typedef std::vector::const_iterator type; + }; +} + +namespace boost_range_test +{ + template + void test_iterator_impl() + { + BOOST_STATIC_ASSERT(( + boost::is_same< + std::vector::iterator, + typename boost::range_iterator::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + std::vector::const_iterator, + typename boost::range_iterator::type + >::value)); + + #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + std::vector::iterator, + typename boost::range_iterator::type + >::value)); + #endif + } + + void test_iterator() + { + test_iterator_impl(); + test_iterator_impl(); + test_iterator_impl(); + + test_iterator_impl(); + } +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range range_iterator meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_iterator)); + + return test; +} diff --git a/libs/range/test/iterator_pair.cpp b/libs/range/test/iterator_pair.cpp new file mode 100644 index 00000000..19e5acd5 --- /dev/null +++ b/libs/range/test/iterator_pair.cpp @@ -0,0 +1,104 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void check_iterator_pair() +{ + typedef std::vector vec_t; + vec_t vec; + vec.push_back( 4 ); + typedef std::pair + pair_t; + typedef std::pair + const_pair_t; + typedef const pair_t const_pair_tt; + pair_t pair = std::make_pair( boost::begin( vec ), boost::end( vec ) ); + const_pair_t const_pair = std::make_pair( boost::begin( vec ), boost::end( vec ) ); + const_pair_tt constness_pair( pair ); + + + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_value::type, + std::iterator_traits::value_type>::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_iterator::type, pair_t::first_type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_const_iterator::type, pair_t::first_type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_difference::type, + std::iterator_traits::difference_type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_size::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_iterator::type, pair_t::first_type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_iterator::type, const_pair_t::first_type >::value )); + + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_value::type, + std::iterator_traits::value_type>::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_iterator::type, const_pair_tt::first_type >::value )); + // + // This behavior is not supported with v2. + //BOOST_STATIC_ASSERT(( is_same< range_const_iterator::type, const_pair_tt::first_type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_difference::type, + std::iterator_traits::difference_type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_size::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_iterator::type, const_pair_tt::first_type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_iterator::type, const_pair_tt::first_type >::value )); + + BOOST_CHECK( boost::begin( pair ) == pair.first ); + BOOST_CHECK( boost::end( pair ) == pair.second ); + BOOST_CHECK( boost::empty( pair ) == (pair.first == pair.second) ); + BOOST_CHECK( boost::size( pair ) == + static_cast( + std::distance(pair.first, pair.second)) ); + + BOOST_CHECK( boost::begin( const_pair ) == const_pair.first ); + BOOST_CHECK( boost::end( const_pair ) == const_pair.second ); + BOOST_CHECK( boost::empty( const_pair ) == (const_pair.first == const_pair.second) ); + BOOST_CHECK( boost::size( const_pair ) == + static_cast( + std::distance(const_pair.first, const_pair.second)) ); + + BOOST_CHECK( boost::begin( constness_pair ) == constness_pair.first ); + BOOST_CHECK( boost::end( constness_pair ) == constness_pair.second ); + BOOST_CHECK( boost::empty( constness_pair ) == (constness_pair.first == const_pair.second) ); + BOOST_CHECK( boost::size( constness_pair ) == + static_cast( + std::distance(constness_pair.first, + constness_pair.second)) ); +} + + +#include + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &check_iterator_pair ) ); + + return test; +} + + + + + + diff --git a/libs/range/test/iterator_range.cpp b/libs/range/test/iterator_range.cpp new file mode 100644 index 00000000..fd534bb7 --- /dev/null +++ b/libs/range/test/iterator_range.cpp @@ -0,0 +1,330 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen & Larry Evans 2003-2005. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +//#include + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void check_reference_type(); + +void check_iterator_range() +{ + + typedef std::string::iterator iterator; + typedef std::string::const_iterator const_iterator; + typedef boost::iterator_range irange; + typedef boost::iterator_range cirange; + std::string str = "hello world"; + const std::string cstr = "const world"; + irange r = boost::make_iterator_range( str ); + r = boost::make_iterator_range( str.begin(), str.end() ); + cirange r2 = boost::make_iterator_range( cstr ); + r2 = boost::make_iterator_range( cstr.begin(), cstr.end() ); + r2 = boost::make_iterator_range( str ); + + BOOST_CHECK( !r.empty() ); + BOOST_CHECK( !r2.empty() ); + +//#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +// if( !(bool)r ) +// BOOST_CHECK( false ); +// if( !(bool)r2 ) +// BOOST_CHECK( false ); +//#else + if( !r ) + BOOST_CHECK( false ); + if( !r2 ) + BOOST_CHECK( false ); +//#endif + + BOOST_CHECK_EQUAL( r.size(), boost::size( r ) ); + BOOST_CHECK_EQUAL( r2.size(), boost::size( r2 ) ); + + BOOST_CHECK_EQUAL( std::distance( r.begin(), r.end() ), + std::distance( boost::begin( r2 ), boost::end( r2 ) ) ); + std::cout << r << r2; + + +#ifndef BOOST_NO_STD_WSTRING + std::wcout << boost::make_iterator_range( std::wstring( L"a wide string" ) ) + << boost::make_iterator_range( L"another wide string" ); +#endif + + std::string res = boost::copy_range( r ); + BOOST_CHECK_EQUAL_COLLECTIONS( res.begin(), res.end(), r.begin(), r.end() ); + + irange rr = boost::make_iterator_range( str ); + BOOST_CHECK( rr.equal( r ) ); + + rr = boost::make_iterator_range( str.begin(), str.begin() + 5 ); + BOOST_CHECK( rr == boost::as_literal("hello") ); + BOOST_CHECK( rr != boost::as_literal("hell") ); + BOOST_CHECK( rr < boost::as_literal("hello dude") ); + BOOST_CHECK( boost::as_literal("hello") == rr ); + BOOST_CHECK( boost::as_literal("hell") != rr ); + BOOST_CHECK( ! (boost::as_literal("hello dude") < rr ) ); + irange rrr = rr; + BOOST_CHECK( rrr == rr ); + BOOST_CHECK( !( rrr != rr ) ); + BOOST_CHECK( !( rrr < rr ) ); + + const irange cr = boost::make_iterator_range( str ); + BOOST_CHECK_EQUAL( cr.front(), 'h' ); + BOOST_CHECK_EQUAL( cr.back(), 'd' ); + BOOST_CHECK_EQUAL( cr[1], 'e' ); + BOOST_CHECK_EQUAL( cr(1), 'e' ); + + rrr = boost::make_iterator_range( str, 1, -1 ); + BOOST_CHECK( rrr == boost::as_literal("ello worl") ); + rrr = boost::make_iterator_range( rrr, -1, 1 ); + BOOST_CHECK( rrr == str ); + + check_reference_type(); + + // Check that an iterator range can be instantiated with + // a pointer to an array as an iterator. + int arr[2][2]; + boost::make_iterator_range(arr, arr + 2); +} + +namespace iterator_range_test_detail +{ + struct less + { + template< class Left, class Right > + bool operator()(const Left& l, const Right& r) const + { + return l < r; + } + }; + + struct greater + { + template< class Left, class Right > + bool operator()(const Left& l, const Right& r) const + { + return l > r; + } + }; + + struct less_or_equal + { + template< class Left, class Right > + bool operator()(const Left& l, const Right& r) const + { + return l <= r; + } + }; + + struct greater_or_equal + { + template< class Left, class Right > + bool operator()(const Left& l, const Right& r) const + { + return l >= r; + } + }; + + struct equal_to + { + template< class Left, class Right > + bool operator()(const Left& l, const Right& r) const + { + return l == r; + } + }; + + struct not_equal_to + { + template< class Left, class Right > + bool operator()(const Left& l, const Right& r) const + { + return l != r; + } + }; + + template< class Pred > + void check_iterator_range_operators_impl(Pred pred) + { + std::vector vals; + vals.push_back(std::string()); + vals.push_back("a"); + vals.push_back("b"); + vals.push_back("z"); + vals.push_back("ab"); + vals.push_back("ba"); + vals.push_back("abc"); + vals.push_back("cba"); + vals.push_back("aa"); + vals.push_back("aaa"); + vals.push_back("aab"); + vals.push_back("bba"); + + typedef std::string::const_iterator citer; + typedef boost::iterator_range iter_range; + + typedef std::vector::const_iterator value_const_iterator; + value_const_iterator first_val = vals.begin(); + value_const_iterator last_val = vals.end(); + + for (value_const_iterator left_it = first_val; left_it != last_val; ++left_it) + { + const std::string& leftValue = *left_it; + for (value_const_iterator right_it = first_val; right_it != last_val; ++right_it) + { + const std::string& rightValue = *right_it; + iter_range left = boost::make_iterator_range(leftValue); + iter_range right = boost::make_iterator_range(rightValue); + + const bool reference = pred(leftValue, rightValue); + + BOOST_CHECK_EQUAL( pred(left, right), reference ); + BOOST_CHECK_EQUAL( pred(left, rightValue), reference ); + BOOST_CHECK_EQUAL( pred(leftValue, right), reference ); + } + } + } + + void check_iterator_range_from_array() + { + double source[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0 }; + boost::iterator_range rng = boost::make_iterator_range(source); + BOOST_CHECK_EQUAL_COLLECTIONS( rng.begin(), rng.end(), + source, source + 6 ); + } + + void check_make_iterator_range_n() + { + using boost::uint32_t; + + std::vector input; + for (uint32_t i = 0; i < 10u; ++i) + input.push_back(i); + + boost::iterator_range::iterator> rng = + boost::make_iterator_range_n(boost::begin(input), 8u); + + BOOST_CHECK(rng.begin() == input.begin()); + BOOST_CHECK(rng.end() == input.begin() + 8); + BOOST_CHECK_EQUAL(rng.size(), 8u); + + const std::vector& cinput = input; + + boost::iterator_range::const_iterator> crng = + boost::make_iterator_range_n(boost::begin(cinput), 8u); + + BOOST_CHECK(crng.begin() == cinput.begin()); + BOOST_CHECK(crng.end() == cinput.begin() + 8); + BOOST_CHECK_EQUAL(crng.size(), 8u); + } + +} // namespace iterator_range_test_detail + +template +inline void check_iterator_range_operator() +{ + iterator_range_test_detail::check_iterator_range_operators_impl( + Pred()); +} + +inline void test_advance() +{ + std::vector l; + l.push_back(1); + l.push_back(2); + typedef boost::iterator_range::iterator> rng_t; + + rng_t r1(l.begin(), l.end()); + BOOST_CHECK(r1.advance_begin(1).advance_end(-1).empty()); + + rng_t r2(l.begin(), l.end()); + BOOST_CHECK_EQUAL(r2.advance_begin(1).size(), 1u); + + rng_t r3(l.begin(), l.end()); + BOOST_CHECK_EQUAL(r3.advance_end(-1).size(), 1u); +} + +struct ptr_iterator + : boost::iterator_adaptor +{ + ptr_iterator() {} + ptr_iterator(int *p) : boost::iterator_adaptor(p) {} +private: + typedef void iterator; // To throw off the SFINAE mechanism in iterator_range +}; + +void test_sfinae() +{ + boost::iterator_range r(ptr_iterator(0), ptr_iterator(0)); +} + +// +// +// Check that constness is propagated correct from +// the iterator types. +// +// Test contributed by Larry Evans. +// + +template< class Container > +int test_iter_range( Container& a_cont ) +{ + typedef BOOST_DEDUCED_TYPENAME boost::range_iterator::type citer_type; + typedef boost::iterator_range riter_type; + riter_type a_riter( boost::make_iterator_range( a_cont ) ); + a_riter.front(); + a_riter.back(); + int i = a_riter[0]; + return i; +} + + + +void check_reference_type() +{ + typedef std::vector veci_type; + veci_type a_vec; + a_vec.push_back( 999 ); + test_iter_range(a_vec); + test_iter_range(a_vec); +} + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add(BOOST_TEST_CASE(&check_iterator_range)); + test->add(BOOST_TEST_CASE(&check_iterator_range_operator)); + test->add(BOOST_TEST_CASE(&check_iterator_range_operator)); + test->add(BOOST_TEST_CASE(&check_iterator_range_operator)); + test->add(BOOST_TEST_CASE(&check_iterator_range_operator)); + test->add(BOOST_TEST_CASE(&check_iterator_range_operator)); + test->add(BOOST_TEST_CASE(&check_iterator_range_operator)); + test->add(BOOST_TEST_CASE(&iterator_range_test_detail::check_make_iterator_range_n)); + test->add(BOOST_TEST_CASE(&test_advance)); + + return test; +} + diff --git a/libs/range/test/iterator_range_drop.cpp b/libs/range/test/iterator_range_drop.cpp new file mode 100644 index 00000000..58ac43ca --- /dev/null +++ b/libs/range/test/iterator_range_drop.cpp @@ -0,0 +1,200 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +class single_pass_iterator + : public boost::iterator_facade< + single_pass_iterator, + boost::int32_t, + boost::single_pass_traversal_tag, + const boost::int32_t& + > +{ + friend class boost::iterator_core_access; + + typedef std::vector::const_iterator iterator_t; + +public: + single_pass_iterator() { } + + explicit single_pass_iterator(iterator_t it) + : m_it(it) + { + } + +private: + void increment() + { + ++m_it; + } + + bool equal(single_pass_iterator other) const + { + return m_it == other.m_it; + } + + reference dereference() const + { + return *m_it; + } + + iterator_t m_it; +}; + +class bidirectional_iterator + : public boost::iterator_facade< + bidirectional_iterator, + boost::int32_t, + boost::bidirectional_traversal_tag, + const boost::int32_t& + > +{ + friend class boost::iterator_core_access; + + typedef std::vector::const_iterator iterator_t; + +public: + bidirectional_iterator() { } + + explicit bidirectional_iterator(iterator_t it) + : m_it(it) + { + } + +private: + void increment() + { + ++m_it; + } + + void decrement() + { + --m_it; + } + + bool equal(bidirectional_iterator other) const + { + return m_it == other.m_it; + } + + reference dereference() const + { + return *m_it; + } + + iterator_t m_it; +}; + +template +boost::iterator_range +single_pass_range(const SinglePassRange& rng) +{ + return boost::iterator_range( + single_pass_iterator(boost::begin(rng)), + single_pass_iterator(boost::end(rng))); +} + +template +boost::iterator_range +bidirectional_range(const BidirectionalRange& rng) +{ + return boost::iterator_range( + bidirectional_iterator(boost::begin(rng)), + bidirectional_iterator(boost::end(rng))); +} + +void test_drop_front() +{ + std::vector v; + std::vector ref_output; + + for (boost::int32_t i = 0; i < 10; ++i) + { + v.push_back(i); + ref_output.push_back(i); + } + + boost::iterator_range rng = single_pass_range(v); + + BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(), + ref_output.begin(), ref_output.end()); + + rng.drop_front(); + + ref_output.erase(ref_output.begin()); + + BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(), + ref_output.begin(), ref_output.end()); + + rng.drop_front(5); + + ref_output.erase(ref_output.begin(), ref_output.begin() + 5); + + BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(), + ref_output.begin(), ref_output.end()); +} + +void test_drop_back() +{ + std::vector v; + std::vector ref_output; + + for (boost::int32_t i = 0; i < 10; ++i) + { + v.push_back(i); + ref_output.push_back(i); + } + + boost::iterator_range rng = bidirectional_range(v); + + BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(), + ref_output.begin(), ref_output.end()); + + rng.drop_back(); + + ref_output.pop_back(); + + BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(), + ref_output.begin(), ref_output.end()); + + rng.drop_back(5); + + ref_output.erase(ref_output.end() - 5, ref_output.end()); + + BOOST_CHECK_EQUAL_COLLECTIONS(rng.begin(), rng.end(), + ref_output.begin(), ref_output.end()); +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range iterator_range drop functions"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_drop_front)); + test->add(BOOST_TEST_CASE(&boost_range_test::test_drop_back)); + + return test; +} diff --git a/libs/range/test/iterator_range_equality_bug.cpp b/libs/range/test/iterator_range_equality_bug.cpp new file mode 100644 index 00000000..eea47cb5 --- /dev/null +++ b/libs/range/test/iterator_range_equality_bug.cpp @@ -0,0 +1,39 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +// As reported in https://groups.google.com/forum/#!msg/boost-developers-archive/6JVNg7ZPb4k/RAlvPUec4MAJ + +#include +#include +#include + +namespace boost +{ + enum {unnamed}; + struct S { + bool operator<(int) const {return false;} + bool operator==(int) const {return false;} + }; + template + bool foo(T i) + { + return i < unnamed || i == unnamed; + } +} + +int main() +{ + using boost::lambda::_1; + (void)(_1 == 42); + (void)(42 == _1); + + boost::foo(42); + boost::foo(boost::S()); +} diff --git a/libs/range/test/iterator_range_hash.cpp b/libs/range/test/iterator_range_hash.cpp new file mode 100644 index 00000000..3ef9007f --- /dev/null +++ b/libs/range/test/iterator_range_hash.cpp @@ -0,0 +1,52 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_iterator_range_hash() +{ + std::vector v; + + for (boost::int32_t i = 0; i < 10; ++i) + { + v.push_back(i); + } + + std::size_t ref_output = boost::hash_range(v.begin(), v.end()); + + boost::iterator_range::iterator> rng(v); + + std::size_t test_output = boost::hash_value(rng); + + BOOST_CHECK_EQUAL(ref_output, test_output); +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range iterator_range hash function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_iterator_range_hash)); + + return test; +} diff --git a/libs/range/test/iterator_range_variant.cpp b/libs/range/test/iterator_range_variant.cpp new file mode 100644 index 00000000..d55ae853 --- /dev/null +++ b/libs/range/test/iterator_range_variant.cpp @@ -0,0 +1,60 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + enum E + { + e1, e2, e3 + }; + + void test_variant_report() + { + typedef boost::mpl::vector< + E, + std::string, + boost::iterator_range + >::type args; + + typedef boost::make_variant_over::type variant_t; + + variant_t v; + std::string s; + v = boost::iterator_range(s.begin(), s.end()); + v = e2; + v = std::string(); + + // Rationale: + // This is cast to const char* to guard against ambiguity in the case + // where std::string::iterator it a char* + v = static_cast(""); + } +} + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("iterator range and variant interoperability"); + + test->add(BOOST_TEST_CASE(&test_variant_report)); + + return test; +} diff --git a/libs/range/test/join.cpp b/libs/range/test/join.cpp new file mode 100644 index 00000000..300028b3 --- /dev/null +++ b/libs/range/test/join.cpp @@ -0,0 +1,397 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +// Credits: +// Trac 7376 - was raised by Leonid Gershanovich and his sample was used to +// make the test case to cover this condition. +// +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace boost +{ + namespace + { + // This function is a helper function that writes integers + // of increasing value into a range. It is used to test + // that joined ranged may be written to. + // + // Requires: + // - Range uses shallow copy semantics. + template< typename Range > + void fill_with_ints(Range rng) + { + typedef typename range_iterator::type iterator; + iterator target = boost::begin(rng); + const int count = boost::distance(rng); + for (int i = 0; i < count; ++i) + { + *target = i; + ++target; + } + } + + // The test_join_traversal function is used to provide additional + // tests based upon the underlying join iterator traversal. + // The join iterator takes care of the appropriate demotion, and + // this demotion. + + // test_join_traversal - additional tests for input and forward + // traversal iterators. This is of course a no-op. + template< typename Range1, typename Range2, typename TraversalTag > + void test_join_traversal(Range1& rng1, Range2& rng2, TraversalTag) + { + } + + // test_join_traversal - additional tests for bidirectional + // traversal iterators. + template< typename Range1, typename Range2 > + void test_join_traversal(Range1& rng1, Range2& rng2, boost::bidirectional_traversal_tag) + { + typedef typename range_value::type value_type; + std::vector reference(boost::begin(rng1), boost::end(rng1)); + boost::push_back(reference, rng2); + std::reverse(reference.begin(), reference.end()); + + std::vector test_result; + BOOST_REVERSE_FOREACH( value_type x, join(rng1, rng2) ) + { + test_result.push_back(x); + } + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test_result.begin(), test_result.end() ); + } + + // Test helper function to implement the additional tests for random + // access traversal iterators. This is used by the test_join_traversal + // function for random access iterators. The reason that the test + // implementation is put into this function is to utilise + // template parameter type deduction for the joined range type. + template< typename Range1, typename Range2, typename JoinedRange > + void test_random_access_join(Range1& rng1, Range2& rng2, JoinedRange joined) + { + BOOST_CHECK_EQUAL( boost::end(joined) - boost::begin(joined), boost::distance(joined) ); + BOOST_CHECK( boost::end(joined) <= boost::begin(joined) ); + BOOST_CHECK( boost::begin(joined) >= boost::end(joined) ); + if (boost::empty(joined)) + { + BOOST_CHECK(!(boost::begin(joined) < boost::end(joined))); + BOOST_CHECK(!(boost::end(joined) > boost::begin(joined))); + } + else + { + BOOST_CHECK(boost::begin(joined) < boost::end(joined)); + BOOST_CHECK(boost::end(joined) < boost::begin(joined)); + } + + typedef typename boost::range_difference::type difference_t; + const difference_t count = boost::distance(joined); + BOOST_CHECK( boost::begin(joined) + count == boost::end(joined) ); + BOOST_CHECK( boost::end(joined) - count == boost::begin(joined) ); + + typedef typename boost::range_iterator::type iterator_t; + iterator_t it = boost::begin(joined); + it += count; + BOOST_CHECK( it == boost::end(joined) ); + + it = boost::end(joined); + it -= count; + BOOST_CHECK( it == boost::begin(joined) ); + } + + // test_join_traversal function for random access traversal joined + // ranges. + template< typename Range1, typename Range2 > + void test_join_traversal(Range1& rng1, Range2& rng2, boost::random_access_traversal_tag) + { + test_join_traversal(rng1, rng2, boost::bidirectional_traversal_tag()); + test_random_access_join(rng1, rng2, join(rng1, rng2)); + } + + // Test the ability to write values into a joined range. This is + // achieved by copying the constant collections, altering them + // and then checking the result. Hence this relies upon both + // rng1 and rng2 having value copy semantics. + template< typename Collection1, typename Collection2 > + void test_write_to_joined_range(const Collection1& rng1, const Collection2& rng2) + { + Collection1 c1(rng1); + Collection2 c2(rng2); + + typedef BOOST_DEDUCED_TYPENAME boost::range_value< + Collection1 + >::type value_t BOOST_RANGE_UNUSED; + + fill_with_ints(boost::join(c1,c2)); + + // Ensure that the size of the written range has not been + // altered. + BOOST_CHECK_EQUAL( boost::distance(c1), boost::distance(rng1) ); + BOOST_CHECK_EQUAL( boost::distance(c2), boost::distance(rng2) ); + + // For each element x, in c1 ensure that it has been written to + // with incrementing integers + int x = 0; + typedef typename range_iterator::type iterator1; + iterator1 it1 = boost::begin(c1); + for (; it1 != boost::end(c1); ++it1) + { + BOOST_CHECK_EQUAL( x, *it1 ); + ++x; + } + + // For each element y, in c2 ensure that it has been written to + // with incrementing integers + typedef typename range_iterator::type iterator2; + iterator2 it2 = boost::begin(c2); + for (; it2 != boost::end(c2); ++it2) + { + BOOST_CHECK_EQUAL( x, *it2 ); + ++x; + } + } + + // Perform a unit test of a Boost.Range join() comparing + // it to a reference that is populated by appending + // elements from both source ranges into a vector. + template< typename Collection1, typename Collection2 > + void test_join_impl(Collection1& rng1, Collection2& rng2) + { + typedef typename range_value::type value_type; + std::vector reference(boost::begin(rng1), boost::end(rng1)); + boost::push_back(reference, rng2); + + std::vector test_result; + boost::push_back(test_result, join(rng1, rng2)); + + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test_result.begin(), test_result.end() ); + + typedef boost::range_detail::join_iterator< + typename boost::range_iterator::type, + typename boost::range_iterator::type + > join_iterator_t; + + typedef boost::iterator_traversal< join_iterator_t > tag_t; + + test_join_traversal(rng1, rng2, tag_t()); + + test_write_to_joined_range(rng1, rng2); + } + + // Make a collection filling it with items from the source + // range. This is used to build collections of various + // sizes populated with various values designed to optimize + // the code coverage exercised by the core test function + // test_join_impl. + template + boost::shared_ptr makeCollection(const Range& source) + { + boost::shared_ptr c(new Collection); + c->insert(c->end(), boost::begin(source), boost::end(source)); + return c; + } + + // This templatised version of the test_join_impl function + // generates and populates collections which are later + // used as input to the core test function. + // The caller of this function explicitly provides the + // template parameters. This supports the generation + // of testing a large combination of range types to be + // joined. It is of particular importance to remember + // to combine a random_access range with a bidirectional + // range to determine that the correct demotion of + // types occurs in the join_iterator. + template< typename Collection1, typename Collection2 > + void test_join_impl() + { + typedef boost::shared_ptr collection1_ptr; + typedef boost::shared_ptr collection2_ptr; + typedef boost::shared_ptr collection1_cptr; + typedef boost::shared_ptr collection2_cptr; + std::vector< collection1_cptr > left_containers; + std::vector< collection2_cptr > right_containers; + + left_containers.push_back(collection1_ptr(new Collection1)); + left_containers.push_back(makeCollection(irange(0,1))); + left_containers.push_back(makeCollection(irange(0,100))); + + right_containers.push_back(collection2_ptr(new Collection2)); + right_containers.push_back(makeCollection(irange(0,1))); + right_containers.push_back(makeCollection(irange(0,100))); + + BOOST_FOREACH( collection1_cptr left_container, left_containers ) + { + BOOST_FOREACH( collection2_cptr right_container, right_containers ) + { + test_join_impl(*left_container, *right_container); + } + } + } + + // entry-point into the unit test for the join() function + // this tests a representative sample of combinations of + // source range type. + void join_test() + { + test_join_impl< std::vector, std::vector >(); + test_join_impl< std::list, std::list >(); + test_join_impl< std::deque, std::deque >(); + + test_join_impl< std::vector, std::list >(); + test_join_impl< std::list, std::vector >(); + test_join_impl< std::vector, std::deque >(); + test_join_impl< std::deque, std::vector >(); + } + + void test_join_iterator_reference_type_constness_ticket8483() + { + // Just test that this compiles. + // Before the fix for bug 8483, the reference type of the joined + // range's iterator was incorrect ('int&' instead of 'const int&'), + // causing compiler errors. + const std::vector v1; + std::vector v2; + std::vector joined; + boost::push_back(joined, join(v1, v2)); + boost::push_back(joined, join(v2, v1)); + } + + namespace trac7376 + { + struct base_type + { + explicit base_type(boost::int32_t value) + : value(value) + { + } + + virtual boost::int32_t get() const = 0; + + boost::int32_t value; + }; + + struct derived_type1 + : base_type + { + derived_type1(boost::int32_t value) + : base_type(value) + { + } + + virtual boost::int32_t get() const + { + return value * 2; + } + }; + + struct derived_type2 + : base_type + { + derived_type2(boost::int32_t value) + : base_type(value) + { + } + + virtual boost::int32_t get() const + { + return value * 4; + } + }; + + struct apply_get + { + typedef boost::int32_t result_type; + result_type operator()(const base_type& arg) const + { + return arg.get(); + } + }; + + void test_reference_types() + { + using namespace boost::adaptors; + + typedef boost::range_detail::join_iterator< + std::vector::iterator, + std::vector::iterator, + const base_type&, + const base_type& + > join_iterator_t; + + std::vector reference_output; + + std::vector x; + for (boost::int32_t i = 0; i < 10; ++i) + { + x.push_back(derived_type1(i)); + reference_output.push_back(i * 2); + } + + std::vector y; + for (boost::int32_t i = 0; i < 10; ++i) + { + y.push_back(derived_type2(i)); + reference_output.push_back(i * 4); + } + + join_iterator_t it( + x, + y, + boost::range_detail::join_iterator_begin_tag()); + + std::vector output; + boost::push_back( + output, + boost::make_iterator_range( + join_iterator_t( + x, y, + boost::range_detail::join_iterator_begin_tag()), + join_iterator_t( + x, y, + boost::range_detail::join_iterator_end_tag())) + | transformed(apply_get())); + + BOOST_CHECK_EQUAL_COLLECTIONS( + output.begin(), output.end(), + reference_output.begin(), reference_output.end()); + } + } // namespace trac7376 + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.adaptor.joined" ); + + test->add( BOOST_TEST_CASE( &boost::join_test ) ); + test->add( BOOST_TEST_CASE( &boost::test_join_iterator_reference_type_constness_ticket8483 ) ); + test->add( BOOST_TEST_CASE( &boost::trac7376::test_reference_types ) ); + + return test; +} diff --git a/libs/range/test/mfc.cpp b/libs/range/test/mfc.cpp new file mode 100644 index 00000000..7a13e8e9 --- /dev/null +++ b/libs/range/test/mfc.cpp @@ -0,0 +1,743 @@ +// Boost.Range MFC Extension +// +// Copyright Shunsuke Sogame 2005-2006. +// 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) + + +#include // must be here + +// #include + +#include +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS +#define _ATL_NO_AUTOMATIC_NAMESPACE + +#define BOOST_LIB_NAME boost_test_exec_monitor +#include + +#define BOOST_RANGE_DETAIL_MICROSOFT_TEST +#include // can be placed first + + +#include +#include +// #include +#include +#include +#include +#include +#include + + +#include +#include +#include + +#if !(_ATL_VER < 0x0700) + #include + #include + #include +#endif + + +namespace brdm = boost::range_detail_microsoft; + + +// helpers +// + +template< class MfcMapT, class MapT > +bool test_mfc_map(MfcMapT& map, const MapT& sample) +{ + typedef typename boost::range_iterator::type iter_t; + typedef typename boost::range_const_iterator::type siter_t; + + bool result = true; + + result = result && (boost::distance(map) == boost::distance(sample)); + if (!result) + return false; + + { + for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) { + result = result && brdm::test_find_key_and_mapped(sample, *it); + } + } + + { + for (siter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) { + result = result && (map[it->first] == it->second); + } + } + + return result; +} + + +template< class MfcMapT, class MapT > +bool test_mfc_cpair_map(MfcMapT& map, const MapT& sample) +{ + typedef typename boost::range_iterator::type iter_t; + typedef typename boost::range_const_iterator::type siter_t; + + bool result = true; + + result = result && (boost::distance(map) == boost::distance(sample)); + if (!result) + return false; + + { + for (iter_t it = boost::begin(map), last = boost::end(map); it != last; ++it) { + result = result && brdm::test_find_key_and_mapped(sample, std::make_pair(it->key, it->value)); + } + } + + { + for (siter_t it = boost::begin(sample), last = boost::end(sample); it != last; ++it) { + result = result && (map[it->first] == it->second); + } + } + + return result; +} + + +// arrays +// +template< class Range > +void test_CByteArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CByteArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CDWordArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CDWordArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CObArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CObArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter >::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CPtrArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CPtrArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter >::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter >::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CStringArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CStringArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CUIntArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CUIntArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CWordArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CWordArray rng_t; + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// lists +// + +template< class Range > +void test_CObList(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CObList rng_t; + + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator >::value )); +#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF) + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#else + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#endif + + rng_t rng; + BOOST_CHECK( brdm::test_init_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CPtrList(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CPtrList rng_t; + + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator >::value )); +#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF) + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#else + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#endif + + rng_t rng; + BOOST_CHECK( brdm::test_init_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CStringList(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CStringList rng_t; + + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator >::value )); +#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF) + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#else + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#endif + + rng_t rng; + BOOST_CHECK( brdm::test_init_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// maps +// + +template< class MapT > +void test_CMapPtrToWord(const MapT& sample) +{ + typedef ::CMapPtrToWord rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_mfc_map(rng, sample) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMapPtrToPtr(const MapT& sample) +{ + typedef ::CMapPtrToPtr rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_mfc_map(rng, sample) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMapStringToOb(const MapT& sample) +{ + typedef ::CMapStringToOb rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_mfc_map(rng, sample) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMapStringToPtr(const MapT& sample) +{ + typedef ::CMapStringToPtr rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_mfc_map(rng, sample) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMapStringToString(const MapT& sample) +{ + typedef ::CMapStringToString rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); +#if !defined(BOOST_RANGE_MFC_NO_CPAIR) + BOOST_CHECK( ::test_mfc_cpair_map(rng, sample) ); +#endif + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMapWordToOb(const MapT& sample) +{ + typedef ::CMapWordToOb rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_mfc_map(rng, sample) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMapWordToPtr(const MapT& sample) +{ + typedef ::CMapWordToPtr rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); + BOOST_CHECK( ::test_mfc_map(rng, sample) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// templates +// + +template< class Range > +void test_CArray(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CArray rng_t; // An old MFC needs the second template argument. + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_array(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class Range > +void test_CList(const Range& sample) +{ + typedef typename boost::range_value::type val_t; + + typedef ::CList rng_t; + + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter< rng_t, brdm::list_iterator >::value )); +#if !defined(BOOST_RANGE_MFC_CONST_COL_RETURNS_NON_REF) + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#else + BOOST_STATIC_ASSERT(( brdm::test_const_iter < rng_t, brdm::list_iterator >::value )); +#endif + + rng_t rng; + BOOST_CHECK( brdm::test_init_list(rng, sample) ); + BOOST_CHECK( brdm::test_bidirectional(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +template< class MapT > +void test_CMap(const MapT& sample) +{ + typedef typename MapT::key_type k_t; + typedef typename MapT::mapped_type m_t; + + typedef ::CMap rng_t; + + rng_t rng; + boost::function_requires< boost::ForwardRangeConcept >(); + BOOST_CHECK( brdm::test_init_map(rng, sample) ); +#if !defined(BOOST_RANGE_MFC_NO_CPAIR) + BOOST_CHECK( ::test_mfc_cpair_map(rng, sample) ); +#endif + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +void test_CTypedPtrArray() +{ + typedef ::CTypedPtrArray< ::CPtrArray, int * > rng_t; + boost::function_requires< boost::RandomAccessRangeConcept >(); + + rng_t rng; + int o1, o2, o3, o4, o5; + int *data[] = { &o1, &o2, &o3, &o4, &o5 }; + BOOST_CHECK( brdm::test_init_array(rng, boost::make_iterator_range(data, data+5)) ); + + BOOST_CHECK( *(boost::begin(rng) + 2) == &o3 ); + BOOST_CHECK( *(boost::end(rng) - 1) == &o5 ); + + // BOOST_CHECK( brdm::test_random_access(rng) ); this range is not mutable + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +void test_CTypedPtrList() +{ + typedef ::CTypedPtrList< ::CObList, ::CObList * > rng_t; + boost::function_requires< boost::BidirectionalRangeConcept >(); + + rng_t rng; + + ::CObList o1, o2, o3, o4, o5; + ::CObList *data[] = { &o1, &o2, &o3, &o4, &o5 }; + BOOST_CHECK( brdm::test_init_list(rng, data) ); + + boost::range_iterator::type it = boost::begin(rng); + std::advance(it, 1); + BOOST_CHECK( *it == &o2 ); + std::advance(it, 2); + BOOST_CHECK( *it == &o4 ); + + // BOOST_CHECK( brdm::test_bidirectional(rng) ); this range is not mutable + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +void test_CTypedPtrMap() +{ + typedef ::CTypedPtrMap< ::CMapStringToPtr, ::CString, int *> rng_t; + boost::function_requires< boost::ForwardRangeConcept >(); + + rng_t rng; + ::CString o0(_T('a')), o1(_T('c')), o2(_T('f')), o3(_T('q')), o4(_T('g')); + int d0, d1, d2, d3, d4; + std::map< ::CString, int * > data; + data[o0] = &d0, data[o1] = &d1, data[o2] = &d2, data[o3] = &d3, data[o4] = &d4; + + BOOST_CHECK( brdm::test_init_map(rng, data) ); + BOOST_CHECK( ::test_mfc_map(rng, data) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); +} + + +// strings +// +#if defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING) + + template< class Range > + void test_CString(const Range& sample) + { + typedef typename boost::range_value::type val_t; + + typedef ::CString rng_t; // An old MFC needs the second template argument. + BOOST_STATIC_ASSERT(( brdm::test_mutable_iter::value )); + BOOST_STATIC_ASSERT(( brdm::test_const_iter ::value )); + + rng_t rng; + BOOST_CHECK( brdm::test_init_string(rng, sample) ); + BOOST_CHECK( brdm::test_random_access(rng) ); + BOOST_CHECK( brdm::test_emptiness(rng) ); + } + +#endif + + +struct CPerson +{ + void hello_range() { }; +}; + + +void test_mfc() +{ +#if 0 + // overview + // + { + CTypedPtrArray *> myArray; + // ... + BOOST_FOREACH (CList *theList, myArray) + { + BOOST_FOREACH (CString& str, *theList) + { + boost::to_upper(str); + std::sort(boost::begin(str), boost::end(str)); + // ... + } + } + } +#endif + + // arrays + // + { + BYTE data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 }; + + ::test_CByteArray(boost::make_iterator_range(data, data+22)); + } + + { + DWORD data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 }; + + test_CDWordArray(boost::make_iterator_range(data, data+22)); + } + + { + ::CObArray o1, o2, o3, o4, o5; + ::CObject *data[] = { &o1, &o2, &o3, &o4, &o5 }; + + ::test_CObArray(boost::make_iterator_range(data, data+5)); + } + + { + ::CPtrArray o1, o2, o3, o4, o5; + void *data[] = { &o1, &o2, &o3, &o4, &o5 }; + + ::test_CPtrArray(boost::make_iterator_range(data, data+5)); + } + + { + ::CString data[] = { + ::CString(_T('0')), ::CString(_T('1')), ::CString(_T('2')), ::CString(_T('3')), + ::CString(_T('4')), ::CString(_T('5')), ::CString(_T('6')), ::CString(_T('7')) + }; + + ::test_CStringArray(boost::make_iterator_range(data, data+8)); + } + + { + ::CUIntArray rng; + UINT data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 }; + + ::test_CUIntArray(boost::make_iterator_range(data, data+22)); + } + + { + ::CWordArray rng; + WORD data[] = { 4,5,1,3,5,12,3,1,3,1,6,1,3,60,1,1,5,1,3,1,10 }; + + ::test_CWordArray(boost::make_iterator_range(data, data+22)); + } + + + // lists + // + { + ::CObList rng; + ::CObList o1, o2, o3, o4, o5; + ::CObject *data[] = { &o1, &o2, &o3, &o4, &o5 }; + + ::test_CObList(boost::make_iterator_range(data, data+5)); + } + + { + ::CPtrList rng; + ::CPtrList o1, o2, o3, o4, o5; + void *data[] = { &o1, &o2, &o3, &o4, &o5 }; + + ::test_CPtrList(boost::make_iterator_range(data, data+5)); + } + + { + ::CString data[] = { + ::CString(_T('0')), ::CString(_T('1')), ::CString(_T('2')), ::CString(_T('3')), + ::CString(_T('4')), ::CString(_T('5')), ::CString(_T('6')), ::CString(_T('7')) + }; + + ::test_CStringList(boost::make_iterator_range(data, data+8)); + } + + + // maps + // + { + std::map data; + int o0, o1, o2, o3, o4; + data[&o0] = 15, data[&o1] = 14, data[&o2] = 3, data[&o3] = 6, data[&o4] = 1; + + ::test_CMapPtrToWord(data); + } + + { + std::map data; + int o0, o1, o2, o3, o4; + data[&o0] = &o3, data[&o1] = &o2, data[&o2] = &o1, data[&o3] = &o0, data[&o4] = &o4; + + ::test_CMapPtrToPtr(data); + } + + { + std::map< ::CString, CObject * > data; + CObArray o0, o1, o2, o3, o4; + data[ ::CString('0') ] = &o0, data[ ::CString('1') ] = &o1, data[ ::CString('2') ] = &o2, + data[ ::CString('3') ] = &o3, data[ ::CString('4') ] = &o4; + + ::test_CMapStringToOb(data); + } + + { + std::map< ::CString, void * > data; + CObArray o0, o1, o2, o3, o4; + data[ ::CString('0') ] = &o0, data[ ::CString('1') ] = &o1, data[ ::CString('2') ] = &o2, + data[ ::CString('3') ] = &o3, data[ ::CString('4') ] = &o4; + + ::test_CMapStringToPtr(data); + } + + { + std::map< ::CString, ::CString > data; + CString o0('a'), o1('b'), o2('c'), o3('d'), o4('e'); + data[ ::CString('0') ] = o0, data[ ::CString('1') ] = o1, data[ ::CString('2') ] = o2, + data[ ::CString('3') ] = o3, data[ ::CString('4') ] = o4; + + ::test_CMapStringToString(data); + } + + { + std::map< WORD, CObject * > data; + ::CDWordArray o0, o1, o2, o3, o4; + data[21] = &o3, data[52] = &o2, data[12] = &o1, data[76] = &o0, data[54] = &o4; + + ::test_CMapWordToOb(data); + } + + { + std::map< WORD, void * > data; + ::CDWordArray o0, o1, o2, o3, o4; + data[21] = &o3, data[52] = &o2, data[12] = &o1, data[76] = &o0, data[54] = &o4; + + ::test_CMapWordToPtr(data); + } + + // templates + // + { + std::string data("0987654321qwertyuiop"); + ::test_CArray(data); + ::test_CList(data); + } + + { + std::wstring data(L"asdfghjklzxcvbnm"); + ::test_CArray(data); + ::test_CList(data); + } + + { + std::map< int, std::string > data; + data[0] = "abcde", data[1] = "ajfie", data[2] = "lij", data[3] = "abc", data[4] = "ioiu"; + + ::test_CMap(data); + } + + + // typed + // + { + ::test_CTypedPtrArray(); + ::test_CTypedPtrList(); + ::test_CTypedPtrMap(); + } + + + // strings + // +#if defined(BOOST_RANGE_MFC_HAS_LEGACY_STRING) + { + std::string data("123456789 abcdefghijklmn"); + ::test_CString(data); + } +#endif + + +} // test_mfc + + +#include +using boost::unit_test::test_suite; + + +test_suite * +init_unit_test_suite(int argc, char* argv[]) +{ + test_suite *test = BOOST_TEST_SUITE("MFC Range Test Suite"); + test->add(BOOST_TEST_CASE(&test_mfc)); + + (void)argc, (void)argv; // unused + return test; +} diff --git a/libs/range/test/mutable_iterator.cpp b/libs/range/test/mutable_iterator.cpp new file mode 100644 index 00000000..40a38791 --- /dev/null +++ b/libs/range/test/mutable_iterator.cpp @@ -0,0 +1,61 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_mutable_iterator() +{ + typedef std::vector cont; + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::iterator, + boost::range_mutable_iterator::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::iterator, + boost::range_mutable_iterator::type + >::value)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::iterator, + boost::range_mutable_iterator::type + >::value)); +#endif +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range range_mutable_iterator meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_mutable_iterator)); + + return test; +} diff --git a/libs/range/test/partial_workaround.cpp b/libs/range/test/partial_workaround.cpp new file mode 100644 index 00000000..b8da4154 --- /dev/null +++ b/libs/range/test/partial_workaround.cpp @@ -0,0 +1,114 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +//#define BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION 1 + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +using namespace boost; +using namespace std; + +void check_partial_workaround() +{ + using namespace range_detail; + using type_traits::yes_type; + using type_traits::no_type; + + ////////////////////////////////////////////////////////////////////// + // string + ////////////////////////////////////////////////////////////////////// + char* c_ptr; + const char* cc_ptr; + wchar_t* w_ptr; + const wchar_t* cw_ptr; + + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_string_impl( c_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_string_impl( cc_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_string_impl( w_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_string_impl( cw_ptr ) ) ); + + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_char_ptr_impl( c_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( no_type ) == sizeof( is_char_ptr_impl( cc_ptr ) ) ); + + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_wchar_t_ptr_impl( w_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( no_type ) == sizeof( is_wchar_t_ptr_impl( cw_ptr ) ) ); + + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_const_char_ptr_impl( c_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_const_char_ptr_impl( cc_ptr ) ) ); + + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_const_wchar_t_ptr_impl( w_ptr ) ) ); + BOOST_STATIC_ASSERT( sizeof( yes_type ) == sizeof( is_const_wchar_t_ptr_impl( cw_ptr ) ) ); + + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::std_container_, + boost::range_detail::range< vector >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::std_pair_, + boost::range_detail::range< pair >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::array_, + boost::range_detail::range< int[42] >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::char_ptr_, + boost::range_detail::range< char* >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::const_char_ptr_, + boost::range_detail::range< const char* >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::wchar_t_ptr_, + boost::range_detail::range< wchar_t* >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::const_wchar_t_ptr_, + boost::range_detail::range< const wchar_t* >::type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_detail::std_container_, + boost::range_detail::range< vector >::type >::value )); + +} + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +void check_partial_workaround() +{ + // + // test if warnings are generated + // + std::size_t s = boost::range_detail::array_size( "foo" ); + BOOST_CHECK_EQUAL( s, 4u ); +} + +#endif + +#include +using boost::unit_test::test_suite; + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &check_partial_workaround ) ); + + return test; +} diff --git a/libs/range/test/pointer.cpp b/libs/range/test/pointer.cpp new file mode 100644 index 00000000..94e78f3d --- /dev/null +++ b/libs/range/test/pointer.cpp @@ -0,0 +1,61 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_pointer() +{ + typedef std::vector cont; + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::pointer, + boost::range_pointer::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::const_pointer, + boost::range_pointer::type + >::value)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::pointer, + boost::range_pointer::type + >::value)); +#endif +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range range_pointer meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_pointer)); + + return test; +} diff --git a/libs/range/test/pointer_as_iterator.cpp b/libs/range/test/pointer_as_iterator.cpp new file mode 100644 index 00000000..e0e28d06 --- /dev/null +++ b/libs/range/test/pointer_as_iterator.cpp @@ -0,0 +1,39 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + void test_pointer_as_iterator() + { + boost::array arr; + boost::iterator_range r(arr.begin(), arr.end()); + r[0]; + } +} // anonymous namespace + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.pointer_as_iterator" ); + + test->add(BOOST_TEST_CASE( &test_pointer_as_iterator )); + + return test; +} diff --git a/libs/range/test/reference.cpp b/libs/range/test/reference.cpp new file mode 100644 index 00000000..755be0ea --- /dev/null +++ b/libs/range/test/reference.cpp @@ -0,0 +1,61 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_reference() +{ + typedef std::vector cont; + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::reference, + boost::range_reference::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::const_reference, + boost::range_reference::type + >::value)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::reference, + boost::range_reference::type + >::value)); +#endif +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range range_reference meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_reference)); + + return test; +} diff --git a/libs/range/test/result_iterator.cpp b/libs/range/test/result_iterator.cpp new file mode 100644 index 00000000..67d4a2d0 --- /dev/null +++ b/libs/range/test/result_iterator.cpp @@ -0,0 +1,62 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#define BOOST_ALLOW_DEPRECATED_HEADERS +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_result_iterator() +{ + typedef std::vector cont; + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::iterator, + boost::range_result_iterator::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::const_iterator, + boost::range_result_iterator::type + >::value)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::iterator, + boost::range_result_iterator::type + >::value)); +#endif +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range range_result_iterator meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_result_iterator)); + + return test; +} diff --git a/libs/range/test/reverse_iterator.cpp b/libs/range/test/reverse_iterator.cpp new file mode 100644 index 00000000..827f244d --- /dev/null +++ b/libs/range/test/reverse_iterator.cpp @@ -0,0 +1,61 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_reverse_iterator() +{ + typedef std::vector cont; + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::reverse_iterator, + boost::range_reverse_iterator::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::reverse_iterator, + boost::range_reverse_iterator::type + >::value)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::reverse_iterator, + boost::range_reverse_iterator::type + >::value)); +#endif +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range range_reverse_iterator meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_reverse_iterator)); + + return test; +} diff --git a/libs/range/test/reverse_result_iterator.cpp b/libs/range/test/reverse_result_iterator.cpp new file mode 100644 index 00000000..107b4bdd --- /dev/null +++ b/libs/range/test/reverse_result_iterator.cpp @@ -0,0 +1,63 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#define BOOST_ALLOW_DEPRECATED_HEADERS +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_reverse_result_iterator() +{ + typedef std::vector cont; + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::reverse_iterator, + boost::range_reverse_result_iterator::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::reverse_iterator, + boost::range_reverse_result_iterator::type + >::value)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + boost::reverse_iterator, + boost::range_reverse_result_iterator::type + >::value)); +#endif +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE( + "Boost.Range range_reverse_result_iterator meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_reverse_result_iterator)); + + return test; +} diff --git a/libs/range/test/reversible_range.cpp b/libs/range/test/reversible_range.cpp new file mode 100644 index 00000000..fec18c3c --- /dev/null +++ b/libs/range/test/reversible_range.cpp @@ -0,0 +1,74 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void check_iterator() +{ + typedef std::vector vec_t; + typedef vec_t::iterator iterator; + typedef std::pair pair_t; + typedef boost::range_reverse_iterator::type rev_iterator; + typedef std::pair rev_pair_t; + + vec_t vec; + pair_t p = std::make_pair( vec.begin(), vec.end() ); + rev_pair_t rp = std::make_pair( boost::rbegin( p ), boost::rend( p ) ); + int a[] = {1,2,3,4,5,6,7,8,9,10}; + const int ca[] = {1,2,3,4,5,6,7,8,9,10,11,12}; + BOOST_CHECK( boost::rbegin( vec ) == boost::range_reverse_iterator::type( vec.end() ) ); + BOOST_CHECK( boost::rend( vec ) == boost::range_reverse_iterator::type( vec.begin() ) ); + BOOST_CHECK( std::distance( boost::rbegin( vec ), boost::rend( vec ) ) == std::distance( boost::begin( vec ), boost::end( vec ) ) ); + + BOOST_CHECK( boost::rbegin( p ) == boost::begin( rp ) ); + BOOST_CHECK( boost::rend( p ) == boost::end( rp ) ); + BOOST_CHECK( std::distance( boost::rbegin( p ), boost::rend( p ) ) == std::distance( boost::begin( rp ), boost::end( rp ) ) ); + BOOST_CHECK( std::distance( boost::begin( p ), boost::end( p ) ) == std::distance( boost::rbegin( rp ), boost::rend( rp ) ) ); + + + BOOST_CHECK_EQUAL( &*boost::begin( a ), &*( boost::rend( a ) - 1 ) ); + BOOST_CHECK_EQUAL( &*( boost::end( a ) - 1 ), &*boost::rbegin( a ) ); + BOOST_CHECK_EQUAL( &*boost::begin( ca ), &*( boost::rend( ca ) - 1 ) ); + BOOST_CHECK_EQUAL( &*( boost::end( ca ) - 1 ), &*boost::rbegin( ca ) ); +} + + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &check_iterator ) ); + + return test; +} + + + + + + + diff --git a/libs/range/test/size_type.cpp b/libs/range/test/size_type.cpp new file mode 100644 index 00000000..9c335f14 --- /dev/null +++ b/libs/range/test/size_type.cpp @@ -0,0 +1,61 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_size() +{ + typedef std::vector cont; + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::size_type, + boost::range_size::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::size_type, + boost::range_size::type + >::value)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::size_type, + boost::range_size::type + >::value)); +#endif +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range range_size meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_size)); + + return test; +} diff --git a/libs/range/test/std_container.cpp b/libs/range/test/std_container.cpp new file mode 100644 index 00000000..f980bff5 --- /dev/null +++ b/libs/range/test/std_container.cpp @@ -0,0 +1,74 @@ + // Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include +#include +#include +#include + +void check_std_container() +{ + typedef std::vector vec_t; + vec_t vec; + vec.push_back( 3 ); vec.push_back( 4 ); + const vec_t cvec( vec ); + + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_value::type, vec_t::value_type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_iterator::type, vec_t::iterator >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_iterator::type, vec_t::const_iterator >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_difference::type, vec_t::difference_type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_size::type, vec_t::size_type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_iterator::type, vec_t::iterator >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_iterator::type, vec_t::const_iterator >::value )); + + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_value::type, vec_t::value_type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_difference::type, vec_t::difference_type >::value )); + BOOST_STATIC_ASSERT(( boost::is_same< boost::range_size::type, vec_t::size_type >::value )); + + BOOST_CHECK( boost::begin( vec ) == vec.begin() ); + BOOST_CHECK( boost::end( vec ) == vec.end() ); + BOOST_CHECK( boost::empty( vec ) == vec.empty() ); + BOOST_CHECK( static_cast(boost::size( vec )) == vec.size() ); + + BOOST_CHECK( boost::begin( cvec ) == cvec.begin() ); + BOOST_CHECK( boost::end( cvec ) == cvec.end() ); + BOOST_CHECK( boost::empty( cvec ) == cvec.empty() ); + BOOST_CHECK( static_cast(boost::size( cvec )) == cvec.size() ); + +} + + +#include + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &check_std_container ) ); + + return test; +} + + + + + + diff --git a/libs/range/test/string.cpp b/libs/range/test/string.cpp new file mode 100644 index 00000000..1935ffdd --- /dev/null +++ b/libs/range/test/string.cpp @@ -0,0 +1,281 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +//#define _MSL_USING_NAMESPACE 1 + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + template< class CharT, std::size_t Length > + class test_string + { + public: + typedef CharT value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef std::size_t size_type; + typedef value_type array_t[Length]; + typedef const value_type const_array_t[Length]; + + explicit test_string(const CharT literal_sz[]) + { + std::copy(literal_sz, literal_sz + Length, m_buffer.data()); + m_buffer[Length] = value_type(); + } + + const_pointer const_sz() const { return m_buffer.data(); } + pointer mutable_sz() { return m_buffer.data(); } + + private: + typedef boost::array buffer_t; + buffer_t m_buffer; + }; +} + +template< class T > +inline BOOST_DEDUCED_TYPENAME boost::range_iterator::type +str_begin( T& r ) +{ + return boost::begin( boost::as_literal(r) ); +} + +template< class T > +inline BOOST_DEDUCED_TYPENAME boost::range_iterator::type +str_end( T& r ) +{ + return boost::end( boost::as_literal(r) ); +} + +template< class T > +inline BOOST_DEDUCED_TYPENAME boost::range_difference::type +str_size( const T& r ) +{ + return boost::size( boost::as_literal(r) ); +} + +template< class T > +inline bool +str_empty( T& r ) +{ + return boost::empty( boost::as_literal(r) ); +} + +template< typename Container, typename T > +BOOST_DEDUCED_TYPENAME boost::range_iterator::type +find( Container& c, T value ) +{ + return std::find( str_begin(c), str_end(c), + value ); +} + +template< typename Container, typename T > +BOOST_DEDUCED_TYPENAME boost::range_iterator::type +find( const Container& c, T value ) +{ + return std::find( str_begin(c), str_end(c), + value ); +} + +template< typename Container, typename T > +BOOST_DEDUCED_TYPENAME boost::range_iterator::type +find_mutable( Container& c, T value ) +{ + str_size( c ); + return std::find( str_begin(c), str_end(c), + value ); +} + +template< typename Container, typename T > +BOOST_DEDUCED_TYPENAME boost::range_iterator::type +find_const( const Container& c, T value ) +{ + str_size( c ); + return std::find( str_begin(c), str_end(c), + value ); +} + + +std::vector +check_rvalue_return() +{ + return std::vector( 10, 'm' ); +} + +using namespace boost; + + +void check_char() +{ + typedef boost::range_difference::type diff_t; + typedef char* char_iterator_t; + typedef char char_array_t[10]; + + test_string a_string("a string"); + test_string another_string("another string"); + + const char* char_s = a_string.const_sz(); + char my_string[] = "another_string"; + const char my_const_string[] = "another string"; + const diff_t my_string_length = 14; + char* char_s2 = a_string.mutable_sz(); + + BOOST_STATIC_ASSERT(( is_same< range_value::type, + std::iterator_traits::value_type>::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, char_iterator_t >::value )); + + BOOST_STATIC_ASSERT(( is_same< range_difference::type, + ::std::ptrdiff_t >::value )); + BOOST_STATIC_ASSERT(( is_same< range_size::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, char_iterator_t >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, const char* >::value )); + + BOOST_STATIC_ASSERT(( is_same< range_value::type, + char>::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, char* >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, const char* >::value )); + BOOST_STATIC_ASSERT(( is_same< range_difference::type, + ::std::ptrdiff_t >::value )); + BOOST_STATIC_ASSERT(( is_same< range_size::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, char* >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, const char* >::value )); + + BOOST_CHECK_EQUAL( str_begin( char_s ), char_s ); + const diff_t sz = str_size(char_s); + const char* str_end1 = str_begin( char_s ) + sz; + BOOST_CHECK_EQUAL( str_end( char_s ), str_end1 ); + BOOST_CHECK_EQUAL( str_empty( char_s ), (char_s == 0 || char_s[0] == char()) ); + BOOST_CHECK_EQUAL( sz, static_cast(std::char_traits::length(char_s)) ); + + BOOST_CHECK_EQUAL( str_begin( my_string ), my_string ); + range_iterator::type str_end2 = str_begin( my_string ) + str_size(my_string); + range_iterator::type str_end3 = str_end(my_string); + BOOST_CHECK_EQUAL( str_end3, str_end2 ); + BOOST_CHECK_EQUAL( str_empty( my_string ), (my_string == 0 || my_string[0] == char()) ); + BOOST_CHECK_EQUAL( str_size( my_string ), my_string_length ); + BOOST_CHECK_EQUAL( str_size( my_string ), static_cast(std::char_traits::length(my_string)) ); + + char to_search = 'n'; + BOOST_CHECK( find_mutable( char_s, to_search ) != str_end( char_s ) ); + BOOST_CHECK( find_const( char_s, to_search ) != str_end(char_s) ); + + BOOST_CHECK( find_mutable( my_string, to_search ) != str_end(my_string) ); + BOOST_CHECK( find_const( my_string, to_search ) != str_end(my_string) ); + + BOOST_CHECK( find_mutable( char_s2, to_search ) != str_end(char_s) ); + BOOST_CHECK( find_const( char_s2, to_search ) != str_end(char_s2) ); + + BOOST_CHECK( find_const( as_array( my_string ), to_search ) != str_end(my_string) ); + BOOST_CHECK( find_const( as_array( my_const_string ), to_search ) != str_end(my_string) ); + + // + // Test that as_literal() always scan for null terminator + // + char an_array[] = "foo\0bar"; + BOOST_CHECK_EQUAL( str_begin( an_array ), an_array ); + BOOST_CHECK_EQUAL( str_end( an_array ), an_array + 3 ); + BOOST_CHECK_EQUAL( str_size( an_array ), 3 ); + + const char a_const_array[] = "foobar\0doh"; + BOOST_CHECK_EQUAL( str_begin( a_const_array ), a_const_array ); + BOOST_CHECK_EQUAL( str_end( a_const_array ), a_const_array + 6 ); + BOOST_CHECK_EQUAL( str_size( a_const_array ), 6 ); + +} + + + +void check_string() +{ + check_char(); + +#ifndef BOOST_NO_STD_WSTRING + typedef wchar_t* wchar_iterator_t; + + test_string a_wide_string(L"a wide string"); + test_string another_wide_string(L"another wide string"); + + const wchar_t* char_ws = a_wide_string.const_sz(); + wchar_t my_wstring[] = L"another wide string"; + wchar_t* char_ws2 = a_wide_string.mutable_sz(); + + BOOST_STATIC_ASSERT(( is_same< range_value::type, + std::iterator_traits::value_type>::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, wchar_iterator_t >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, const wchar_t* >::value )); + BOOST_STATIC_ASSERT(( is_same< range_difference::type, + std::iterator_traits::difference_type >::value )); + BOOST_STATIC_ASSERT(( is_same< range_size::type, std::size_t >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, wchar_iterator_t >::value )); + BOOST_STATIC_ASSERT(( is_same< range_iterator::type, const wchar_t* >::value )); + + typedef boost::range_difference::type diff_t; + const diff_t sz = str_size( char_ws ); + BOOST_CHECK_EQUAL( str_begin( char_ws ), char_ws ); + BOOST_CHECK_EQUAL( str_end(char_ws), (str_begin( char_ws ) + sz) ); + BOOST_CHECK_EQUAL( str_empty( char_ws ), (char_ws == 0 || char_ws[0] == wchar_t()) ); + BOOST_CHECK_EQUAL( sz, static_cast(std::char_traits::length(char_ws)) ); + + wchar_t to_search = L'n'; + BOOST_CHECK( find( char_ws, to_search ) != str_end(char_ws) ); + BOOST_CHECK( find( char_ws2, to_search ) != str_end(char_ws2) ); + +#if BOOST_WORKAROUND(_MSC_VER, BOOST_TESTED_AT(1300)) + + BOOST_CHECK( find( my_wstring, to_search ) != str_end(my_wstring) ); + +#else + + boost::ignore_unused_variable_warning( my_wstring ); + +#endif +#endif + + find( check_rvalue_return(), 'n' ); + +} + +#include +using boost::unit_test::test_suite; + + +test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" ); + + test->add( BOOST_TEST_CASE( &check_string ) ); + + return test; +} + + + + + + diff --git a/libs/range/test/sub_range.cpp b/libs/range/test/sub_range.cpp new file mode 100644 index 00000000..6a0113e0 --- /dev/null +++ b/libs/range/test/sub_range.cpp @@ -0,0 +1,289 @@ +// Boost.Range library +// +// Copyright Thorsten Ottosen 2003-2004. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + + +#include + +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +# pragma warn -8091 // suppress warning in Boost.Test +# pragma warn -8057 // unused argument argc/argv in Boost.Test +#endif + +#include +#include +#include +#include +#include +#include +#include + +namespace boost_range_test +{ + namespace + { + +void check_sub_range() +{ + + typedef std::string::iterator iterator; + typedef std::string::const_iterator const_iterator; + typedef boost::iterator_range irange; + typedef boost::iterator_range cirange; + std::string str = "hello world"; + const std::string cstr = "const world"; + irange r = boost::make_iterator_range( str ); + r = boost::make_iterator_range( str.begin(), str.end() ); + cirange r2 = boost::make_iterator_range( cstr ); + r2 = boost::make_iterator_range( cstr.begin(), cstr.end() ); + r2 = boost::make_iterator_range( str ); + + typedef boost::sub_range srange; + typedef boost::sub_range csrange; + srange s = r; + BOOST_CHECK( r == r ); + BOOST_CHECK( s == r ); + s = boost::make_iterator_range( str ); + csrange s2 = r; + s2 = r2; + s2 = boost::make_iterator_range( cstr ); + BOOST_CHECK( r2 == r2 ); + BOOST_CHECK( s2 != r2 ); + s2 = boost::make_iterator_range( str ); + BOOST_CHECK( !(s != s) ); + + BOOST_CHECK( r.begin() == s.begin() ); + BOOST_CHECK( r2.begin()== s2.begin() ); + BOOST_CHECK( r.end() == s.end() ); + BOOST_CHECK( r2.end() == s2.end() ); + BOOST_CHECK_EQUAL( r.size(), s.size() ); + BOOST_CHECK_EQUAL( r2.size(), s2.size() ); + +//#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x564)) +// if( !(bool)r ) +// BOOST_CHECK( false ); +// if( !(bool)r2 ) +// BOOST_CHECK( false ); +// if( !(bool)s ) +// BOOST_CHECK( false ); +// if( !(bool)s2 ) +// BOOST_CHECK( false ); +//#else + if( !r ) + BOOST_CHECK( false ); + if( !r2 ) + BOOST_CHECK( false ); + if( !s ) + BOOST_CHECK( false ); + if( !s2 ) + BOOST_CHECK( false ); +//#endif + + std::cout << r << r2 << s << s2; + + std::string res = boost::copy_range( r ); + BOOST_CHECK_EQUAL_COLLECTIONS( res.begin(), res.end(), r.begin(), r.end() ); + + r.empty(); + s.empty(); + r.size(); + s.size(); + + // + // As of range v2 not legal anymore. + // + //irange singular_irange; + //BOOST_CHECK( singular_irange.empty() ); + //BOOST_CHECK( singular_irange.size() == 0 ); + // + //srange singular_srange; + //BOOST_CHECK( singular_srange.empty() ); + //BOOST_CHECK( singular_srange.size() == 0 ); + // + //BOOST_CHECK( empty( singular_irange ) ); + //BOOST_CHECK( empty( singular_srange ) ); + // + + srange rr = boost::make_iterator_range( str ); + BOOST_CHECK( rr.equal( r ) ); + + rr = boost::make_iterator_range( str.begin(), str.begin() + 5 ); + BOOST_CHECK( rr == boost::as_literal("hello") ); + BOOST_CHECK( rr != boost::as_literal("hell") ); + BOOST_CHECK( rr < boost::as_literal("hello dude") ); + BOOST_CHECK( boost::as_literal("hello") == rr ); + BOOST_CHECK( boost::as_literal("hell") != rr ); + BOOST_CHECK( ! (boost::as_literal("hello dude") < rr ) ); + + irange rrr = rr; + BOOST_CHECK( rrr == rr ); + BOOST_CHECK( !( rrr != rr ) ); + BOOST_CHECK( !( rrr < rr ) ); + + const irange cr = boost::make_iterator_range( str ); + BOOST_CHECK_EQUAL( cr.front(), 'h' ); + BOOST_CHECK_EQUAL( cr.back(), 'd' ); + BOOST_CHECK_EQUAL( cr[1], 'e' ); + BOOST_CHECK_EQUAL( cr(1), 'e' ); + + rrr = boost::make_iterator_range( str, 1, -1 ); + BOOST_CHECK( rrr == boost::as_literal("ello worl") ); + rrr = boost::make_iterator_range( rrr, -1, 1 ); + BOOST_CHECK( rrr == str ); + rrr.front() = 'H'; + rrr.back() = 'D'; + rrr[1] = 'E'; + BOOST_CHECK( rrr == boost::as_literal("HEllo worlD") ); +} + +template +void check_mutable_type(T&) +{ + BOOST_STATIC_ASSERT(!boost::is_const::value); +} + +template +void check_constant_type(T&) +{ + BOOST_STATIC_ASSERT(boost::is_const::value); +} + +template +void check_is_const_iterator(Iterator it) +{ + BOOST_STATIC_ASSERT(( + boost::is_same< + BOOST_DEDUCED_TYPENAME boost::range_iterator< + BOOST_DEDUCED_TYPENAME boost::add_const::type + >::type, + Iterator + >::value)); +} + +template +void check_is_iterator(Iterator it) +{ + BOOST_STATIC_ASSERT(( + boost::is_same< + BOOST_DEDUCED_TYPENAME boost::range_iterator< + BOOST_DEDUCED_TYPENAME boost::remove_const::type + >::type, + Iterator + >::value)); +} + +void const_propagation_mutable_collection(void) +{ + typedef std::vector coll_t; + typedef boost::sub_range sub_range_t; + + coll_t c; + c.push_back(0); + + sub_range_t rng(c); + const sub_range_t crng(c); + + check_is_iterator(rng.begin()); + check_is_iterator(rng.end()); + + check_is_const_iterator(crng.begin()); + check_is_const_iterator(crng.end()); + + check_mutable_type(rng[0]); + check_mutable_type(rng.front()); + check_mutable_type(rng.back()); + check_constant_type(crng[0]); + check_constant_type(crng.front()); + check_constant_type(crng.back()); +} + +void const_propagation_const_collection(void) +{ + typedef std::vector coll_t; + typedef boost::sub_range sub_range_t; + + coll_t c; + c.push_back(0); + + sub_range_t rng(c); + const sub_range_t crng(c); + + check_is_const_iterator(rng.begin()); + check_is_const_iterator(rng.end()); + + check_is_const_iterator(crng.begin()); + check_is_const_iterator(crng.end()); + + check_constant_type(rng[0]); + check_constant_type(rng.front()); + check_constant_type(rng.back()); + check_constant_type(crng[0]); + check_constant_type(crng.front()); + check_constant_type(crng.back()); +} + +inline void test_advance() +{ + std::vector l; + l.push_back(1); + l.push_back(2); + typedef boost::sub_range > rng_t; + rng_t r1(l.begin(), l.end()); + BOOST_CHECK(r1.advance_begin(1).advance_end(-1).empty()); + + rng_t r2(l.begin(), l.end()); + BOOST_CHECK_EQUAL(r2.advance_begin(1).size(), 1u); + + rng_t r3(l.begin(), l.end()); + BOOST_CHECK_EQUAL(r3.advance_end(-1).size(), 1u); +} + +void ticket_10514() +{ + typedef std::vector vec_t; + typedef boost::sub_range range_t; + vec_t v(10); + range_t r(v.begin(), v.end()); + const range_t& cr = r; + range_t copy_r = cr; + + BOOST_CHECK(r.begin() == copy_r.begin()); + BOOST_CHECK(r.end() == copy_r.end()); + + BOOST_CHECK(cr.begin() == copy_r.begin()); + BOOST_CHECK(cr.end() == copy_r.end()); +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite(int, char*[]) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE( "Boost.Range sub_range test suite" ); + + test->add(BOOST_TEST_CASE(&boost_range_test::check_sub_range)); + + test->add(BOOST_TEST_CASE( + &boost_range_test::const_propagation_const_collection)); + + test->add(BOOST_TEST_CASE( + &boost_range_test::const_propagation_mutable_collection)); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_advance)); + + test->add(BOOST_TEST_CASE(&boost_range_test::ticket_10514)); + + return test; +} + + + + + diff --git a/libs/range/test/test_driver/range_overload_test_driver.hpp b/libs/range/test/test_driver/range_overload_test_driver.hpp new file mode 100644 index 00000000..e4b2ce78 --- /dev/null +++ b/libs/range/test/test_driver/range_overload_test_driver.hpp @@ -0,0 +1,74 @@ + // Copyright Neil Groves 2013. Use, modification and + // distribution is subject to 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) + // + // + // For more information, see http://www.boost.org/libs/range/ + // + // Acknowledgments: + // Implemented by Andy in response to Ticket 6888 - unique fix + // + #ifndef BOOST_RANGE_TEST_TEST_DRIVER_RANGE_OVERLOAD_TEST_DRIVER_HPP_INCLUDED + #define BOOST_RANGE_TEST_TEST_DRIVER_RANGE_OVERLOAD_TEST_DRIVER_HPP_INCLUDED + + #include "range_return_test_driver.hpp" + #include + #include + #include + + namespace boost + { + namespace range_test + { + + // A test driver to exercise a test through range_return_test_driver + // plus the overload that determines the return_type by overload + // + // The test driver also contains the code required to check the + // return value correctness. + // + // The TestPolicy needs to implement all those required by + // range_return_test_driver, and additionally + // + // - perform the boost range version of the algorithm that determines + // the return_type by overload + class range_overload_test_driver : range_return_test_driver + { + public: + template< class Container, + class TestPolicy > + void operator()(Container& cont, TestPolicy policy) + { + range_return_test_driver::operator()(cont, policy); + test_range_overload()(cont, policy); + } + + private: + template< class Container, class TestPolicy > + struct test_range_overload + { + void operator()(Container& cont, TestPolicy policy) + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; + typedef BOOST_DEDUCED_TYPENAME TestPolicy::template test_range_overload test_range_overload_t; + const range_return_value result_type = test_range_overload_t::result_type; + typedef BOOST_DEDUCED_TYPENAME range_return::type range_return_t; + + Container reference(cont); + Container test_cont(cont); + + test_range_overload_t test_range_overload_fn; + range_return_t range_result = test_range_overload_fn(policy, test_cont); + + iterator_t reference_it = policy.reference(reference); + + check_results::test(test_cont, reference, + range_result, reference_it); + } + }; + }; + } + } + + #endif // include guard \ No newline at end of file diff --git a/libs/range/test/test_driver/range_return_test_driver.hpp b/libs/range/test/test_driver/range_return_test_driver.hpp new file mode 100644 index 00000000..3dfd2a24 --- /dev/null +++ b/libs/range/test/test_driver/range_return_test_driver.hpp @@ -0,0 +1,406 @@ +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_TEST_TEST_DRIVER_RANGE_RETURN_TEST_DRIVER_HPP_INCLUDED +#define BOOST_RANGE_TEST_TEST_DRIVER_RANGE_RETURN_TEST_DRIVER_HPP_INCLUDED + +#include +#include +#include + +namespace boost +{ + namespace range_test + { + // check the results of an algorithm that returns + // a range_return. + // + // This version is the general version. It should never be called. + // All calls should invoke specialized implementations. + template< range_return_value return_type > + struct check_results + { + template< class Container, class Iterator > + static void test( + Container& test, + Container& reference, + Iterator test_it, + Iterator reference_it + ) + { + BOOST_ASSERT( false ); + } + }; + + // check the results of an algorithm that returns + // a 'found' iterator + template< > + struct check_results + { + template< class Container, class Iterator > + static void test( + Container& test, + Container& reference, + Iterator test_it, + Iterator reference_it + ) + { + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + BOOST_CHECK_EQUAL( std::distance(test.begin(), test_it), + std::distance(reference.begin(), reference_it) ); + } + }; + + // check the results of an algorithm that returns + // a 'next(found)' iterator + template< > + struct check_results + { + template< class Container, class Iterator > + static void test( + Container& test, + Container& reference, + Iterator test_it, + Iterator reference_it + ) + { + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + if (reference_it == reference.end()) + { + BOOST_CHECK( test_it == test.end() ); + } + else + { + BOOST_CHECK_EQUAL( + std::distance(test.begin(), test_it), + std::distance(reference.begin(), reference_it) + 1); + } + } + }; + + // check the results of an algorithm that returns + // a 'prior(found)' iterator + template< > + struct check_results + { + template< class Container, class Iterator > + static void test( + Container& test, + Container& reference, + Iterator test_it, + Iterator reference_it + ) + { + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + if (reference_it == reference.begin()) + { + BOOST_CHECK( test_it == test.begin() ); + } + else + { + BOOST_CHECK_EQUAL( + std::distance(test.begin(), test_it) + 1, + std::distance(reference.begin(), reference_it)); + } + } + }; + + // check the results of an algorithm that returns + // a '[begin, found)' range + template< > + struct check_results + { + template< class Container, class Iterator > + static void test( + Container& test, + Container& reference, + iterator_range test_rng, + Iterator reference_it + ) + { + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + + BOOST_CHECK( test_rng.begin() == test.begin() ); + + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference_it, + boost::begin(test_rng), boost::end(test_rng) + ); + } + }; + + // check the results of an algorithm that returns + // a '[begin, next(found))' range + template< > + struct check_results + { + template< class Container, class Iterator > + static void test( + Container& test, + Container& reference, + iterator_range test_rng, + Iterator reference_it + ) + { + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + + BOOST_CHECK( test_rng.begin() == test.begin() ); + + if (reference_it == reference.end()) + { + BOOST_CHECK( test_rng.end() == test.end() ); + } + else + { + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), boost::next(reference_it), + test_rng.begin(), test_rng.end()); + } + } + }; + + // check the results of an algorithm that returns + // a '[begin, prior(found))' range + template< > + struct check_results + { + template< class Container, class Iterator > + static void test( + Container& test, + Container& reference, + iterator_range test_rng, + Iterator reference_it + ) + { + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + BOOST_CHECK( test_rng.begin() == test.begin() ); + + if (reference_it == reference.begin()) + { + BOOST_CHECK( boost::end(test_rng) == test.begin() ); + } + else + { + BOOST_CHECK_EQUAL( std::distance(boost::begin(test_rng), boost::end(test_rng)) + 1, + std::distance(reference.begin(), reference_it) ); + } + } + }; + + // check the results of an algorithm that returns + // a '[found, end)' range + template< > + struct check_results + { + template< class Container, class Iterator > + static void test( + Container& test, + Container& reference, + iterator_range test_rng, + Iterator reference_it + ) + { + BOOST_CHECK_EQUAL_COLLECTIONS( reference.begin(), reference.end(), + test.begin(), test.end() ); + + BOOST_CHECK_EQUAL( + std::distance(test.begin(), boost::begin(test_rng)), + std::distance(reference.begin(), reference_it)); + + BOOST_CHECK( boost::end(test_rng) == test.end() ); + } + }; + + // check the results of an algorithm that returns + // a '[next(found), end)' range + template< > + struct check_results + { + template< class Container, class Iterator > + static void test( + Container& test, + Container& reference, + iterator_range test_rng, + Iterator reference_it + ) + { + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + + BOOST_CHECK( test_rng.end() == test.end() ); + + if (reference_it == reference.end()) + { + BOOST_CHECK( test_rng.begin() == test.end() ); + } + else + { + BOOST_CHECK_EQUAL_COLLECTIONS( + boost::next(reference_it), reference.end(), + test_rng.begin(), test_rng.end() + ); + } + } + }; + + // check the results of an algorithm that returns + // a 'prior(found), end)' range + template< > + struct check_results + { + template< class Container, class Iterator > + static void test( + Container& test, + Container& reference, + iterator_range test_rng, + Iterator reference_it + ) + { + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + + BOOST_CHECK( test_rng.end() == test.end() ); + + if (reference_it == reference.begin()) + { + BOOST_CHECK( test_rng.begin() == test.begin() ); + } + else + { + BOOST_CHECK_EQUAL_COLLECTIONS( + boost::prior(reference_it), reference.end(), + test_rng.begin(), test_rng.end() + ); + } + } + }; + + // check the results of an algorithm that returns + // a '[begin, end)' range + template< > + struct check_results + { + template< class Container, class Iterator > + static void test( + Container& test, + Container& reference, + iterator_range test_rng, + Iterator reference_it + ) + { + BOOST_CHECK_EQUAL_COLLECTIONS( + reference.begin(), reference.end(), + test.begin(), test.end() + ); + + BOOST_CHECK( test_rng.begin() == test.begin() ); + BOOST_CHECK( test_rng.end() == test.end() ); + } + }; + + // A test driver to exercise a test through all of the range_return + // combinations. + // + // The test driver also contains the code required to check the + // return value correctness. + // + // The TestPolicy needs to implement two functions: + // + // - perform the boost range version of the algorithm that returns + // a range_return::type + // template + // BOOST_DEDUCED_TYPENAME range_return::type + // test(Container& cont); + // + // - perform the reference std version of the algorithm that + // returns the standard iterator result + // template + // BOOST_DEDUCED_TYPENAME range_iterator::type + // reference(Container& cont); + class range_return_test_driver + { + public: + template< class Container, + class TestPolicy > + void operator()(Container& cont, TestPolicy policy) + { + test_range_iter (cont, policy); + test_range ()(cont, policy); + test_range ()(cont, policy); + test_range ()(cont, policy); + test_range()(cont, policy); + test_range ()(cont, policy); + test_range()(cont, policy); + test_range ()(cont, policy); + test_range ()(cont, policy); + test_range ()(cont, policy); + test_range ()(cont, policy); + } + + private: + template< class Container, class TestPolicy > + void test_range_iter( + Container& cont, + TestPolicy policy + ) + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; + + Container reference(cont); + Container test(cont); + + iterator_t range_result = policy.test_iter(test); + iterator_t reference_it = policy.reference(reference); + + check_results::test(test, reference, + range_result, reference_it); + } + + template< range_return_value result_type, class Container, class TestPolicy > + struct test_range + { + void operator()(Container& cont, TestPolicy policy) + { + typedef BOOST_DEDUCED_TYPENAME range_iterator::type iterator_t; + typedef BOOST_DEDUCED_TYPENAME range_return::type range_return_t; + typedef BOOST_DEDUCED_TYPENAME TestPolicy::template test_range test_range_t; + + Container reference(cont); + Container test_cont(cont); + + test_range_t test_range_fn; + range_return_t range_result = test_range_fn(policy, test_cont); + iterator_t reference_it = policy.reference(reference); + + check_results::test(test_cont, reference, + range_result, reference_it); + } + }; + }; + } +} + +#endif // include guard diff --git a/libs/range/test/test_function/check_equal_fn.hpp b/libs/range/test/test_function/check_equal_fn.hpp new file mode 100644 index 00000000..8da2ed83 --- /dev/null +++ b/libs/range/test/test_function/check_equal_fn.hpp @@ -0,0 +1,49 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_TEST_FUNCTIONS_CHECK_EQUAL_FN_HPP_INCLUDED +#define BOOST_RANGE_TEST_FUNCTIONS_CHECK_EQUAL_FN_HPP_INCLUDED + +#include "counted_function.hpp" + +namespace boost +{ + namespace range_test_function + { + template< class Collection > + class check_equal_fn : private counted_function + { + typedef BOOST_DEDUCED_TYPENAME Collection::const_iterator iter_t; + public: + explicit check_equal_fn( const Collection& c ) + : m_it(boost::begin(c)), m_last(boost::end(c)) {} + + using counted_function::invocation_count; + + void operator()(int x) const + { + invoked(); + BOOST_CHECK( m_it != m_last ); + if (m_it != m_last) + { + BOOST_CHECK_EQUAL( *m_it, x ); + ++m_it; + } + } + + private: + mutable iter_t m_it; + iter_t m_last; + }; + + } // namespace range_test_function +} // namespace boost + +#endif // include guard diff --git a/libs/range/test/test_function/counted_function.hpp b/libs/range/test/test_function/counted_function.hpp new file mode 100644 index 00000000..4a74515c --- /dev/null +++ b/libs/range/test/test_function/counted_function.hpp @@ -0,0 +1,40 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_TEST_FUNCTION_COUNTED_FUNCTION_HPP_INCLUDED +#define BOOST_RANGE_TEST_FUNCTION_COUNTED_FUNCTION_HPP_INCLUDED + +namespace boost +{ + namespace range_test_function + { + + class counted_function + { + public: + counted_function() : m_count(0u) {} + + void invoked() const + { + ++m_count; + } + + // Return the number of times that this function object + // has been invoked. + unsigned int invocation_count() const { return m_count; } + + private: + mutable unsigned int m_count; + }; + + } +} + +#endif // include guard diff --git a/libs/range/test/test_function/equal_to_x.hpp b/libs/range/test/test_function/equal_to_x.hpp new file mode 100644 index 00000000..14d00162 --- /dev/null +++ b/libs/range/test/test_function/equal_to_x.hpp @@ -0,0 +1,33 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_TEST_TEST_FUNCTION_EQUAL_TO_X_HPP_INCLUDED +#define BOOST_RANGE_TEST_TEST_FUNCTION_EQUAL_TO_X_HPP_INCLUDED + +namespace boost +{ + namespace range_test_function + { + template + struct equal_to_x + { + typedef bool result_type; + typedef Arg argument_type; + + explicit equal_to_x(Arg x) : m_x(x) {} + bool operator()(Arg x) const { return x == m_x; } + + private: + Arg m_x; + }; + } +} + +#endif // include guard diff --git a/libs/range/test/test_function/false_predicate.hpp b/libs/range/test/test_function/false_predicate.hpp new file mode 100644 index 00000000..533e83d5 --- /dev/null +++ b/libs/range/test/test_function/false_predicate.hpp @@ -0,0 +1,29 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_TEST_TEST_FUNCTION_FALSE_PREDICATE_HPP_INCLUDED +#define BOOST_RANGE_TEST_TEST_FUNCTION_FALSE_PREDICATE_HPP_INCLUDED + +namespace boost +{ + namespace range_test_function + { + struct false_predicate + { + typedef bool result_type; + + bool operator()() const { return false; } + template bool operator()(Arg) const { return false; } + template bool operator()(Arg1,Arg2) const { return false; } + }; + } +} + +#endif // include guard diff --git a/libs/range/test/test_function/greater_than_x.hpp b/libs/range/test/test_function/greater_than_x.hpp new file mode 100644 index 00000000..032f594e --- /dev/null +++ b/libs/range/test/test_function/greater_than_x.hpp @@ -0,0 +1,32 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_TEST_FUNCTION_GREATER_THAN_X_HPP_INCLUDED +#define BOOST_RANGE_TEST_FUNCTION_GREATER_THAN_X_HPP_INCLUDED + +namespace boost +{ + namespace range_test_function + { + template< class Number > + struct greater_than_x + { + typedef bool result_type; + typedef Number argument_type; + + explicit greater_than_x(Number x) : m_x(x) {} + bool operator()(Number x) const { return x > m_x; } + private: + Number m_x; + }; + } // namespace range_test_function +} // namespace boost + +#endif // include guard diff --git a/libs/range/test/test_function/multiply_by_x.hpp b/libs/range/test/test_function/multiply_by_x.hpp new file mode 100644 index 00000000..b343c61e --- /dev/null +++ b/libs/range/test/test_function/multiply_by_x.hpp @@ -0,0 +1,32 @@ +// Boost.Range library +// +// Copyright Neil Groves 2009. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_TEST_TEST_FUNCTION_MULTIPLY_BY_X_HPP_INCLUDED +#define BOOST_RANGE_TEST_TEST_FUNCTION_MULTIPLY_BY_X_HPP_INCLUDED + +namespace boost +{ + namespace range_test_function + { + template< class Arg > + struct multiply_by_x + { + typedef Arg result_type; + typedef Arg argument_type; + + explicit multiply_by_x(Arg x) : m_x(x) {} + Arg operator()(Arg x) const { return x * m_x; } + private: + Arg m_x; + }; + } +} + +#endif // include guard diff --git a/libs/range/test/test_function/true_predicate.hpp b/libs/range/test/test_function/true_predicate.hpp new file mode 100644 index 00000000..87a0dcaf --- /dev/null +++ b/libs/range/test/test_function/true_predicate.hpp @@ -0,0 +1,29 @@ +// Boost.Range library +// +// Copyright Neil Groves 2010. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#ifndef BOOST_RANGE_TEST_TEST_FUNCTION_TRUE_PREDICATE_HPP_INCLUDED +#define BOOST_RANGE_TEST_TEST_FUNCTION_TRUE_PREDICATE_HPP_INCLUDED + +namespace boost +{ + namespace range_test_function + { + struct true_predicate + { + typedef bool result_type; + + bool operator()() const { return true; } + template bool operator()(Arg) const { return true; } + template bool operator()(Arg1,Arg2) const { return true; } + }; + } +} + +#endif // include guard diff --git a/libs/range/test/test_utils.hpp b/libs/range/test/test_utils.hpp new file mode 100644 index 00000000..7af920a4 --- /dev/null +++ b/libs/range/test/test_utils.hpp @@ -0,0 +1,24 @@ +// Boost.Range library +// +// Copyright Akira Takahashi 2013. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include + +template +void check_random_access_range_concept(const RandomAccessRng& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept )); +} + +template +void check_bidirectional_range_concept(const BidirectionalRng& rng) +{ + BOOST_RANGE_CONCEPT_ASSERT(( boost::BidirectionalRangeConcept )); +} diff --git a/libs/range/test/ticket_10336.cpp b/libs/range/test/ticket_10336.cpp new file mode 100644 index 00000000..541e037a --- /dev/null +++ b/libs/range/test/ticket_10336.cpp @@ -0,0 +1,43 @@ +// Boost.Range library +// +// Copyright Neil Groves 2011. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include + +#include +#include + +namespace boost +{ + namespace + { + // Ticket 10336 - compilation error in iterator_range and unordered_map + void test_ticket_10336() + { + typedef boost::unordered_map container_t; + typedef container_t::const_iterator citer_t; + typedef boost::iterator_range rng_t; + + const container_t c; + rng_t rng(c.begin(), c.end()); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.ticket_10336" ); + + test->add( BOOST_TEST_CASE( &boost::test_ticket_10336 ) ); + + return test; +} diff --git a/libs/range/test/ticket_5486.cpp b/libs/range/test/ticket_5486.cpp new file mode 100644 index 00000000..94d8dd4f --- /dev/null +++ b/libs/range/test/ticket_5486.cpp @@ -0,0 +1,58 @@ +// Boost.Range library +// +// Copyright Neil Groves 2011. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include + +#include +#include + +#include + +namespace boost +{ + namespace + { + class TestTicket5486Pred + { + public: + typedef int first_argument_type; + typedef int second_argument_type; + typedef bool result_type; + + explicit TestTicket5486Pred(int x) {} + bool operator()(int,int) const { return true; } + private: + TestTicket5486Pred(); + }; + + // Ticket 5486 - pertained to predicates erroneous + // requiring default construction + void test_ticket_5486() + { + std::vector v; + boost::push_back(v, v | boost::adaptors::adjacent_filtered(TestTicket5486Pred(1))); + + BOOST_CHECK_EQUAL_COLLECTIONS( v.begin(), v.end(), + v.begin(), v.end() ); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.ticket_5486" ); + + test->add( BOOST_TEST_CASE( &boost::test_ticket_5486 ) ); + + return test; +} diff --git a/libs/range/test/ticket_5544_terminate_irange.cpp b/libs/range/test/ticket_5544_terminate_irange.cpp new file mode 100644 index 00000000..fa64436c --- /dev/null +++ b/libs/range/test/ticket_5544_terminate_irange.cpp @@ -0,0 +1,47 @@ +// Boost.Range library +// +// Copyright Neil Groves 2011. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include + +#include +#include + +#include + +namespace boost +{ + namespace + { + void test_irange_termination() + { + std::vector reference; + for (int i = 0; i < 9; i += 2) + reference.push_back(i); + + std::vector actual; + boost::push_back(actual, boost::irange(0,9,2)); + + BOOST_CHECK_EQUAL_COLLECTIONS(actual.begin(), actual.end(), + reference.begin(), reference.end()); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.ticket_5544" ); + + test->add( BOOST_TEST_CASE( &boost::test_irange_termination ) ); + + return test; +} diff --git a/libs/range/test/ticket_5547.cpp b/libs/range/test/ticket_5547.cpp new file mode 100644 index 00000000..1b9d3f6f --- /dev/null +++ b/libs/range/test/ticket_5547.cpp @@ -0,0 +1,42 @@ +// Boost.Range library +// +// Copyright Neil Groves 2011. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include + +#include +#include + +#include + +namespace boost +{ + namespace + { + + // Ticket 5547 - boost::join ambiguous with algorithm::join + void test_ticket_5547() + { + std::vector x; + boost::range::join(x,x); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.ticket_5547" ); + + test->add( BOOST_TEST_CASE( &boost::test_ticket_5547 ) ); + + return test; +} diff --git a/libs/range/test/ticket_5556_is_sorted_namespace.cpp b/libs/range/test/ticket_5556_is_sorted_namespace.cpp new file mode 100644 index 00000000..78a75cde --- /dev/null +++ b/libs/range/test/ticket_5556_is_sorted_namespace.cpp @@ -0,0 +1,37 @@ +// Boost.Range library +// +// Copyright Neil Groves 2011. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// + +// Embarrasingly, the mere inclusion of these headers in this order was +// enough to trigger the defect. +#include +#include + +#include +#include + +namespace boost +{ + namespace + { + void test_ticket_5556() {} + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.ticket_5556" ); + + test->add( BOOST_TEST_CASE( &boost::test_ticket_5556 ) ); + + return test; +} diff --git a/libs/range/test/ticket_5811_indirected_optional.cpp b/libs/range/test/ticket_5811_indirected_optional.cpp new file mode 100644 index 00000000..1279a4a4 --- /dev/null +++ b/libs/range/test/ticket_5811_indirected_optional.cpp @@ -0,0 +1,48 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include + +#include +#include + +#include + +namespace boost +{ + namespace + { + void test_ticket_5811_indirected_optional() + { + std::vector > v; + std::vector r; + for (int i = 0; i < 10; ++i) + { + v.push_back(i); + r.push_back(i); + } + BOOST_CHECK_EQUAL_COLLECTIONS(r.begin(), r.end(), + v.begin(), v.end()); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE("RangeTestSuite.ticket_5811_indirected_optional"); + + test->add(BOOST_TEST_CASE(&boost::test_ticket_5811_indirected_optional)); + + return test; +} diff --git a/libs/range/test/ticket_6715_iterator_range_equality.cpp b/libs/range/test/ticket_6715_iterator_range_equality.cpp new file mode 100644 index 00000000..6c6972df --- /dev/null +++ b/libs/range/test/ticket_6715_iterator_range_equality.cpp @@ -0,0 +1,52 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include + +#include +#include +#include + +namespace boost +{ + namespace + { + class str_ref : public boost::iterator_range + { + public: + explicit str_ref(const std::string& str) + : boost::iterator_range( + str.c_str(), str.c_str() + str.size()) + { + } + }; + + void test_ticket_6715_iterator_range_equality() + { + std::string src("test"); + str_ref a(src); + str_ref b(src); + BOOST_CHECK(a == b); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( + "RangeTestSuite.ticket_6715_iterator_range_equality"); + + test->add(BOOST_TEST_CASE( + &boost::test_ticket_6715_iterator_range_equality)); + + return test; +} diff --git a/libs/range/test/ticket_6944.cpp b/libs/range/test/ticket_6944.cpp new file mode 100644 index 00000000..43796a8c --- /dev/null +++ b/libs/range/test/ticket_6944.cpp @@ -0,0 +1,46 @@ +// Boost.Range library +// +// Copyright Neil Groves 2011. Use, modification and +// distribution is subject to 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) +// +// +// For more information, see http://www.boost.org/libs/range/ +// +#include +#include +#include +#include + +#include +#include + +#include + +namespace boost +{ + typedef std::vector::iterator iter_base; + struct iter : boost::iterator_adaptor {}; // will be deduced as random-access traversal but input category + typedef boost::iterator_range iter_range; + + namespace + { + // Ticket 6944 - Some Range concepts use the incorrect Iterator concept + void test_ticket_6944() + { + BOOST_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept )); + } + } +} + +boost::unit_test::test_suite* +init_unit_test_suite(int argc, char* argv[]) +{ + boost::unit_test::test_suite* test + = BOOST_TEST_SUITE( "RangeTestSuite.ticket_6944" ); + + test->add( BOOST_TEST_CASE( &boost::test_ticket_6944 ) ); + + return test; +} diff --git a/libs/range/test/value_type.cpp b/libs/range/test/value_type.cpp new file mode 100644 index 00000000..9a18b2f2 --- /dev/null +++ b/libs/range/test/value_type.cpp @@ -0,0 +1,61 @@ +// Boost.Range library +// +// Copyright Neil Groves 2014. Use, modification and +// distribution is subject to 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) +// +// For more information, see http://www.boost.org/libs/range/ +// + +#include +#include +#include + +#include +#include + +#include + +namespace boost_range_test +{ + namespace + { + +void test_value_type() +{ + typedef std::vector cont; + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::value_type, + boost::range_value::type + >::value)); + + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::value_type, + boost::range_value::type + >::value)); + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + BOOST_STATIC_ASSERT(( + boost::is_same< + cont::value_type, + boost::range_value::type + >::value)); +#endif +} + + } // anonymous namespace +} // namespace boost_range_test + +boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) +{ + boost::unit_test::test_suite* test = + BOOST_TEST_SUITE("Boost.Range range_value meta-function"); + + test->add(BOOST_TEST_CASE(&boost_range_test::test_value_type)); + + return test; +} diff --git a/libs/regex/build/Jamfile.v2 b/libs/regex/build/Jamfile.v2 new file mode 100644 index 00000000..08f98195 --- /dev/null +++ b/libs/regex/build/Jamfile.v2 @@ -0,0 +1,165 @@ +# copyright John Maddock 2003 +# 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. + +import modules ; +import testing ; +import errors ; + +project : requirements + # default to all warnings on: + all + ; + +local disable-icu = [ MATCH (--disable-icu) : [ modules.peek : ARGV ] ] ; + +rule path_options ( properties * ) +{ + local result ; + if 64 in $(properties) && msvc in $(properties) + { + result = $(ICU_PATH)/bin64 $(ICU_PATH)/lib64 ; + } + else + { + result = $(ICU_PATH)/bin $(ICU_PATH)/lib ; + } + return $(result) ; +} + +# +# ICU configuration: +# +if ! $(disable-icu) +{ + if [ modules.peek : ICU_LINK ] + { + errors.user-error : "The ICU_LINK option is no longer supported by the Boost.Regex build - please refer to the documentation for equivalent options" ; + } + + if [ modules.peek : ICU_PATH ] + { + ICU_PATH = [ modules.peek : ICU_PATH ] ; + } + if [ modules.peek : ICU_ICUUC_NAME ] + { + ICU_ICUUC_NAME = [ modules.peek : ICU_ICUUC_NAME ] ; + } + if [ modules.peek : ICU_ICUDT_NAME ] + { + ICU_ICUDT_NAME = [ modules.peek : ICU_ICUDT_NAME ] ; + } + if [ modules.peek : ICU_ICUIN_NAME ] + { + ICU_ICUIN_NAME = [ modules.peek : ICU_ICUIN_NAME ] ; + } + + if $(ICU_ICUUC_NAME) + { + lib icuuc : : $(ICU_ICUUC_NAME) @path_options ; + } + else + { + lib icuuc : : shared @path_options ; + lib icuuc : : msvc debug icuucd shared @path_options ; + lib icuuc : : intel windows debug icuucd shared @path_options ; + lib icuuc : : sicuuc static @path_options ; + lib icuuc : : msvc debug sicuucd static @path_options ; + lib icuuc : : intel windows debug sicuucd static @path_options ; + lib icuuc : : this_is_an_invalid_library_name ; + } + if $(ICU_ICUDT_NAME) + { + lib icudt : : $(ICU_ICUDT_NAME) @path_options ; + } + else + { + lib icudt : : icudata shared @path_options ; + lib icudt : : icudt msvc shared @path_options ; + lib icudt : : icudt intel windows shared @path_options ; + lib icudt : : sicudata static @path_options ; + lib icudt : : sicudt msvc static @path_options ; + lib icudt : : sicudt intel windows static @path_options ; + lib icudt : : this_is_an_invalid_library_name ; + } + if $(ICU_ICUIN_NAME) + { + lib icuin : : $(ICU_ICUIN_NAME) @path_options ; + } + else + { + lib icuin : : icui18n shared @path_options ; + lib icuin : : msvc debug icuind shared @path_options ; + lib icuin : : msvc icuin shared @path_options ; + lib icuin : : intel windows debug icuind shared @path_options ; + lib icuin : : intel windows icuin shared @path_options ; + lib icuin : : sicui18n static @path_options ; + lib icuin : : msvc debug sicuind static @path_options ; + lib icuin : : msvc sicuin static @path_options ; + lib icuin : : intel windows debug sicuind static @path_options ; + lib icuin : : intel windows sicuin static @path_options ; + lib icuin : : this_is_an_invalid_library_name ; + } + + ICU_OPTS = + $(ICU_PATH)/include + shared:icuuc/shared + shared:icudt/shared + shared:icuin/shared + static:icuuc + static:icudt + static:icuin + windows,clang:"advapi32.lib" + BOOST_HAS_ICU=1 + static:U_STATIC_IMPLEMENTATION=1 + ; + + if [ modules.peek : ICU_DATA_DIR ] + { + rule data-dir-options ( properties * ) + { + local result ; + local data_dir = [ modules.peek : ICU_DATA_DIR ] ; + if emscripten in $(properties) + { + result = ICU_DATA_DIR=\\\"/$(data_dir:BS)\\\" + "--embed-file $(data_dir)@/$(data_dir:BS)" + ; + } + else + { + result = ICU_DATA_DIR=\\\"$(data_dir)\\\" ; + } + return $(result) ; + } + + ICU_OPTS += @data-dir-options ; + } + +} + +exe has_icu : has_icu_test.cpp : $(ICU_OPTS) ; +explicit has_icu ; + +obj is_legacy_03 : is_legacy_03.cpp ; +explicit is_legacy_03 ; + +alias icu_options : : : : [ check-target-builds has_icu : $(ICU_OPTS) : ] ; + +SOURCES = + posix_api.cpp + regex.cpp + regex_debug.cpp + static_mutex.cpp + wide_posix_api.cpp +; + +lib boost_regex : ../src/$(SOURCES) icu_options + : + shared:BOOST_REGEX_DYN_LINK=1 + gcc-cygwin:static + ; + +boost-install boost_regex ; + diff --git a/libs/regex/build/has_icu_test.cpp b/libs/regex/build/has_icu_test.cpp new file mode 100644 index 00000000..36a919b4 --- /dev/null +++ b/libs/regex/build/has_icu_test.cpp @@ -0,0 +1,56 @@ +/* + * + * Copyright (c) 2010 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) && !defined(_DLL) +//#error "Mixing ICU with a static runtime doesn't work" +#endif + +void print_error(UErrorCode err, const char* func) +{ + std::cerr << "Error from function " << func << " with error: " << ::u_errorName(err) << std::endl; +} + +int main() +{ +#ifdef ICU_DATA_DIR + ::u_setDataDirectory(ICU_DATA_DIR); +#endif + + // To detect possible binary mismatches between the installed ICU build, and whatever + // C++ std lib's we're using, we need to: + // * Make sure we call ICU C++ API's + // * Make sure we call std lib C++ API's as well (cout). + // * Be sure this program is run, not just built. + UErrorCode err = U_ZERO_ERROR; + UChar32 c = ::u_charFromName(U_UNICODE_CHAR_NAME, "GREEK SMALL LETTER ALPHA", &err); + std::cout << (int)c << std::endl; + if(err > 0) + { + print_error(err, "u_charFromName"); + return err; + } + U_NAMESPACE_QUALIFIER Locale l; + boost::scoped_ptr p_col(U_NAMESPACE_QUALIFIER Collator::createInstance(l, err)); + if(err > 0) + { + print_error(err, "Collator::createInstance"); + return err; + } + return err > 0 ? err : 0; +} diff --git a/libs/regex/build/is_legacy_03.cpp b/libs/regex/build/is_legacy_03.cpp new file mode 100644 index 00000000..78c36e19 --- /dev/null +++ b/libs/regex/build/is_legacy_03.cpp @@ -0,0 +1,16 @@ +/* + * + * Copyright (c) 2020 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + +#include + +#ifdef BOOST_REGEX_CXX03 +#error "Legacy mode" +#endif diff --git a/libs/regex/src/internals.hpp b/libs/regex/src/internals.hpp new file mode 100644 index 00000000..3a15cc67 --- /dev/null +++ b/libs/regex/src/internals.hpp @@ -0,0 +1,35 @@ +/* + * + * Copyright (c) 2011 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + +#ifndef BOOST_REGEX_SRC_INTERNALS_HPP +#define BOOST_REGEX_SRC_INTERNALS_HPP + +enum +{ + char_class_space=1<<0, + char_class_print=1<<1, + char_class_cntrl=1<<2, + char_class_upper=1<<3, + char_class_lower=1<<4, + char_class_alpha=1<<5, + char_class_digit=1<<6, + char_class_punct=1<<7, + char_class_xdigit=1<<8, + char_class_alnum=char_class_alpha|char_class_digit, + char_class_graph=char_class_alnum|char_class_punct, + char_class_blank=1<<9, + char_class_word=1<<10, + char_class_unicode=1<<11, + char_class_horizontal=1<<12, + char_class_vertical=1<<13 +}; + +#endif // BOOST_REGEX_SRC_INTERNALS_HPP diff --git a/libs/regex/src/posix_api.cpp b/libs/regex/src/posix_api.cpp new file mode 100644 index 00000000..e30f9d8e --- /dev/null +++ b/libs/regex/src/posix_api.cpp @@ -0,0 +1,290 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE: posix_api.cpp + * VERSION: see + * DESCRIPTION: Implements the Posix API wrappers. + */ + +#define BOOST_REGEX_SOURCE + +#include +#include +#include + +#ifndef BOOST_WORKAROUND +#define BOOST_WORKAROUND(x, y) false +#endif + +#ifndef BOOST_REGEX_STANDALONE +#include +#else +namespace boost { namespace core { using std::snprintf; } } +#endif + +namespace boost{ + +namespace{ + +unsigned int magic_value = 25631; + +const char* names[] = { + "REG_NOERROR", + "REG_NOMATCH", + "REG_BADPAT", + "REG_ECOLLATE", + "REG_ECTYPE", + "REG_EESCAPE", + "REG_ESUBREG", + "REG_EBRACK", + "REG_EPAREN", + "REG_EBRACE", + "REG_BADBR", + "REG_ERANGE", + "REG_ESPACE", + "REG_BADRPT", + "REG_EEND", + "REG_ESIZE", + "REG_ERPAREN", + "REG_EMPTY", + "REG_ECOMPLEXITY", + "REG_ESTACK", + "REG_E_PERL", + "REG_E_UNKNOWN", +}; +} // namespace + +typedef boost::basic_regex > c_regex_type; + +#ifdef BOOST_MSVC +# pragma warning(push) +#pragma warning(disable:26812) +#endif +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompA(regex_tA* expression, const char* ptr, int f) +{ +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + expression->guts = new c_regex_type(); +#ifndef BOOST_NO_EXCEPTIONS + } catch(...) + { + expression->guts = 0; + return REG_ESPACE; + } +#else + if(0 == expression->guts) + return REG_E_MEMORY; +#endif + // set default flags: + unsigned flags = (f & REG_PERLEX) ? 0 : ((f & REG_EXTENDED) ? regex::extended : regex::basic); + expression->eflags = (f & REG_NEWLINE) ? match_not_dot_newline : match_default; + // and translate those that are actually set: + + if(f & REG_NOCOLLATE) + { + flags |= regex::nocollate; +#ifndef BOOST_REGEX_V3 + flags &= ~regex::collate; +#endif + } + + if(f & REG_NOSUB) + { + //expression->eflags |= match_any; + flags |= regex::nosubs; + } + + if(f & REG_NOSPEC) + flags |= regex::literal; + if(f & REG_ICASE) + flags |= regex::icase; + if(f & REG_ESCAPE_IN_LISTS) + flags &= ~regex::no_escape_in_lists; + if(f & REG_NEWLINE_ALT) + flags |= regex::newline_alt; + + const char* p2; + if(f & REG_PEND) + p2 = expression->re_endp; + else p2 = ptr + std::strlen(ptr); + + int result; + +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + expression->re_magic = magic_value; + static_cast(expression->guts)->set_expression(ptr, p2, flags); + expression->re_nsub = static_cast(expression->guts)->mark_count(); + result = static_cast(expression->guts)->error_code(); +#ifndef BOOST_NO_EXCEPTIONS + } + catch(const boost::regex_error& be) + { + result = be.code(); + } + catch(...) + { + result = REG_E_UNKNOWN; + } +#endif + if(result) + regfreeA(expression); + return result; + +} +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int code, const regex_tA* e, char* buf, regsize_t buf_size) +{ + std::size_t result = 0; + if(code & REG_ITOA) + { + code &= ~REG_ITOA; + if(code <= (int)REG_E_UNKNOWN) + { + result = std::strlen(names[code]) + 1; + if(buf_size >= result) + BOOST_REGEX_DETAIL_NS::strcpy_s(buf, buf_size, names[code]); + return result; + } + return result; + } + if(code == REG_ATOI) + { + char localbuf[5]; + if(e == 0) + return 0; + for(int i = 0; i <= (int)REG_E_UNKNOWN; ++i) + { + if(std::strcmp(e->re_endp, names[i]) == 0) + { + // + // We're converting an integer i to a string, and since i <= REG_E_UNKNOWN + // a five character string is *always* large enough: + // + int r = (boost::core::snprintf)(localbuf, 5, "%d", i); + if(r < 0) + return 0; // sprintf failed + if(std::strlen(localbuf) < buf_size) + BOOST_REGEX_DETAIL_NS::strcpy_s(buf, buf_size, localbuf); + return std::strlen(localbuf) + 1; + } + } + int r = (boost::core::snprintf)(localbuf, 5, "%d", 0); + if(r < 0) + return 0; // sprintf failed + if(std::strlen(localbuf) < buf_size) + BOOST_REGEX_DETAIL_NS::strcpy_s(buf, buf_size, localbuf); + return std::strlen(localbuf) + 1; + } + if(code <= (int)REG_E_UNKNOWN) + { + std::string p; + if((e) && (e->re_magic == magic_value)) + p = static_cast(e->guts)->get_traits().error_string(static_cast< ::boost::regex_constants::error_type>(code)); + else + { + p = BOOST_REGEX_DETAIL_NS::get_default_error_string(static_cast< ::boost::regex_constants::error_type>(code)); + } + std::size_t len = p.size(); + if(len < buf_size) + { + BOOST_REGEX_DETAIL_NS::strcpy_s(buf, buf_size, p.c_str()); + } + return len + 1; + } + if(buf_size) + *buf = 0; + return 0; +} + +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecA(const regex_tA* expression, const char* buf, regsize_t n, regmatch_t* array, int eflags) +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4267) +#endif + bool result = false; + match_flag_type flags = match_default | expression->eflags; + const char* end; + const char* start; + cmatch m; + + if(eflags & REG_NOTBOL) + flags |= match_not_bol; + if(eflags & REG_NOTEOL) + flags |= match_not_eol; + if(eflags & REG_STARTEND) + { + start = buf + array[0].rm_so; + end = buf + array[0].rm_eo; + } + else + { + start = buf; + end = buf + std::strlen(buf); + } + +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + if(expression->re_magic == magic_value) + { + result = regex_search(start, end, m, *static_cast(expression->guts), flags); + } + else + return result; +#ifndef BOOST_NO_EXCEPTIONS + } catch(...) + { + return REG_E_UNKNOWN; + } +#endif + + if(result) + { + // extract what matched: + std::size_t i; + for(i = 0; (i < n) && (i < expression->re_nsub + 1); ++i) + { + array[i].rm_so = m[i].matched ? (m[i].first - buf) : -1; + array[i].rm_eo = m[i].matched ? (m[i].second - buf) : -1; + } + // and set anything else to -1: + for(i = expression->re_nsub + 1; i < n; ++i) + { + array[i].rm_so = -1; + array[i].rm_eo = -1; + } + return 0; + } + return REG_NOMATCH; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeA(regex_tA* expression) +{ + if(expression->re_magic == magic_value) + { + delete static_cast(expression->guts); + } + expression->re_magic = 0; +} + +} // namespace boost diff --git a/libs/regex/src/regex.cpp b/libs/regex/src/regex.cpp new file mode 100644 index 00000000..2d923955 --- /dev/null +++ b/libs/regex/src/regex.cpp @@ -0,0 +1,120 @@ +/* + * + * Copyright (c) 1998-2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE: regex.cpp + * VERSION: see + * DESCRIPTION: Misc boost::regbase member funnctions. + */ + + +#define BOOST_REGEX_SOURCE + +#include + +#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD + +#include + +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMINMAX +# define NOMINMAX +#endif +#define NOGDI +#define NOUSER +#include +#include +#include +#include + +namespace boost { +namespace BOOST_REGEX_DETAIL_NS { + +static void execute_eror() +{ + // we only get here after a stack overflow, + // this has to be a separate proceedure because we + // can't mix __try{}__except block with local objects + // that have destructors: + reset_stack_guard_page(); + std::runtime_error err("Out of stack space, while attempting to match a regular expression."); + raise_runtime_error(err); +} + +bool BOOST_REGEX_CALL abstract_protected_call::execute()const +{ + __try{ + return this->call(); + }__except(EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) + { + execute_eror(); + } + // We never really get here at all: + return false; +} + +BOOST_REGEX_DECL void BOOST_REGEX_CALL reset_stack_guard_page() +{ +#if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && defined(_MSC_VER) && (_MSC_VER >= 1300) + _resetstkoflw(); +#else + // + // We need to locate the current page being used by the stack, + // move to the page below it and then deallocate and protect + // that page. Note that ideally we would protect only the lowest + // stack page that has been allocated: in practice there + // seems to be no easy way to locate this page, in any case as + // long as the next page is protected, then Windows will figure + // the rest out for us... + // + SYSTEM_INFO si; + GetSystemInfo(&si); + MEMORY_BASIC_INFORMATION mi; + DWORD previous_protection_status; + // + // this is an address in our stack space: + // + LPBYTE page = (LPBYTE)&page; + // + // Get the current memory page in use: + // + VirtualQuery(page, &mi, sizeof(mi)); + // + // Go to the page one below this: + // + page = (LPBYTE)(mi.BaseAddress)-si.dwPageSize; + // + // Free and protect everything from the start of the + // allocation range, to the end of the page below the + // one in use: + // + if (!VirtualFree(mi.AllocationBase, (LPBYTE)page - (LPBYTE)mi.AllocationBase, MEM_DECOMMIT) + || !VirtualProtect(page, si.dwPageSize, PAGE_GUARD | PAGE_READWRITE, &previous_protection_status)) + { + throw std::bad_exception(); + } +#endif +} +} +} // namspaces +#endif + +#if defined(BOOST_RE_USE_VCL) && defined(BOOST_REGEX_DYN_LINK) + +int WINAPI DllEntryPoint(HINSTANCE , unsigned long , void*) +{ + return 1; +} +#endif + diff --git a/libs/regex/src/regex_debug.cpp b/libs/regex/src/regex_debug.cpp new file mode 100644 index 00000000..9306a82e --- /dev/null +++ b/libs/regex/src/regex_debug.cpp @@ -0,0 +1,59 @@ +/* + * + * Copyright (c) 1998-2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE: regex_debug.cpp + * VERSION: see + * DESCRIPTION: Misc. debugging helpers. + */ + + +#define BOOST_REGEX_SOURCE + +#include + + +// +// regex configuration information: this prints out the settings used +// when the library was built - include in debugging builds only: +// +#ifdef BOOST_REGEX_CONFIG_INFO + +#define print_macro regex_lib_print_macro +#define print_expression regex_lib_print_expression +#define print_byte_order regex_lib_print_byte_order +#define print_sign regex_lib_print_sign +#define print_compiler_macros regex_lib_print_compiler_macros +#define print_stdlib_macros regex_lib_print_stdlib_macros +#define print_platform_macros regex_lib_print_platform_macros +#define print_boost_macros regex_lib_print_boost_macros +#define print_separator regex_lib_print_separator +#define OLD_MAIN regex_lib_main +#define NEW_MAIN regex_lib_main2 +#define NO_RECURSE + +#include + +BOOST_REGEX_DECL void BOOST_REGEX_CALL print_regex_library_info() +{ + std::cout << "\n\n"; + print_separator(); + std::cout << "Regex library build configuration:\n\n"; + regex_lib_main2(); +} + +#endif + + + + + diff --git a/libs/regex/src/static_mutex.cpp b/libs/regex/src/static_mutex.cpp new file mode 100644 index 00000000..b238b44a --- /dev/null +++ b/libs/regex/src/static_mutex.cpp @@ -0,0 +1,189 @@ +/* + * + * Copyright (c) 2004 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE static_mutex.cpp + * VERSION see + * DESCRIPTION: Declares static_mutex lock type. + */ + +#define BOOST_REGEX_SOURCE +#include + +#if defined(BOOST_REGEX_CXX03) + +#include + +#ifdef BOOST_HAS_THREADS + +#include + +#if defined(BOOST_HAS_WINTHREADS) +#ifndef NOMINMAX +# define NOMINMAX +#endif +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#endif + + +namespace boost{ + +#if defined(BOOST_HAS_PTHREADS) && defined(PTHREAD_MUTEX_INITIALIZER) + +scoped_static_mutex_lock::scoped_static_mutex_lock(static_mutex& m, bool lk) +: m_mutex(m), m_have_lock(false) +{ + if(lk) + lock(); +} + +scoped_static_mutex_lock::~scoped_static_mutex_lock() +{ + if(m_have_lock) + unlock(); +} + +void scoped_static_mutex_lock::lock() +{ + if(0 == m_have_lock) + { + // Client code will throw if this fails: + m_have_lock = (pthread_mutex_lock(&(m_mutex.m_mutex)) == 0); + } +} + +void scoped_static_mutex_lock::unlock() +{ + if(m_have_lock) + { + // If this fails there's nothing we can do except assert, + // exceptions are out of the question as this code is called + // from the lock's destructor: + BOOST_VERIFY(pthread_mutex_unlock(&(m_mutex.m_mutex)) == 0); + m_have_lock = false; + } +} + +#elif defined(BOOST_HAS_WINTHREADS) + +BOOST_STATIC_ASSERT(sizeof(LONG) == sizeof(boost::int32_t)); + +scoped_static_mutex_lock::scoped_static_mutex_lock(static_mutex& m, bool lk) +: m_mutex(m), m_have_lock(false) +{ + if(lk) + lock(); +} + +scoped_static_mutex_lock::~scoped_static_mutex_lock() +{ + if(m_have_lock) + unlock(); +} + +void scoped_static_mutex_lock::lock() +{ + if(0 == m_have_lock) + { +#if !defined(InterlockedCompareExchangePointer) + while(0 != InterlockedCompareExchange(reinterpret_cast((boost::uint_least16_t*)&(m_mutex.m_mutex)), (void*)1, 0)) +#else + while(0 != InterlockedCompareExchange(reinterpret_cast(&(m_mutex.m_mutex)), 1, 0)) +#endif + { + Sleep(0); + } + m_have_lock = true; + } +} + +void scoped_static_mutex_lock::unlock() +{ + if(m_have_lock) + { +#if !defined(InterlockedCompareExchangePointer) + InterlockedExchange((LONG*)&(m_mutex.m_mutex), 0); +#else + InterlockedExchange(reinterpret_cast(&(m_mutex.m_mutex)), 0); +#endif + m_have_lock = false; + } +} + +#else +// +// Portable version of a static mutex based on Boost.Thread library: +// +#include +#include + +boost::recursive_mutex* static_mutex::m_pmutex = 0; +boost::once_flag static_mutex::m_once = BOOST_ONCE_INIT; + +extern "C" BOOST_REGEX_DECL void boost_regex_free_static_mutex() +{ + delete static_mutex::m_pmutex; + static_mutex::m_pmutex = 0; +} + +void static_mutex::init() +{ + m_pmutex = new boost::recursive_mutex(); + int r = atexit(boost_regex_free_static_mutex); + BOOST_ASSERT(0 == r); +} + +scoped_static_mutex_lock::scoped_static_mutex_lock(static_mutex& , bool lk) +: m_plock(0), m_have_lock(false) +{ + if(lk) + lock(); +} + +scoped_static_mutex_lock::~scoped_static_mutex_lock() +{ + if(m_have_lock) + unlock(); + delete m_plock; +} + +void scoped_static_mutex_lock::lock() +{ + if(0 == m_have_lock) + { + boost::call_once(static_mutex::m_once,&static_mutex::init); + if(0 == m_plock) + m_plock = new boost::unique_lock(*static_mutex::m_pmutex, boost::defer_lock); + m_plock->lock(); + m_have_lock = true; + } +} + +void scoped_static_mutex_lock::unlock() +{ + if(m_have_lock) + { + m_plock->unlock(); + m_have_lock = false; + } +} + +#endif + +} + +#endif // BOOST_HAS_THREADS +#endif diff --git a/libs/regex/src/wide_posix_api.cpp b/libs/regex/src/wide_posix_api.cpp new file mode 100644 index 00000000..993464f8 --- /dev/null +++ b/libs/regex/src/wide_posix_api.cpp @@ -0,0 +1,314 @@ +/* + * + * Copyright (c) 1998-2002 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE: wide_posix_api.cpp + * VERSION: see + * DESCRIPTION: Implements the wide character POSIX API wrappers. + */ + +#define BOOST_REGEX_SOURCE + +#include + +#ifndef BOOST_NO_WREGEX + +#include +#include + +#ifndef BOOST_REGEX_STANDALONE +#include +#else +namespace boost { namespace core { using std::swprintf; } } +#endif + +#ifndef BOOST_WORKAROUND +#define BOOST_WORKAROUND(x, y) false +#endif + +#include +#include +#include + +#ifdef BOOST_INTEL +#pragma warning(disable:981) +#endif + +namespace boost{ + +namespace { + +unsigned int wmagic_value = 28631; + +const wchar_t* wnames[] = { + L"REG_NOERROR", + L"REG_NOMATCH", + L"REG_BADPAT", + L"REG_ECOLLATE", + L"REG_ECTYPE", + L"REG_EESCAPE", + L"REG_ESUBREG", + L"REG_EBRACK", + L"REG_EPAREN", + L"REG_EBRACE", + L"REG_BADBR", + L"REG_ERANGE", + L"REG_ESPACE", + L"REG_BADRPT", + L"REG_EEND", + L"REG_ESIZE", + L"REG_ERPAREN", + L"REG_EMPTY", + L"REG_ECOMPLEXITY", + L"REG_ESTACK", + L"REG_E_PERL", + L"REG_E_UNKNOWN", +}; +} + +typedef boost::basic_regex > wc_regex_type; + +#ifdef BOOST_MSVC +# pragma warning(push) +#pragma warning(disable:26812) +#endif +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompW(regex_tW* expression, const wchar_t* ptr, int f) +{ +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + expression->guts = new wc_regex_type(); +#ifndef BOOST_NO_EXCEPTIONS + } catch(...) + { + expression->guts = 0; + return REG_ESPACE; + } +#else + if(0 == expression->guts) + return REG_E_MEMORY; +#endif + // set default flags: + unsigned flags = (f & REG_PERLEX) ? 0 : ((f & REG_EXTENDED) ? wregex::extended : wregex::basic); + expression->eflags = (f & REG_NEWLINE) ? match_not_dot_newline : match_default; + + // and translate those that are actually set: + if(f & REG_NOCOLLATE) + { + flags |= wregex::nocollate; +#ifndef BOOST_REGEX_V3 + flags &= ~wregex::collate; +#endif + } + + if(f & REG_NOSUB) + { + //expression->eflags |= match_any; + flags |= wregex::nosubs; + } + + if(f & REG_NOSPEC) + flags |= wregex::literal; + if(f & REG_ICASE) + flags |= wregex::icase; + if(f & REG_ESCAPE_IN_LISTS) + flags &= ~wregex::no_escape_in_lists; + if(f & REG_NEWLINE_ALT) + flags |= wregex::newline_alt; + + const wchar_t* p2; + if(f & REG_PEND) + p2 = expression->re_endp; + else p2 = ptr + std::wcslen(ptr); + + int result; + +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + expression->re_magic = wmagic_value; + static_cast(expression->guts)->set_expression(ptr, p2, flags); + expression->re_nsub = static_cast(expression->guts)->mark_count(); + result = static_cast(expression->guts)->error_code(); +#ifndef BOOST_NO_EXCEPTIONS + } + catch(const boost::regex_error& be) + { + result = be.code(); + } + catch(...) + { + result = REG_E_UNKNOWN; + } +#endif + if(result) + regfreeW(expression); + return result; + +} +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int code, const regex_tW* e, wchar_t* buf, regsize_t buf_size) +{ + std::size_t result = 0; + if(code & REG_ITOA) + { + code &= ~REG_ITOA; + if((code <= (int)REG_E_UNKNOWN) && (code >= 0)) + { + result = std::wcslen(wnames[code]) + 1; + if(buf_size >= result) +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(_WIN32_WCE) && !defined(UNDER_CE) + ::wcscpy_s(buf, buf_size, wnames[code]); +#else + std::wcscpy(buf, wnames[code]); +#endif + return result; + } + return result; + } + if(code == REG_ATOI) + { + wchar_t localbuf[5]; + if(e == 0) + return 0; + for(int i = 0; i <= (int)REG_E_UNKNOWN; ++i) + { + if(std::wcscmp(e->re_endp, wnames[i]) == 0) + { +#if defined(_WIN32_WCE) && !defined(UNDER_CE) + (std::swprintf)(localbuf, L"%d", i); +#else + (boost::core::swprintf)(localbuf, 5, L"%d", i); +#endif + if(std::wcslen(localbuf) < buf_size) +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(_WIN32_WCE) && !defined(UNDER_CE) + ::wcscpy_s(buf, buf_size, localbuf); +#else + std::wcscpy(buf, localbuf); +#endif + return std::wcslen(localbuf) + 1; + } + } +#if defined(_WIN32_WCE) && !defined(UNDER_CE) + (std::swprintf)(localbuf, L"%d", 0); +#else + (boost::core::swprintf)(localbuf, 5, L"%d", 0); +#endif + if(std::wcslen(localbuf) < buf_size) +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(_WIN32_WCE) && !defined(UNDER_CE) + ::wcscpy_s(buf, buf_size, localbuf); +#else + std::wcscpy(buf, localbuf); +#endif + return std::wcslen(localbuf) + 1; + } + if(code <= (int)REG_E_UNKNOWN) + { + std::string p; + if((e) && (e->re_magic == wmagic_value)) + p = static_cast(e->guts)->get_traits().error_string(static_cast< ::boost::regex_constants::error_type>(code)); + else + { + p = BOOST_REGEX_DETAIL_NS::get_default_error_string(static_cast< ::boost::regex_constants::error_type>(code)); + } + std::size_t len = p.size(); + if(len < buf_size) + { + BOOST_REGEX_DETAIL_NS::copy(p.c_str(), p.c_str() + p.size() + 1, buf); + } + return len + 1; + } + if(buf_size) + *buf = 0; + return 0; +} + +BOOST_REGEX_DECL int BOOST_REGEX_CCALL regexecW(const regex_tW* expression, const wchar_t* buf, regsize_t n, regmatch_t* array, int eflags) +{ +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4267) +#endif + bool result = false; + match_flag_type flags = match_default | expression->eflags; + const wchar_t* end; + const wchar_t* start; + wcmatch m; + + if(eflags & REG_NOTBOL) + flags |= match_not_bol; + if(eflags & REG_NOTEOL) + flags |= match_not_eol; + if(eflags & REG_STARTEND) + { + start = buf + array[0].rm_so; + end = buf + array[0].rm_eo; + } + else + { + start = buf; + end = buf + std::wcslen(buf); + } + +#ifndef BOOST_NO_EXCEPTIONS + try{ +#endif + if(expression->re_magic == wmagic_value) + { + result = regex_search(start, end, m, *static_cast(expression->guts), flags); + } + else + return result; +#ifndef BOOST_NO_EXCEPTIONS + } catch(...) + { + return REG_E_UNKNOWN; + } +#endif + if(result) + { + // extract what matched: + std::size_t i; + for(i = 0; (i < n) && (i < expression->re_nsub + 1); ++i) + { + array[i].rm_so = m[i].matched ? (m[i].first - buf) : -1; + array[i].rm_eo = m[i].matched ? (m[i].second - buf) : -1; + } + // and set anything else to -1: + for(i = expression->re_nsub + 1; i < n; ++i) + { + array[i].rm_so = -1; + array[i].rm_eo = -1; + } + return 0; + } + return REG_NOMATCH; +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +} + +BOOST_REGEX_DECL void BOOST_REGEX_CCALL regfreeW(regex_tW* expression) +{ + if(expression->re_magic == wmagic_value) + { + delete static_cast(expression->guts); + } + expression->re_magic = 0; +} + +} // namespace boost; + +#endif diff --git a/libs/regex/test/config_info/regex_config_info.cpp b/libs/regex/test/config_info/regex_config_info.cpp new file mode 100644 index 00000000..211e9ec0 --- /dev/null +++ b/libs/regex/test/config_info/regex_config_info.cpp @@ -0,0 +1,73 @@ +/* + * + * Copyright (c) 2003 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + +// +// This program extends config_info to print out regex library +// configuration information. We do this by redfining the main +// provided by config_info, our real main will call it later: +// +#ifndef OLD_MAIN +# define OLD_MAIN info_main +#endif + +#define main OLD_MAIN +#include +#undef main +#ifndef NEW_MAIN +# define NEW_MAIN main +#endif +#include + +int NEW_MAIN() +{ + OLD_MAIN(); + + print_separator(); + PRINT_MACRO(BOOST_REGEX_USER_CONFIG); + PRINT_MACRO(BOOST_REGEX_USE_C_LOCALE); + PRINT_MACRO(BOOST_REGEX_USE_CPP_LOCALE); + PRINT_MACRO(BOOST_REGEX_HAS_DLL_RUNTIME); + PRINT_MACRO(BOOST_REGEX_DYN_LINK); + PRINT_MACRO(BOOST_REGEX_NO_LIB); + PRINT_MACRO(BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE); + PRINT_MACRO(BOOST_REGEX_NO_W32); + PRINT_MACRO(BOOST_REGEX_NO_BOOL); + PRINT_MACRO(BOOST_REGEX_NO_EXTERNAL_TEMPLATES); + PRINT_MACRO(BOOST_REGEX_NO_FWD); + PRINT_MACRO(BOOST_REGEX_V3); + PRINT_MACRO(BOOST_REGEX_HAS_MS_STACK_GUARD); + PRINT_MACRO(BOOST_REGEX_RECURSIVE); + PRINT_MACRO(BOOST_REGEX_NON_RECURSIVE); + PRINT_MACRO(BOOST_REGEX_BLOCKSIZE); + PRINT_MACRO(BOOST_REGEX_MAX_BLOCKS); + PRINT_MACRO(BOOST_REGEX_MAX_CACHE_BLOCKS); + PRINT_MACRO(BOOST_NO_WREGEX); + PRINT_MACRO(BOOST_REGEX_NO_FILEITER); + PRINT_MACRO(BOOST_REGEX_STATIC_LINK); + PRINT_MACRO(BOOST_REGEX_DYN_LINK); + PRINT_MACRO(BOOST_REGEX_DECL); + PRINT_MACRO(BOOST_REGEX_CALL); + PRINT_MACRO(BOOST_REGEX_CCALL); + PRINT_MACRO(BOOST_REGEX_MAX_STATE_COUNT); + PRINT_MACRO(BOOST_REGEX_BUGGY_CTYPE_FACET); + PRINT_MACRO(BOOST_REGEX_MATCH_EXTRA); + PRINT_MACRO(BOOST_HAS_ICU); + PRINT_MACRO(BOOST_REGEX_HAS_OTHER_WCHAR_T); + +#if defined(BOOST_REGEX_CONFIG_INFO) && !defined(NO_RECURSE) + print_regex_library_info(); +#endif + + return 0; +} + + + diff --git a/libs/tuple/.gitattributes b/libs/tuple/.gitattributes new file mode 100644 index 00000000..3e84d7c7 --- /dev/null +++ b/libs/tuple/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain diff --git a/libs/tuple/.github/workflows/ci.yml b/libs/tuple/.github/workflows/ci.yml new file mode 100644 index 00000000..53c7f5d6 --- /dev/null +++ b/libs/tuple/.github/workflows/ci.yml @@ -0,0 +1,609 @@ +name: CI + +on: + pull_request: + push: + branches: + - master + - develop + - feature/** + +env: + UBSAN_OPTIONS: print_stacktrace=1 + +jobs: + posix: + strategy: + fail-fast: false + matrix: + include: + - toolset: gcc-4.8 + cxxstd: "03,11" + os: ubuntu-latest + container: ubuntu:18.04 + install: g++-4.8-multilib + address-model: 32,64 + - toolset: gcc-5 + cxxstd: "03,11,14,1z" + os: ubuntu-latest + container: ubuntu:18.04 + install: g++-5-multilib + address-model: 32,64 + - toolset: gcc-6 + cxxstd: "03,11,14,1z" + os: ubuntu-latest + container: ubuntu:18.04 + install: g++-6-multilib + address-model: 32,64 + - toolset: gcc-7 + cxxstd: "03,11,14,17" + os: ubuntu-20.04 + install: g++-7-multilib + address-model: 32,64 + - toolset: gcc-8 + cxxstd: "03,11,14,17,2a" + os: ubuntu-20.04 + install: g++-8-multilib + address-model: 32,64 + - toolset: gcc-9 + cxxstd: "03,11,14,17,2a" + os: ubuntu-20.04 + install: g++-9-multilib + address-model: 32,64 + - toolset: gcc-10 + cxxstd: "03,11,14,17,2a" + os: ubuntu-20.04 + install: g++-10-multilib + address-model: 32,64 + - toolset: gcc-11 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 + install: g++-11-multilib + address-model: 32,64 + - toolset: gcc-12 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 + install: g++-12-multilib + address-model: 32,64 + - toolset: gcc-13 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-latest + container: ubuntu:23.04 + install: g++-13-multilib + address-model: 32,64 + - toolset: clang + compiler: clang++-3.9 + cxxstd: "03,11,14" + os: ubuntu-latest + container: ubuntu:18.04 + install: clang-3.9 + - toolset: clang + compiler: clang++-4.0 + cxxstd: "03,11,14" + os: ubuntu-latest + container: ubuntu:18.04 + install: clang-4.0 + - toolset: clang + compiler: clang++-5.0 + cxxstd: "03,11,14,1z" + os: ubuntu-latest + container: ubuntu:18.04 + install: clang-5.0 + - toolset: clang + compiler: clang++-6.0 + cxxstd: "03,11,14,17" + os: ubuntu-20.04 + install: clang-6.0 + - toolset: clang + compiler: clang++-7 + cxxstd: "03,11,14,17" + os: ubuntu-20.04 + install: clang-7 + - toolset: clang + compiler: clang++-8 + cxxstd: "03,11,14,17" + os: ubuntu-20.04 + install: clang-8 + - toolset: clang + compiler: clang++-9 + cxxstd: "03,11,14,17" + os: ubuntu-20.04 + install: clang-9 + - toolset: clang + compiler: clang++-10 + cxxstd: "03,11,14,17,2a" + os: ubuntu-20.04 + - toolset: clang + compiler: clang++-11 + cxxstd: "03,11,14,17,2a" + os: ubuntu-20.04 + - toolset: clang + compiler: clang++-12 + cxxstd: "03,11,14,17,20" + os: ubuntu-20.04 + - toolset: clang + compiler: clang++-13 + cxxstd: "03,11,14,17,20" + os: ubuntu-22.04 + install: clang-13 + - toolset: clang + compiler: clang++-14 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 + install: clang-14 + - toolset: clang + compiler: clang++-15 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-22.04 + install: clang-15 + - toolset: clang + compiler: clang++-16 + cxxstd: "03,11,14,17,20,2b" + os: ubuntu-latest + container: ubuntu:23.04 + install: clang-16 + - toolset: clang + cxxstd: "03,11,14,17,2a" + os: macos-11 + - toolset: clang + cxxstd: "03,11,14,17,20,2b" + os: macos-12 + - toolset: clang + cxxstd: "03,11,14,17,20,2b" + os: macos-13 + + runs-on: ${{matrix.os}} + container: ${{matrix.container}} + + defaults: + run: + shell: bash + + steps: + - uses: actions/checkout@v3 + + - name: Setup container environment + if: matrix.container + run: | + apt-get update + apt-get -y install sudo python3 git g++ + + - name: Install packages + if: matrix.install + run: | + sudo apt-get update + sudo apt-get -y install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python3 tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + ./bootstrap.sh + ./b2 -d0 headers + + - name: Create user-config.jam + if: matrix.compiler + run: | + echo "using ${{matrix.toolset}} : : ${{matrix.compiler}} ;" > ~/user-config.jam + + - name: Run tests + run: | + cd ../boost-root + export ADDRMD=${{matrix.address-model}} + ./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} ${ADDRMD:+address-model=$ADDRMD} variant=debug,release + + windows: + strategy: + fail-fast: false + matrix: + include: + - toolset: msvc-14.0 + cxxstd: 14,latest + addrmd: 32,64 + os: windows-2019 + - toolset: msvc-14.2 + cxxstd: "14,17,20,latest" + addrmd: 32,64 + os: windows-2019 + - toolset: msvc-14.3 + cxxstd: "14,17,20,latest" + addrmd: 32,64 + os: windows-2022 + - toolset: clang-win + cxxstd: "14,17,latest" + addrmd: 32,64 + os: windows-2022 + - toolset: gcc + cxxstd: "03,11,14,17,2a" + addrmd: 64 + os: windows-2019 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Setup Boost + shell: cmd + run: | + echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% + for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi + echo LIBRARY: %LIBRARY% + echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% + echo GITHUB_BASE_REF: %GITHUB_BASE_REF% + echo GITHUB_REF: %GITHUB_REF% + if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% + set BOOST_BRANCH=develop + for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master + echo BOOST_BRANCH: %BOOST_BRANCH% + cd .. + git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + cmd /c bootstrap + b2 -d0 headers + + - name: Run tests + shell: cmd + run: | + cd ../boost-root + b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker + + posix-cmake-subdir: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: macos-11 + - os: macos-12 + - os: macos-13 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Install packages + if: matrix.install + run: sudo apt-get -y install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Use library with add_subdirectory + run: | + cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test + mkdir __build__ && cd __build__ + cmake .. + cmake --build . + ctest --output-on-failure --no-tests=error + + posix-cmake-install: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: macos-11 + - os: macos-12 + - os: macos-13 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Install packages + if: matrix.install + run: sudo apt-get -y install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local .. + + - name: Install + run: | + cd ../boost-root/__build__ + cmake --build . --target install + + - name: Use the installed library + run: | + cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__ + cmake -DCMAKE_INSTALL_PREFIX=~/.local .. + cmake --build . + ctest --output-on-failure --no-tests=error + + posix-cmake-test: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-20.04 + - os: ubuntu-22.04 + - os: macos-11 + - os: macos-12 + - os: macos-13 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Install packages + if: matrix.install + run: sudo apt-get -y install ${{matrix.install}} + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + cd .. + git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + + - name: Configure + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON .. + + - name: Build tests + run: | + cd ../boost-root/__build__ + cmake --build . --target tests + + - name: Run tests + run: | + cd ../boost-root/__build__ + ctest --output-on-failure --no-tests=error + + windows-cmake-subdir: + strategy: + fail-fast: false + matrix: + include: + - os: windows-2019 + - os: windows-2022 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Setup Boost + shell: cmd + run: | + echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% + for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi + echo LIBRARY: %LIBRARY% + echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% + echo GITHUB_BASE_REF: %GITHUB_BASE_REF% + echo GITHUB_REF: %GITHUB_REF% + if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% + set BOOST_BRANCH=develop + for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master + echo BOOST_BRANCH: %BOOST_BRANCH% + cd .. + git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + + - name: Use library with add_subdirectory (Debug) + shell: cmd + run: | + cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test + mkdir __build__ && cd __build__ + cmake .. + cmake --build . --config Debug + ctest --output-on-failure --no-tests=error -C Debug + + - name: Use library with add_subdirectory (Release) + shell: cmd + run: | + cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test/__build__ + cmake --build . --config Release + ctest --output-on-failure --no-tests=error -C Release + + windows-cmake-install: + strategy: + fail-fast: false + matrix: + include: + - os: windows-2019 + - os: windows-2022 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Setup Boost + shell: cmd + run: | + echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% + for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi + echo LIBRARY: %LIBRARY% + echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% + echo GITHUB_BASE_REF: %GITHUB_BASE_REF% + echo GITHUB_REF: %GITHUB_REF% + if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% + set BOOST_BRANCH=develop + for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master + echo BOOST_BRANCH: %BOOST_BRANCH% + cd .. + git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + + - name: Configure + shell: cmd + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix .. + + - name: Install (Debug) + shell: cmd + run: | + cd ../boost-root/__build__ + cmake --build . --target install --config Debug + + - name: Install (Release) + shell: cmd + run: | + cd ../boost-root/__build__ + cmake --build . --target install --config Release + + - name: Use the installed library (Debug) + shell: cmd + run: | + cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test && mkdir __build__ && cd __build__ + cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix .. + cmake --build . --config Debug + ctest --output-on-failure --no-tests=error -C Debug + + - name: Use the installed library (Release) + shell: cmd + run: | + cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test/__build__ + cmake --build . --config Release + ctest --output-on-failure --no-tests=error -C Release + + windows-cmake-test: + strategy: + fail-fast: false + matrix: + include: + - os: windows-2019 + - os: windows-2022 + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Setup Boost + shell: cmd + run: | + echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% + for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi + echo LIBRARY: %LIBRARY% + echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% + echo GITHUB_BASE_REF: %GITHUB_BASE_REF% + echo GITHUB_REF: %GITHUB_REF% + if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% + set BOOST_BRANCH=develop + for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master + echo BOOST_BRANCH: %BOOST_BRANCH% + cd .. + git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + cd boost-root + xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ + git submodule update --init tools/boostdep + python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% + + - name: Configure + shell: cmd + run: | + cd ../boost-root + mkdir __build__ && cd __build__ + cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DBUILD_TESTING=ON .. + + - name: Build tests (Debug) + shell: cmd + run: | + cd ../boost-root/__build__ + cmake --build . --target tests --config Debug + + - name: Run tests (Debug) + shell: cmd + run: | + cd ../boost-root/__build__ + ctest --output-on-failure --no-tests=error -C Debug + + - name: Build tests (Release) + shell: cmd + run: | + cd ../boost-root/__build__ + cmake --build . --target tests --config Release + + - name: Run tests (Release) + shell: cmd + run: | + cd ../boost-root/__build__ + ctest --output-on-failure --no-tests=error -C Release diff --git a/libs/tuple/.travis.yml b/libs/tuple/.travis.yml new file mode 100644 index 00000000..fd5e2f85 --- /dev/null +++ b/libs/tuple/.travis.yml @@ -0,0 +1,111 @@ +# Copyright 2016, 2017 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +language: cpp + +sudo: false + +python: "2.7" + +branches: + only: + - master + - develop + - /feature\/.*/ + +env: + matrix: + - BOGUS_JOB=true + +matrix: + + exclude: + - env: BOGUS_JOB=true + + include: + - os: linux + compiler: g++ + env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11 + + - os: linux + compiler: g++-5 + env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=03,11,14,1z + addons: + apt: + packages: + - g++-5 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-6 + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=03,11,14,1z + addons: + apt: + packages: + - g++-6 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: g++-7 + env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 + addons: + apt: + packages: + - g++-7 + sources: + - ubuntu-toolchain-r-test + + - os: linux + compiler: clang++ + env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11 + + - os: linux + compiler: clang++-4.0 + env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-4.0 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-4.0 + + - os: linux + compiler: clang++-5.0 + env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z + addons: + apt: + packages: + - clang-5.0 + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-trusty-5.0 + + - os: osx + compiler: clang++ + env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z + +install: + - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true + - cd .. + - git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root + - cd boost-root + - git submodule update --init tools/build + - git submodule update --init libs/config + - git submodule update --init tools/boostdep + - cp -r $TRAVIS_BUILD_DIR/* libs/tuple + - python tools/boostdep/depinst/depinst.py tuple + - ./bootstrap.sh + - ./b2 headers + +script: + - |- + echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam + - ./b2 -j 3 libs/tuple/test toolset=$TOOLSET cxxstd=$CXXSTD + +notifications: + email: + on_success: always diff --git a/libs/tuple/CMakeLists.txt b/libs/tuple/CMakeLists.txt new file mode 100644 index 00000000..3e4431bf --- /dev/null +++ b/libs/tuple/CMakeLists.txt @@ -0,0 +1,27 @@ +# Generated by `boostdep --cmake tuple` +# Copyright 2020, 2021 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.5...3.20) + +project(boost_tuple VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) + +add_library(boost_tuple INTERFACE) +add_library(Boost::tuple ALIAS boost_tuple) + +target_include_directories(boost_tuple INTERFACE include) + +target_link_libraries(boost_tuple + INTERFACE + Boost::config + Boost::core + Boost::static_assert + Boost::type_traits +) + +if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") + + add_subdirectory(test) + +endif() diff --git a/libs/tuple/doc/Jamfile.v2 b/libs/tuple/doc/Jamfile.v2 new file mode 100644 index 00000000..04b49ac3 --- /dev/null +++ b/libs/tuple/doc/Jamfile.v2 @@ -0,0 +1,37 @@ +# Copyright (c) 2001 Jaakko J�rvi + +# 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) + +project doc/tuple ; + +import boostbook ; +import quickbook ; + +xml tuple : tuple_users_guide.qbk ; + +boostbook standalone_tuple + : + tuple + : + boost.root=../../../.. + # File name of HTML output: + root.filename=tuple_users_guide + # How far down we chunk nested sections, basically all of them: + chunk.section.depth=0 + # Don't put the first section on the same page as the TOC: + chunk.first.sections=0 + # How far down sections get TOC's + toc.section.depth=1 + # Max depth in each TOC: + toc.max.depth=1 + # How far down we go with TOC's + generate.section.toc.level=0 + ; + +############################################################################### +alias boostdoc ; +explicit boostdoc ; +alias boostrelease : standalone_tuple ; +explicit boostrelease ; diff --git a/libs/tuple/doc/design_decisions_rationale.qbk b/libs/tuple/doc/design_decisions_rationale.qbk new file mode 100644 index 00000000..a8f4e6d9 --- /dev/null +++ b/libs/tuple/doc/design_decisions_rationale.qbk @@ -0,0 +1,190 @@ +[/ + / Copyright (c) 2001 Jaakko Järvi + / + / 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) + /] + +[article Design decisions rationale + [quickbook 1.6] + [id design_decisions_rationale] + [copyright 2001 Jaakko J\u00E4rvi] + [license Distributed under the + [@http://boost.org/LICENSE_1_0.txt Boost Software License, + Version 1.0]. + ] +] + +[template simplesect[title] +[block ''''''[title]'''''']] + +[template endsimplesect[] +[block '''''']] + +[section About namespaces] + +There was a discussion about whether tuples should be in a separate namespace +or directly in the `boost` namespace. The common principle is that domain +libraries (like /graph/, /python/) should be on a separate subnamespace, while +utility like libraries directly in the boost namespace. Tuples are somewhere +in between, as the tuple template is clearly a general utility, but the +library introduces quite a lot of names in addition to just the tuple template. +Tuples were originally under a subnamespace. As a result of the discussion, +tuple definitions were moved directly under the `boost` namespace. As a result +of a continued discussion, the subnamespace was reintroduced. The final (I +truly hope so) solution is now to have all definitions in namespace +`::boost::tuples`, and the most common names in the `::boost` namespace as well. +This is accomplished with using declarations (suggested by Dave Abrahams): + + namespace boost { + namespace tuples { + ... + // All library code + ... + } + using tuples::tuple; + using tuples::make_tuple; + using tuples::tie; + using tuples::get; + } + +With this arrangement, tuple creation with direct constructor calls, +`make_tuple` or `tie` functions do not need the namespace qualifier. Further, +all functions that manipulate tuples are found with Koenig-lookup. The only +exceptions are the `get` functions, which are always called with an +explicitly qualified template argument, and thus Koenig-lookup does not apply. +Therefore, `get` is lifted to `::boost` namespace with a using declaration. +Hence, the interface for an application programmer is in practice under the +namespace `::boost`. + +The other names, forming an interface for library writers (cons lists, +metafunctions manipulating cons lists, ...) remain in the subnamespace +`::boost::tuples`. Note, that the names `ignore`, `set_open`, `set_close` and +`set_delimiter` are considered to be part of the application programmer's +interface, but are still not under `boost` namespace. The reason being the +danger for name clashes for these common names. Further, the usage of these +features is probably not very frequent. + +[section For those who are really interested in namespaces] + +The subnamespace name /tuples/ raised some discussion. The rationale for not +using the most natural name 'tuple' is to avoid having an identical name with +the tuple template. Namespace names are, however, not generally in plural form +in Boost libraries. First, no real trouble was reported for using the same +name for a namespace and a class and we considered changing the name 'tuples' +to 'tuple'. But we found some trouble after all. Both gcc and edg compilers +reject using declarations where the namespace and class names are identical: + + namespace boost { + namespace tuple { + ... tie(...); + class tuple; + ... + } + using tuple::tie; // ok + using tuple::tuple; // error + ... + } + +Note, however, that a corresponding using declaration in the global namespace +seems to be ok: + + using boost::tuple::tuple; // ok; + +[endsect] + +[endsect] + +[section The end mark of the cons list (`nil`, `null_type`, ...)] + +Tuples are internally represented as cons lists: + + tuple + +inherits from + + cons > + +`null_type` is the end mark of the list. Original proposition was `nil`, but +the name is used in MacOS, and might have caused problems, so `null_type` was +chosen instead. Other names considered were /null_t/ and /unit/ (the empty +tuple type in SML). + +Note that `null_type` is the internal representation of an empty tuple: +`tuple<>` inherits from `null_type`. + +[endsect] + +[section Element indexing] + +Whether to use `0`- or `1`-based indexing was discussed more than thoroughly, +and the following observations were made: + +* `0`-based indexing is 'the C++ way' and used with arrays etc. + +* `1`-based 'name like' indexing exists as well, eg. `bind1st`, `bind2nd`, + `pair::first`, etc. + +Tuple access with the syntax `get(a)`, or `a.get()` (where `a` is a +tuple and `N` an index), was considered to be of the first category, hence, +the index of the first element in a tuple is `0`. + +A suggestion to provide `1`-based 'name like' indexing with constants like +`_1st`, `_2nd`, `_3rd`, ... was made. By suitably chosen constant types, this +would allow alternative syntaxes: + + a.get<0>() == a.get(_1st) == a[_1st] == a(_1st); + +We chose not to provide more than one indexing method for the following +reasons: + +* `0`-based indexing might not please everyone, but once its fixed, it is less + confusing than having two different methods (would anyone want such + constants for arrays?). + +* Adding the other indexing scheme doesn't really provide anything new (like a + new feature) to the user of the library. + +* C++ variable and constant naming rules don't give many possibilities for + defining short and nice index constants (like `_1st`, ...). Let the binding + and lambda libraries use these for a better purpose. + +* The access syntax a[_1st] (or a(_1st)) is appealing, and almost made us add + the index constants after all. However, `0`-based subscripting is so deep in + C++, that we had a fear for confusion. + +* Such constants are easy to add. + +[endsect] + +[section Tuple comparison] + +The comparison operator implements lexicographical order. Other orderings were +considered, mainly dominance /(a < b iff for each i a(i) < b(i))/. Our belief +is, that lexicographical ordering, though not mathematically the most natural +one, is the most frequently needed ordering in everyday programming. + +[endsect] + +[section Streaming] + +The characters specified with tuple stream manipulators are stored within the +space allocated by `ios_base::xalloc`, which allocates storage for `long` type +objects. `static_cast` is used in casting between `long` and the stream's +character type. Streams that have character types not convertible back and +forth to long thus fail to compile. + +This may be revisited at some point. The two possible solutions are: + +* Allow only plain `char` types as the tuple delimiters and use `widen` and + `narrow` to convert between the real character type of the stream. This + would always compile, but some calls to set manipulators might result in a + different character than expected (some default character). + +* Allocate enough space to hold the real character type of the stream. This + means memory for holding the delimiter characters must be allocated + separately, and that pointers to this memory are stored in the space + allocated with `ios_base::xalloc`. Any volunteers? + +[endsect] diff --git a/libs/tuple/doc/tuple_advanced_interface.qbk b/libs/tuple/doc/tuple_advanced_interface.qbk new file mode 100644 index 00000000..051e0ca7 --- /dev/null +++ b/libs/tuple/doc/tuple_advanced_interface.qbk @@ -0,0 +1,159 @@ +[/ + / Copyright (c) 2001 Jaakko Järvi + / + / 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) + /] + +[article Tuple library advanced features + [quickbook 1.6] + [id tuple_advanced_interface] + [copyright 2001 Jaakko J\u00E4rvi] + [license Distributed under the + [@http://boost.org/LICENSE_1_0.txt Boost Software License, + Version 1.0]. + ] +] + +[template simplesect[title] +[block ''''''[title]'''''']] + +[template endsimplesect[] +[block '''''']] + +The advanced features described in this document are all under namespace +`::boost::tuples` + +[section Metafunctions for tuple types] + +Suppose `T` is a tuple type, and `N` is a constant integral expression. + + element::type + +gives the type of the `N`-th element in the tuple type `T`. If `T` is `const`, +the resulting type is `const` qualified as well. Note that the constness of `T` +does not affect reference type elements. + + length::value + +gives the length of the tuple type `T`. + +[endsect] + +[section Cons lists] + +Tuples are internally represented as /cons lists/. For example, the tuple + + tuple + +inherits from the type + + cons > > > + +The tuple template provides the typedef inherited to access the cons list +representation. E.g.: `tuple::inherited` is the type `cons`. + +[section Empty tuple] + +The internal representation of the empty tuple `tuple<>` is `null_type`. + +[endsect] + +[section Head and tail] + +Both tuple template and the cons templates provide the typedefs `head_type` +and `tail_type`. The `head_type` typedef gives the type of the first element +of the tuple (or the cons list). The `tail_type` typedef gives the remaining +cons list after removing the first element. The head element is stored in the +member variable `head` and the tail list in the member variable `tail`. Cons +lists provide the member function `get_head()` for getting a reference to the +head of a cons list, and `get_tail()` for getting a reference to the tail. +There are const and non-const versions of both functions. + +Note that in a one element tuple, `tail_type` equals `null_type` and the +`get_tail()` function returns an object of type `null_type`. + +The empty tuple (`null_type`) has no head or tail, hence the `get_head` and +`get_tail` functions are not provided. + +Treating tuples as cons lists gives a convenient means to define generic +functions to manipulate tuples. For example, the following pair of function +templates assign `0` to each element of a tuple (obviously, the assignments +must be valid operations for the element types): + + inline void set_to_zero(const null_type&) {}; + + template + inline void set_to_zero(cons& x) { x.get_head() = 0; set_to_zero(x.get_tail()); } + +[endsect] + +[section Constructing cons lists] + +A cons list can be default constructed provided that all its elements can be +default constructed. + +A cons list can be constructed from its head and tail. The prototype of the +constructor is: + + cons(typename access_traits::parameter_type h, const tail_type& t) + +The traits template for the head parameter selects correct parameter types for +different kinds of element types (for reference elements the parameter type +equals the element type, for non-reference types the parameter type is a +reference to const non-volatile element type). + +For a one-element cons list the tail argument (`null_type`) can be omitted. + +[endsect] + +[endsect] + +[section Traits classes for tuple element types] + +[section access_traits] + +The template `access_traits` defines three type functions. Let `T` be a type +of an element in a tuple: + +* `access_traits::non_const_type` maps `T` to the return type of the no + n-const access functions (nonmember and member `get` functions, and the + `get_head` function). + +* `access_traits::const_type` maps `T` to the return type of the const + access functions. + +* `access_traits::parameter_type` maps `T` to the parameter type of the + tuple constructor. + +[endsect] + +[section make_tuple_traits] + +The element types of the tuples that are created with the `make_tuple` +functions are computed with the type function `make_tuple_traits`. The type +function call `make_tuple_traits::type` implements the following type +mapping: + +* /any reference type/ -> /compile time error/ + +* /any array type/ -> /constant reference to the array type/ + +* `reference_wrapper` -> `T&` + +* `T` -> `T` + +Objects of type `reference_wrapper` are created with the `ref` and `cref` +functions (see [link tuple.constructing_tuples.make_tuple The `make_tuple` +function]). + +Reference wrappers were originally part of the tuple library, but they are now +a general utility of boost. The `reference_wrapper` template and the `ref` and +`cref` functions are defined in a separate file +[@boost:/libs/core/doc/html/core/ref.html `ref.hpp`] in the main boost include +directory; and directly in the `boost` namespace. + +[endsect] + +[endsect] diff --git a/libs/tuple/doc/tuple_users_guide.qbk b/libs/tuple/doc/tuple_users_guide.qbk new file mode 100644 index 00000000..43d03e65 --- /dev/null +++ b/libs/tuple/doc/tuple_users_guide.qbk @@ -0,0 +1,525 @@ +[/ + / Copyright (c) 2001 Jaakko Järvi + / + / 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) + /] + +[library Boost.Tuple + [quickbook 1.6] + [id tuple] + [copyright 2001 Jaakko J\u00E4rvi] + [dirname tuple] + [license Distributed under the + [@http://boost.org/LICENSE_1_0.txt Boost Software License, + Version 1.0]. + ] +] + +[include tuple_advanced_interface.qbk] +[include design_decisions_rationale.qbk] + +[template simplesect[title] +[block ''''''[title]'''''']] + +[template endsimplesect[] +[block '''''']] + +A tuple (or n-tuple) is a fixed size collection of elements. Pairs, triples, +quadruples etc. are tuples. In a programming language, a tuple is a data +object containing other objects as elements. These element objects may be of +different types. + +Tuples are convenient in many circumstances. For instance, tuples make it easy +to define functions that return more than one value. + +Some programming languages, such as ML, Python and Haskell, have built-in +tuple constructs. Unfortunately C++ does not. To compensate for this +"deficiency", the Boost Tuple Library implements a tuple construct using +templates. + +[section:using_library Using the Library] + +To use the library, just include: + + #include "boost/tuple/tuple.hpp" + +Comparison operators can be included with: + + #include "boost/tuple/tuple_comparison.hpp" + +To use tuple input and output operators, + + #include "boost/tuple/tuple_io.hpp" + +Both `tuple_io.hpp` and `tuple_comparison.hpp` include `tuple.hpp`. + +All definitions are in namespace `::boost::tuples`, but the most common names +are lifted to namespace `::boost` with using declarations. These names are: +`tuple`, `make_tuple`, `tie` and `get`. Further, `ref` and `cref` are defined +directly under the `::boost` namespace. + +[endsect] + +[section:tuple_types Tuple Types] + +A tuple type is an instantiation of the `tuple` template. The template +parameters specify the types of the tuple elements. The current version +supports tuples with 0-10 elements. If necessary, the upper limit can be +increased up to, say, a few dozen elements. The data element can be any C++ +type. Note that `void` and plain function types are valid C++ types, but +objects of such types cannot exist. Hence, if a tuple type contains such types +as elements, the tuple type can exist, but not an object of that type. There +are natural limitations for element types that cannot be copied, or that are +not default constructible (see [link tuple.constructing_tuples 'Constructing tuples'] +below). + +For example, the following definitions are valid tuple instantiations (`A`, +`B` and `C` are some user defined classes): + + tuple + tuple + tuple + tuple > + tuple, bool, void*> + +[endsect] + +[section:constructing_tuples Constructing Tuples] + +The tuple constructor takes the tuple elements as arguments. For an /n/- +element tuple, the constructor can be invoked with /k/ arguments, where +`0` <= /k/ <= /n/. For example: + + tuple() + tuple(1) + tuple(1, 3.14) + +If no initial value for an element is provided, it is default initialized +(and hence must be default initializable). For example: + + class X { + X(); + public: + X(std::string); + }; + + tuple() // error: no default constructor for X + tuple(string("Jaba"), string("Daba"), string("Duu")) // ok + +In particular, reference types do not have a default initialization: + + tuple() // error: reference must be + // initialized explicitly + + double d = 5; + tuple(d) // ok + + tuple(d+3.14) // error: cannot initialize + // non-const reference with a temporary + + tuple(d+3.14) // ok, but dangerous: + // the element becomes a dangling reference + +Using an initial value for an element that cannot be copied, is a compile time +error: + + class Y { + Y(const Y&); + public: + Y(); + }; + + char a[10]; + + tuple(a, Y()); // error, neither arrays nor Y can be copied + tuple(); // ok + +Note particularly that the following is perfectly ok: + + Y y; + tuple(a, y); + +It is possible to come up with a tuple type that cannot be constructed. This +occurs if an element that cannot be initialized has a lower index than an +element that requires initialization. For example: `tuple`. + +In sum, the tuple construction is semantically just a group of individual +elementary constructions. + +[section:make_tuple The `make_tuple` function] + +Tuples can also be constructed using the `make_tuple` (cf. `std::make_pair`) +helper functions. This makes the construction more convenient, saving the +programmer from explicitly specifying the element types: + + tuple add_multiply_divide(int a, int b) { + return make_tuple(a+b, a*b, double(a)/double(b)); + } + +By default, the element types are deduced to the plain non-reference types. +E.g.: + + void foo(const A& a, B& b) { + ... + make_tuple(a, b); + +The `make_tuple` invocation results in a tuple of type `tuple`. + +Sometimes the plain non-reference type is not desired, e.g. if the element +type cannot be copied. Therefore, the programmer can control the type +deduction and state that a reference to const or reference to non-const type +should be used as the element type instead. This is accomplished with two +helper template functions: [@boost:/libs/core/doc/html/core/ref.html `boost::ref`] +and [@boost:/libs/core/doc/html/core/ref.html `boost::cref`]. Any argument can +be wrapped with these functions to get the desired type. The mechanism does +not compromise const correctness since a const object wrapped with ref results +in a tuple element with const reference type (see the fifth example below). +For example: + + A a; B b; const A ca = a; + make_tuple(cref(a), b); // creates tuple + make_tuple(ref(a), b); // creates tuple + make_tuple(ref(a), cref(b)); // creates tuple + make_tuple(cref(ca)); // creates tuple + make_tuple(ref(ca)); // creates tuple + +Array arguments to `make_tuple` functions are deduced to reference to const +types by default; there is no need to wrap them with `cref`. For example: + + make_tuple("Donald", "Daisy"); + +This creates an object of type `tuple` +(note that the type of a string literal is an array of const characters, not +`const char*`). However, to get `make_tuple` to create a tuple with an element +of a non-const array type one must use the `ref` wrapper. + +Function pointers are deduced to the plain non-reference type, that is, to +plain function pointer. A tuple can also hold a reference to a function, but +such a tuple cannot be constructed with `make_tuple` (a const qualified +function type would result, which is illegal): + + void f(int i); + ... + make_tuple(&f); // tuple + ... + tuple > a(f) // ok + make_tuple(f); // not ok + +[endsect] + +[endsect] + +[section:accessing_elements Accessing Tuple Elements] + +Tuple elements are accessed with the expression: + + t.get() + +or + + get(t) + +where `t` is a tuple object and `N` is a constant integral expression +specifying the index of the element to be accessed. Depending on whether `t` +is const or not, `get` returns the `N`-th element as a reference to const or +non-const type. The index of the first element is `0` and thus `N` must be +between `0` and /k/`-1`, where /k/ is the number of elements in the tuple. +Violations of these constraints are detected at compile time. Examples: + + double d = 2.7; A a; + tuple t(1, d, a); + const tuple ct = t; + ... + int i = get<0>(t); i = t.get<0>(); // ok + int j = get<0>(ct); // ok + get<0>(t) = 5; // ok + get<0>(ct) = 5; // error, can't assign to const + ... + double e = get<1>(t); // ok + get<1>(t) = 3.14; // ok + get<2>(t) = A(); // error, can't assign to const + A aa = get<3>(t); // error: index out of bounds + ... + ++get<0>(t); // ok, can be used as any variable + +/[Note:/ The member `get` functions are not supported with MS Visual C++ +compiler. Further, the compiler has trouble with finding the non-member `get` +functions without an explicit namespace qualifier. Hence, all `get` calls +should be qualified as `tuples::get(a_tuple)` when writing code that should +compile with MSVC++ 6.0./]/ + +[endsect] + +[section:construction_and_assignment Copy Construction and Tuple Assignment] + +A tuple can be copy constructed from another tuple, provided that the element +types are element-wise copy constructible. Analogously, a tuple can be +assigned to another tuple, provided that the element types are element-wise +assignable. For example: + + class A {}; + class B : public A {}; + struct C { C(); C(const B&); }; + struct D { operator C() const; }; + tuple t; + ... + tuple a(t); // ok + a = t; // ok + +In both cases, the conversions performed are: + +* `char -> int`, +* `B* -> A*` (derived class pointer to base class pointer), +* `B -> C` (a user defined conversion), and +* `D -> C` (a user defined conversion). + +Note that assignment is also defined from `std::pair` types: + + tuple a = std::make_pair(1, 'a'); + +[endsect] + +[section:relational_operators Relational Operators] + +Tuples reduce the operators `==`, `!=`, `<`, `>`, `<=` and `>=` to the +corresponding elementary operators. This means, that if any of these operators +is defined between all elements of two tuples, then the same operator is +defined between the tuples as well. The equality operators for two tuples `a` +and `b` are defined as: + +* `a == b` iff for each `i`: `a`'''i'''` == b`'''i''' +* `a != b` iff exists `i`: `a`'''i'''` != b`'''i''' + +The operators `<`, `>`, `<=` and `>=` implement a lexicographical ordering. + +Note that an attempt to compare two tuples of different lengths results in a +compile time error. Also, the comparison operators are /"short-circuited"/: +elementary comparisons start from the first elements and are performed only +until the result is clear. + +Examples: + + tuple t1(std::string("same?"), 2, A()); + tuple t2(std::string("same?"), 2, A()); + tuple t3(std::string("different"), 3, A()); + + bool operator==(A, A) { std::cout << "All the same to me..."; return true; } + + t1 == t2; // true + t1 == t3; // false, does not print "All the..." + +[endsect] + +[section:tiers Tiers] + +/Tiers/ are tuples, where all elements are of non-const reference types. They +are constructed with a call to the `tie` function template (cf. `make_tuple`): + + int i; char c; double d; + ... + tie(i, c, a); + +The above `tie` function creates a tuple of type `tuple`. +The same result could be achieved with the call `make_tuple(ref(i), ref(c), ref(a))`. + +A tuple that contains non-const references as elements can be used to 'unpack' +another tuple into variables. E.g.: + + int i; char c; double d; + tie(i, c, d) = make_tuple(1,'a', 5.5); + std::cout << i << " " << c << " " << d; + +This code prints `1 a 5.5` to the standard output stream. A tuple unpacking +operation like this is found for example in ML and Python. It is convenient +when calling functions which return tuples. + +The tying mechanism works with `std::pair` templates as well: + + int i; char c; + tie(i, c) = std::make_pair(1, 'a'); + +[section Ignore] + +There is also an object called `ignore` which allows you to ignore an element +assigned by a tuple. The idea is that a function may return a tuple, only part +of which you are interested in. For example (note, that ignore is under the +`tuples` subnamespace): + + char c; + tie(tuples::ignore, c) = std::make_pair(1, 'a'); + +[endsect] + +[endsect] + +[section:streaming Streaming] + +The global `operator<<` has been overloaded for `std::ostream` such that +tuples are output by recursively calling `operator<<` for each element. + +Analogously, the global `operator>>` has been overloaded to extract tuples +from `std::istream` by recursively calling `operator>>` for each element. + +The default delimiter between the elements is space, and the tuple is enclosed +in parenthesis. For Example: + + tuple a(1.0f, 2, std::string("Howdy folks!"); + + cout << a; + +outputs the tuple as: `(1.0 2 Howdy folks!)` + +The library defines three manipulators for changing the default behavior: + +* `set_open(char)` defines the character that is output before the first element. +* `set_close(char)` defines the character that is output after the last element. +* `set_delimiter(char)` defines the delimiter character between elements. + +Note, that these manipulators are defined in the tuples subnamespace. For +example: + + cout << tuples::set_open('[') << tuples::set_close(']') << tuples::set_delimiter(',') << a; + +outputs the same tuple `a` as: `[1.0,2,Howdy folks!]` + +The same manipulators work with `operator>>` and `istream` as well. Suppose +the `cin` stream contains the following data: + + (1 2 3) [4:5] + +The code: + + tuple i; + tuple j; + + cin >> i; + cin >> tuples::set_open('[') >> tuples::set_close(']') >> tuples::set_delimiter(':'); + cin >> j; + +reads the data into the tuples `i` and `j`. + +Note that extracting tuples with `std::string` or C-style string elements does +not generally work, since the streamed tuple representation may not be +unambiguously parseable. + +[endsect] + +[section:performance Performance] + +All tuple access and construction functions are small inlined one-liners. +Therefore, a decent compiler can eliminate any extra cost of using tuples +compared to using hand-written tuple like classes. Particularly, with a decent +compiler there is no performance difference between this code: + + class hand_made_tuple { + A a; B b; C c; + public: + hand_made_tuple(const A& aa, const B& bb, const C& cc) + : a(aa), b(bb), c(cc) {}; + A& getA() { return a; }; + B& getB() { return b; }; + C& getC() { return c; }; + }; + + hand_made_tuple hmt(A(), B(), C()); + hmt.getA(); hmt.getB(); hmt.getC(); + +and this code: + + tuple t(A(), B(), C()); + t.get<0>(); t.get<1>(); t.get<2>(); + +Note, that there are widely used compilers (e.g. bcc 5.5.1) which fail to +optimize this kind of tuple usage. + +Depending on the optimizing ability of the compiler, the tier mechanism may +have a small performance penalty compared to using non-const reference +parameters as a mechanism for returning multiple values from a function. For +example, suppose that the following functions `f1` and `f2` have equivalent +functionalities: + + void f1(int&, double&); + tuple f2(); + +Then, the call #1 may be slightly faster than #2 in the code below: + + int i; double d; + ... + f1(i,d); // #1 + tie(i,d) = f2(); // #2 + +See [[link publ_1 1], [link publ_2 2]] for more in-depth discussions about +efficiency. + +[section Effect on Compile Time] + +Compiling tuples can be slow due to the excessive amount of template +instantiations. Depending on the compiler and the tuple length, it may be more +than 10 times slower to compile a tuple construct, compared to compiling an +equivalent explicitly written class, such as the `hand_made_tuple` class above. +However, as a realistic program is likely to contain a lot of code in addition +to tuple definitions, the difference is probably unnoticeable. Compile time +increases between 5 and 10 percent were measured for programs which used tuples +very frequently. With the same test programs, memory consumption of compiling +increased between 22% to 27%. See [[link publ_1 1], [link publ_2 2]] for +details. + +[endsect] + +[endsect] + +[section:portability Portability] + +The library code is(?) standard C++ and thus the library works with a standard +conforming compiler. Below is a list of compilers and known problems with each +compiler: + +[table + [[Compiler] [Problems]] + [[gcc 2.95] [-]] + [[edg 2.44] [-]] + [[Borland 5.5] [Can't use function pointers or member pointers as + tuple elements]] + [[Metrowerks 6.2] [Can't use `ref` and `cref` wrappers]] + [[MS Visual C++] [No reference elements (`tie` still works). Can't use + `ref` and `cref` wrappers]] +] + +[endsect] + +[section:more_details More Details] + +[link tuple_advanced_interface Advanced features] (describes some metafunctions etc.). + +[link design_decisions_rationale Rationale behind some design/implementation decisions]. + +[endsect] + +[section:thanks Acknowledgements] + +Gary Powell has been an indispensable helping hand. In particular, stream +manipulators for tuples were his idea. Doug Gregor came up with a working +version for MSVC, David Abrahams found a way to get rid of most of the +restrictions for compilers not supporting partial specialization. Thanks to +Jeremy Siek, William Kempf and Jens Maurer for their help and suggestions. The +comments by Vesa Karvonen, John Max Skaller, Ed Brey, Beman Dawes, David +Abrahams and Hartmut Kaiser helped to improve the library. The idea for the +`tie` mechanism came from an old usenet article by Ian McCulloch, where he +proposed something similar for `std::pair`s. + +[endsect] + +[section:references References] + +[#publ_1] +[1] J\u00E4rvi J.: /Tuples and multiple return values in C++/, TUCS Technical Report No 249, 1999. + +[#publ_2] +[2] J\u00E4rvi J.: /ML-Style Tuple Assignment in Standard C++ - Extending the Multiple Return Value Formalism/, TUCS Technical Report No 267, 1999. + +[#publ_3] +[3] J\u00E4rvi J.: /Tuple Types and Multiple Return Values/, C/C++ Users Journal, August 2001. + +[endsect] diff --git a/libs/tuple/include/boost/tuple/detail/tuple_basic.hpp b/libs/tuple/include/boost/tuple/detail/tuple_basic.hpp new file mode 100644 index 00000000..ad488be7 --- /dev/null +++ b/libs/tuple/include/boost/tuple/detail/tuple_basic.hpp @@ -0,0 +1,992 @@ +// tuple_basic.hpp ----------------------------------------------------- + +// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// +// 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) + +// For more information, see http://www.boost.org + +// Outside help: +// This and that, Gary Powell. +// Fixed return types for get_head/get_tail +// ( and other bugs ) per suggestion of Jens Maurer +// simplified element type accessors + bug fix (Jeremy Siek) +// Several changes/additions according to suggestions by Douglas Gregor, +// William Kempf, Vesa Karvonen, John Max Skaller, Ed Brey, Beman Dawes, +// David Abrahams. + +// Revision history: +// 2002 05 01 Hugo Duncan: Fix for Borland after Jaakko's previous changes +// 2002 04 18 Jaakko: tuple element types can be void or plain function +// types, as long as no object is created. +// Tuple objects can no hold even noncopyable types +// such as arrays. +// 2001 10 22 John Maddock +// Fixes for Borland C++ +// 2001 08 30 David Abrahams +// Added default constructor for cons<>. +// ----------------------------------------------------------------- + +#ifndef BOOST_TUPLE_BASIC_HPP +#define BOOST_TUPLE_BASIC_HPP + + +#include // needed for the assignment from pair to tuple +#include // for std::size_t + +#include +#include +#include +#include + +#include // needed for BOOST_WORKAROUND + +#if defined(BOOST_GCC) && (BOOST_GCC >= 40700) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#endif + +namespace boost { +namespace tuples { + +// -- null_type -------------------------------------------------------- +struct null_type {}; + +// a helper function to provide a const null_type type temporary +namespace detail { + inline const null_type cnull() { return null_type(); } + + +// -- if construct ------------------------------------------------ +// Proposed by Krzysztof Czarnecki and Ulrich Eisenecker + +template struct IF { typedef Then RET; }; + +template struct IF { + typedef Else RET; +}; + +} // end detail + +// - cons forward declaration ----------------------------------------------- +template struct cons; + + +// - tuple forward declaration ----------------------------------------------- +template < + class T0 = null_type, class T1 = null_type, class T2 = null_type, + class T3 = null_type, class T4 = null_type, class T5 = null_type, + class T6 = null_type, class T7 = null_type, class T8 = null_type, + class T9 = null_type> +class tuple; + +// tuple_length forward declaration +template struct length; + + + +namespace detail { + +// -- generate error template, referencing to non-existing members of this +// template is used to produce compilation errors intentionally +template +class generate_error; + +template +struct drop_front { + template + struct apply { + typedef BOOST_DEDUCED_TYPENAME drop_front::BOOST_NESTED_TEMPLATE + apply next; + typedef BOOST_DEDUCED_TYPENAME next::type::tail_type type; + static const type& call(const Tuple& tup) { + return next::call(tup).tail; + } + }; +}; + +template<> +struct drop_front<0> { + template + struct apply { + typedef Tuple type; + static const type& call(const Tuple& tup) { + return tup; + } + }; +}; + +} // end of namespace detail + + +// -cons type accessors ---------------------------------------- +// typename tuples::element::type gets the type of the +// Nth element ot T, first element is at index 0 +// ------------------------------------------------------- + +#ifndef BOOST_NO_CV_SPECIALIZATIONS + +template +struct element +{ + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply::type::head_type type; +}; + +template +struct element +{ +private: + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply::type::head_type unqualified_type; +public: +#if BOOST_WORKAROUND(BOOST_BORLANDC,<0x600) + typedef const unqualified_type type; +#else + typedef BOOST_DEDUCED_TYPENAME boost::add_const::type type; +#endif +}; +#else // def BOOST_NO_CV_SPECIALIZATIONS + +namespace detail { + +template +struct element_impl +{ + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply::type::head_type type; +}; + +template +struct element_impl +{ + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply::type::head_type unqualified_type; + typedef const unqualified_type type; +}; + +} // end of namespace detail + + +template +struct element: + public detail::element_impl::value> +{ +}; + +#endif + + +// -get function templates ----------------------------------------------- +// Usage: get(aTuple) + +// -- some traits classes for get functions + +// access traits lifted from detail namespace to be part of the interface, +// (Joel de Guzman's suggestion). Rationale: get functions are part of the +// interface, so should the way to express their return types be. + +template struct access_traits { + typedef const T& const_type; + typedef T& non_const_type; + + typedef const typename boost::remove_cv::type& parameter_type; + +// used as the tuple constructors parameter types +// Rationale: non-reference tuple element types can be cv-qualified. +// It should be possible to initialize such types with temporaries, +// and when binding temporaries to references, the reference must +// be non-volatile and const. 8.5.3. (5) +}; + +template struct access_traits { + + typedef T& const_type; + typedef T& non_const_type; + + typedef T& parameter_type; +}; + +// get function for non-const cons-lists, returns a reference to the element + +template +inline typename access_traits< + typename element >::type + >::non_const_type +get(cons& c) { + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply > impl; + typedef BOOST_DEDUCED_TYPENAME impl::type cons_element; + return const_cast(impl::call(c)).head; +} + +// get function for const cons-lists, returns a const reference to +// the element. If the element is a reference, returns the reference +// as such (that is, can return a non-const reference) +template +inline typename access_traits< + typename element >::type + >::const_type +get(const cons& c) { + typedef BOOST_DEDUCED_TYPENAME detail::drop_front::BOOST_NESTED_TEMPLATE + apply > impl; + return impl::call(c).head; +} + +// -- the cons template -------------------------------------------------- +namespace detail { + +// These helper templates wrap void types and plain function types. +// The reationale is to allow one to write tuple types with those types +// as elements, even though it is not possible to instantiate such object. +// E.g: typedef tuple some_type; // ok +// but: some_type x; // fails + +template class non_storeable_type { + non_storeable_type(); +}; + +template struct wrap_non_storeable_type { + typedef typename IF< + ::boost::is_function::value, non_storeable_type, T + >::RET type; +}; +template <> struct wrap_non_storeable_type { + typedef non_storeable_type type; +}; + +} // detail + +template +struct cons { + + typedef HT head_type; + typedef TT tail_type; + + typedef typename + detail::wrap_non_storeable_type::type stored_head_type; + + stored_head_type head; + tail_type tail; + + typename access_traits::non_const_type + get_head() { return head; } + + typename access_traits::non_const_type + get_tail() { return tail; } + + typename access_traits::const_type + get_head() const { return head; } + + typename access_traits::const_type + get_tail() const { return tail; } + + cons() : head(), tail() {} + // cons() : head(detail::default_arg::f()), tail() {} + + // the argument for head is not strictly needed, but it prevents + // array type elements. This is good, since array type elements + // cannot be supported properly in any case (no assignment, + // copy works only if the tails are exactly the same type, ...) + + cons(typename access_traits::parameter_type h, + const tail_type& t) + : head (h), tail(t) {} + + template + cons( T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, + T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 ) + : head (t1), + tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull()) + {} + + template + cons( const null_type& /*t1*/, T2& t2, T3& t3, T4& t4, T5& t5, + T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 ) + : head (), + tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull()) + {} + + cons( const cons& u ) : head(u.head), tail(u.tail) {} + + template + cons( const cons& u ) : head(u.head), tail(u.tail) {} + + template + cons& operator=( const cons& u ) { + head=u.head; tail=u.tail; return *this; + } + + // must define assignment operator explicitly, implicit version is + // illformed if HT is a reference (12.8. (12)) + cons& operator=(const cons& u) { + head = u.head; tail = u.tail; return *this; + } + + template + cons& operator=( const std::pair& u ) { + BOOST_STATIC_ASSERT(length::value == 2); // check length = 2 + head = u.first; tail.head = u.second; return *this; + } + + // get member functions (non-const and const) + template + typename access_traits< + typename element >::type + >::non_const_type + get() { + return boost::tuples::get(*this); // delegate to non-member get + } + + template + typename access_traits< + typename element >::type + >::const_type + get() const { + return boost::tuples::get(*this); // delegate to non-member get + } +}; + +template +struct cons { + + typedef HT head_type; + typedef null_type tail_type; + typedef cons self_type; + + typedef typename + detail::wrap_non_storeable_type::type stored_head_type; + stored_head_type head; + + typename access_traits::non_const_type + get_head() { return head; } + + null_type get_tail() { return null_type(); } + + typename access_traits::const_type + get_head() const { return head; } + + const null_type get_tail() const { return null_type(); } + + // cons() : head(detail::default_arg::f()) {} + cons() : head() {} + + cons(typename access_traits::parameter_type h, + const null_type& = null_type()) + : head (h) {} + + template + cons(T1& t1, const null_type&, const null_type&, const null_type&, + const null_type&, const null_type&, const null_type&, + const null_type&, const null_type&, const null_type&) + : head (t1) {} + + cons(const null_type&, + const null_type&, const null_type&, const null_type&, + const null_type&, const null_type&, const null_type&, + const null_type&, const null_type&, const null_type&) + : head () {} + + cons( const cons& u ) : head(u.head) {} + + template + cons( const cons& u ) : head(u.head) {} + + template + cons& operator=(const cons& u ) + { head = u.head; return *this; } + + // must define assignment operator explicitely, implicit version + // is illformed if HT is a reference + cons& operator=(const cons& u) { head = u.head; return *this; } + + template + typename access_traits< + typename element::type + >::non_const_type + get() { + return boost::tuples::get(*this); + } + + template + typename access_traits< + typename element::type + >::const_type + get() const { + return boost::tuples::get(*this); + } + +}; + +// templates for finding out the length of the tuple ------------------- + +template +struct length: boost::integral_constant::value> +{ +}; + +template<> +struct length >: boost::integral_constant +{ +}; + +template<> +struct length const>: boost::integral_constant +{ +}; + +template<> +struct length: boost::integral_constant +{ +}; + +template<> +struct length: boost::integral_constant +{ +}; + +namespace detail { + +// Tuple to cons mapper -------------------------------------------------- +template +struct map_tuple_to_cons +{ + typedef cons::type + > type; +}; + +// The empty tuple is a null_type +template <> +struct map_tuple_to_cons +{ + typedef null_type type; +}; + +} // end detail + +// ------------------------------------------------------------------- +// -- tuple ------------------------------------------------------ +template + +class tuple : + public detail::map_tuple_to_cons::type +{ +public: + typedef typename + detail::map_tuple_to_cons::type inherited; + typedef typename inherited::head_type head_type; + typedef typename inherited::tail_type tail_type; + + +// access_traits::parameter_type takes non-reference types as const T& + tuple() {} + + explicit tuple(typename access_traits::parameter_type t0) + : inherited(t0, detail::cnull(), detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1) + : inherited(t0, t1, detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2) + : inherited(t0, t1, t2, detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3) + : inherited(t0, t1, t2, t3, detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull(), + detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3, + typename access_traits::parameter_type t4) + : inherited(t0, t1, t2, t3, t4, detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull(), detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3, + typename access_traits::parameter_type t4, + typename access_traits::parameter_type t5) + : inherited(t0, t1, t2, t3, t4, t5, detail::cnull(), detail::cnull(), + detail::cnull(), detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3, + typename access_traits::parameter_type t4, + typename access_traits::parameter_type t5, + typename access_traits::parameter_type t6) + : inherited(t0, t1, t2, t3, t4, t5, t6, detail::cnull(), + detail::cnull(), detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3, + typename access_traits::parameter_type t4, + typename access_traits::parameter_type t5, + typename access_traits::parameter_type t6, + typename access_traits::parameter_type t7) + : inherited(t0, t1, t2, t3, t4, t5, t6, t7, detail::cnull(), + detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3, + typename access_traits::parameter_type t4, + typename access_traits::parameter_type t5, + typename access_traits::parameter_type t6, + typename access_traits::parameter_type t7, + typename access_traits::parameter_type t8) + : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, detail::cnull()) {} + + tuple(typename access_traits::parameter_type t0, + typename access_traits::parameter_type t1, + typename access_traits::parameter_type t2, + typename access_traits::parameter_type t3, + typename access_traits::parameter_type t4, + typename access_traits::parameter_type t5, + typename access_traits::parameter_type t6, + typename access_traits::parameter_type t7, + typename access_traits::parameter_type t8, + typename access_traits::parameter_type t9) + : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) {} + + + template + tuple(const cons& p) : inherited(p) {} + + template + tuple& operator=(const cons& k) { + inherited::operator=(k); + return *this; + } + + template + tuple& operator=(const std::pair& k) { + BOOST_STATIC_ASSERT(length::value == 2);// check_length = 2 + this->head = k.first; + this->tail.head = k.second; + return *this; + } + +}; + +// The empty tuple +template <> +class tuple : + public null_type +{ +public: + typedef null_type inherited; +}; + + +// Swallows any assignment (by Doug Gregor) +namespace detail { + +struct swallow_assign; +typedef void (detail::swallow_assign::*ignore_t)(); +struct swallow_assign { + swallow_assign(ignore_t(*)(ignore_t)) {} + template + swallow_assign const& operator=(const T&) const { + return *this; + } +}; + + +} // namespace detail + +// "ignore" allows tuple positions to be ignored when using "tie". +inline detail::ignore_t ignore(detail::ignore_t) { return 0; } + +// --------------------------------------------------------------------------- +// The call_traits for make_tuple +// Honours the reference_wrapper class. + +// Must be instantiated with plain or const plain types (not with references) + +// from template foo(const T& t) : make_tuple_traits::type +// from template foo(T& t) : make_tuple_traits::type + +// Conversions: +// T -> T, +// references -> compile_time_error +// reference_wrapper -> T& +// const reference_wrapper -> T& +// array -> const ref array + + +template +struct make_tuple_traits { + typedef T type; + + // commented away, see below (JJ) + // typedef typename IF< + // boost::is_function::value, + // T&, + // T>::RET type; + +}; + +// The is_function test was there originally for plain function types, +// which can't be stored as such (we must either store them as references or +// pointers). Such a type could be formed if make_tuple was called with a +// reference to a function. +// But this would mean that a const qualified function type was formed in +// the make_tuple function and hence make_tuple can't take a function +// reference as a parameter, and thus T can't be a function type. +// So is_function test was removed. +// (14.8.3. says that type deduction fails if a cv-qualified function type +// is created. (It only applies for the case of explicitly specifying template +// args, though?)) (JJ) + +template +struct make_tuple_traits { + typedef typename + detail::generate_error:: + do_not_use_with_reference_type error; +}; + +// Arrays can't be stored as plain types; convert them to references. +// All arrays are converted to const. This is because make_tuple takes its +// parameters as const T& and thus the knowledge of the potential +// non-constness of actual argument is lost. +template struct make_tuple_traits { + typedef const T (&type)[n]; +}; + +template +struct make_tuple_traits { + typedef const T (&type)[n]; +}; + +template struct make_tuple_traits { + typedef const volatile T (&type)[n]; +}; + +template +struct make_tuple_traits { + typedef const volatile T (&type)[n]; +}; + +template +struct make_tuple_traits >{ + typedef T& type; +}; + +template +struct make_tuple_traits >{ + typedef T& type; +}; + +template<> +struct make_tuple_traits { + typedef detail::swallow_assign type; +}; + + + +namespace detail { + +// a helper traits to make the make_tuple functions shorter (Vesa Karvonen's +// suggestion) +template < + class T0 = null_type, class T1 = null_type, class T2 = null_type, + class T3 = null_type, class T4 = null_type, class T5 = null_type, + class T6 = null_type, class T7 = null_type, class T8 = null_type, + class T9 = null_type +> +struct make_tuple_mapper { + typedef + tuple::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type, + typename make_tuple_traits::type> type; +}; + +} // end detail + +// -make_tuple function templates ----------------------------------- +inline tuple<> make_tuple() { + return tuple<>(); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0) { + typedef typename detail::make_tuple_mapper::type t; + return t(t0); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1) { + typedef typename detail::make_tuple_mapper::type t; + return t(t0, t1); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1, const T2& t2) { + typedef typename detail::make_tuple_mapper::type t; + return t(t0, t1, t2); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3) { + typedef typename detail::make_tuple_mapper::type t; + return t(t0, t1, t2, t3); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4) { + typedef typename detail::make_tuple_mapper::type t; + return t(t0, t1, t2, t3, t4); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5) { + typedef typename detail::make_tuple_mapper::type t; + return t(t0, t1, t2, t3, t4, t5); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6) { + typedef typename detail::make_tuple_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6); +} + +template +inline typename detail::make_tuple_mapper::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, const T7& t7) { + typedef typename detail::make_tuple_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7); +} + +template +inline typename detail::make_tuple_mapper + ::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, const T7& t7, + const T8& t8) { + typedef typename detail::make_tuple_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7, t8); +} + +template +inline typename detail::make_tuple_mapper + ::type +make_tuple(const T0& t0, const T1& t1, const T2& t2, const T3& t3, + const T4& t4, const T5& t5, const T6& t6, const T7& t7, + const T8& t8, const T9& t9) { + typedef typename detail::make_tuple_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9); +} + +namespace detail { + +template +struct tie_traits { + typedef T& type; +}; + +template<> +struct tie_traits { + typedef swallow_assign type; +}; + +template<> +struct tie_traits { + typedef null_type type; +}; + +template < + class T0 = void, class T1 = void, class T2 = void, + class T3 = void, class T4 = void, class T5 = void, + class T6 = void, class T7 = void, class T8 = void, + class T9 = void +> +struct tie_mapper { + typedef + tuple::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type, + typename tie_traits::type> type; +}; + +} + +// Tie function templates ------------------------------------------------- +template +inline typename detail::tie_mapper::type +tie(T0& t0) { + typedef typename detail::tie_mapper::type t; + return t(t0); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1, t2); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1, t2, t3); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1, t2, t3, t4); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5) { + typedef typename detail::tie_mapper::type t; + return t(t0, t1, t2, t3, t4, t5); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5, T6& t6) { + typedef typename detail::tie_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6); +} + +template +inline typename detail::tie_mapper::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5, T6& t6, T7& t7) { + typedef typename detail::tie_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7); +} + +template +inline typename detail::tie_mapper + ::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5, T6& t6, T7& t7, + T8& t8) { + typedef typename detail::tie_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7, t8); +} + +template +inline typename detail::tie_mapper + ::type +tie(T0& t0, T1& t1, T2& t2, T3& t3, + T4& t4, T5& t5, T6& t6, T7& t7, + T8& t8, T9& t9) { + typedef typename detail::tie_mapper + ::type t; + return t(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9); +} + +template +void swap(tuple& lhs, + tuple& rhs); +inline void swap(null_type&, null_type&) {} +template +inline void swap(cons& lhs, cons& rhs) { + ::boost::core::invoke_swap(lhs.head, rhs.head); +} +template +inline void swap(cons& lhs, cons& rhs) { + ::boost::core::invoke_swap(lhs.head, rhs.head); + ::boost::tuples::swap(lhs.tail, rhs.tail); +} +template +inline void swap(tuple& lhs, + tuple& rhs) { + typedef tuple tuple_type; + typedef typename tuple_type::inherited base; + ::boost::tuples::swap(static_cast(lhs), static_cast(rhs)); +} + +} // end of namespace tuples +} // end of namespace boost + + +#if defined(BOOST_GCC) && (BOOST_GCC >= 40700) +#pragma GCC diagnostic pop +#endif + + +#endif // BOOST_TUPLE_BASIC_HPP diff --git a/libs/tuple/include/boost/tuple/tuple.hpp b/libs/tuple/include/boost/tuple/tuple.hpp new file mode 100644 index 00000000..cbebdf1b --- /dev/null +++ b/libs/tuple/include/boost/tuple/tuple.hpp @@ -0,0 +1,118 @@ +// tuple.hpp - Boost Tuple Library -------------------------------------- + +// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// +// 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) + +// For more information, see http://www.boost.org + +// ----------------------------------------------------------------- + +#ifndef BOOST_TUPLE_HPP +#define BOOST_TUPLE_HPP + +#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 +// Work around a compiler bug. +// boost::python::tuple has to be seen by the compiler before the +// boost::tuple class template. +namespace boost { namespace python { class tuple; }} +#endif + +#include +#include + +// other compilers +#include +#include + + +namespace boost { + +using tuples::tuple; +using tuples::make_tuple; +using tuples::tie; +#if !defined(BOOST_NO_USING_TEMPLATE) +using tuples::get; +#else +// +// The "using tuples::get" statement causes the +// Borland compiler to ICE, use forwarding +// functions instead: +// +template +inline typename tuples::access_traits< + typename tuples::element >::type + >::non_const_type +get(tuples::cons& c) { + return tuples::get(c); +} +// get function for const cons-lists, returns a const reference to +// the element. If the element is a reference, returns the reference +// as such (that is, can return a non-const reference) +template +inline typename tuples::access_traits< + typename tuples::element >::type + >::const_type +get(const tuples::cons& c) { + return tuples::get(c); +} + +#endif // BOOST_NO_USING_TEMPLATE + +} // end namespace boost + +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) + +#include +#include + +namespace std +{ + +#if defined(BOOST_CLANG) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wmismatched-tags" +#endif + +// std::tuple_size + +template + class tuple_size< boost::tuples::tuple >: + public boost::tuples::length< boost::tuples::tuple > +{ +}; + +template class tuple_size< boost::tuples::cons >: + public boost::tuples::length< boost::tuples::cons > +{ +}; + +template<> class tuple_size< boost::tuples::null_type >: + public boost::tuples::length< boost::tuples::null_type > +{ +}; + +// std::tuple_element + +template + class tuple_element< I, boost::tuples::tuple >: + public boost::tuples::element< I, boost::tuples::tuple > +{ +}; + +template class tuple_element< I, boost::tuples::cons >: + public boost::tuples::element< I, boost::tuples::cons > +{ +}; + +#if defined(BOOST_CLANG) +# pragma clang diagnostic pop +#endif + +} // namespace std + +#endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) + +#endif // BOOST_TUPLE_HPP diff --git a/libs/tuple/include/boost/tuple/tuple_comparison.hpp b/libs/tuple/include/boost/tuple/tuple_comparison.hpp new file mode 100644 index 00000000..0a61952a --- /dev/null +++ b/libs/tuple/include/boost/tuple/tuple_comparison.hpp @@ -0,0 +1,175 @@ +// tuple_comparison.hpp ----------------------------------------------------- +// +// Copyright (C) 2001 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// Copyright (C) 2001 Gary Powell (gary.powell@sierra.com) +// +// 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) +// +// For more information, see http://www.boost.org +// +// (The idea and first impl. of comparison operators was from Doug Gregor) + +// ----------------------------------------------------------------- + +#ifndef BOOST_TUPLE_COMPARISON_HPP +#define BOOST_TUPLE_COMPARISON_HPP + +#include + +// ------------------------------------------------------------- +// equality and comparison operators +// +// == and != compare tuples elementwise +// <, >, <= and >= use lexicographical ordering +// +// Any operator between tuples of different length fails at compile time +// No dependencies between operators are assumed +// (i.e. !(a=b, a!=b does not imply a==b etc. +// so any weirdnesses of elementary operators are respected). +// +// ------------------------------------------------------------- + + +namespace boost { +namespace tuples { + +inline bool operator==(const null_type&, const null_type&) { return true; } +inline bool operator>=(const null_type&, const null_type&) { return true; } +inline bool operator<=(const null_type&, const null_type&) { return true; } +inline bool operator!=(const null_type&, const null_type&) { return false; } +inline bool operator<(const null_type&, const null_type&) { return false; } +inline bool operator>(const null_type&, const null_type&) { return false; } + + +namespace detail { + // comparison operators check statically the length of its operands and + // delegate the comparing task to the following functions. Hence + // the static check is only made once (should help the compiler). + // These functions assume tuples to be of the same length. + + +template +inline bool eq(const T1& lhs, const T2& rhs) { + return lhs.get_head() == rhs.get_head() && + eq(lhs.get_tail(), rhs.get_tail()); +} +template<> +inline bool eq(const null_type&, const null_type&) { return true; } + +template +inline bool neq(const T1& lhs, const T2& rhs) { + return lhs.get_head() != rhs.get_head() || + neq(lhs.get_tail(), rhs.get_tail()); +} +template<> +inline bool neq(const null_type&, const null_type&) { return false; } + +template +inline bool lt(const T1& lhs, const T2& rhs) { + return lhs.get_head() < rhs.get_head() || + ( !(rhs.get_head() < lhs.get_head()) && + lt(lhs.get_tail(), rhs.get_tail())); +} +template<> +inline bool lt(const null_type&, const null_type&) { return false; } + +template +inline bool gt(const T1& lhs, const T2& rhs) { + return lhs.get_head() > rhs.get_head() || + ( !(rhs.get_head() > lhs.get_head()) && + gt(lhs.get_tail(), rhs.get_tail())); +} +template<> +inline bool gt(const null_type&, const null_type&) { return false; } + +template +inline bool lte(const T1& lhs, const T2& rhs) { + return lhs.get_head() <= rhs.get_head() && + ( !(rhs.get_head() <= lhs.get_head()) || + lte(lhs.get_tail(), rhs.get_tail())); +} +template<> +inline bool lte(const null_type&, const null_type&) { return true; } + +template +inline bool gte(const T1& lhs, const T2& rhs) { + return lhs.get_head() >= rhs.get_head() && + ( !(rhs.get_head() >= lhs.get_head()) || + gte(lhs.get_tail(), rhs.get_tail())); +} +template<> +inline bool gte(const null_type&, const null_type&) { return true; } + +} // end of namespace detail + + +// equal ---- + +template +inline bool operator==(const cons& lhs, const cons& rhs) +{ + // check that tuple lengths are equal + BOOST_STATIC_ASSERT(length::value == length::value); + + return detail::eq(lhs, rhs); +} + +// not equal ----- + +template +inline bool operator!=(const cons& lhs, const cons& rhs) +{ + + // check that tuple lengths are equal + BOOST_STATIC_ASSERT(length::value == length::value); + + return detail::neq(lhs, rhs); +} + +// < +template +inline bool operator<(const cons& lhs, const cons& rhs) +{ + // check that tuple lengths are equal + BOOST_STATIC_ASSERT(length::value == length::value); + + return detail::lt(lhs, rhs); +} + +// > +template +inline bool operator>(const cons& lhs, const cons& rhs) +{ + // check that tuple lengths are equal + BOOST_STATIC_ASSERT(length::value == length::value); + + return detail::gt(lhs, rhs); +} + +// <= +template +inline bool operator<=(const cons& lhs, const cons& rhs) +{ + // check that tuple lengths are equal + BOOST_STATIC_ASSERT(length::value == length::value); + + return detail::lte(lhs, rhs); +} + +// >= +template +inline bool operator>=(const cons& lhs, const cons& rhs) +{ + // check that tuple lengths are equal + BOOST_STATIC_ASSERT(length::value == length::value); + + return detail::gte(lhs, rhs); +} + +} // end of namespace tuples +} // end of namespace boost + + +#endif // BOOST_TUPLE_COMPARISON_HPP diff --git a/libs/tuple/include/boost/tuple/tuple_io.hpp b/libs/tuple/include/boost/tuple/tuple_io.hpp new file mode 100644 index 00000000..ce551702 --- /dev/null +++ b/libs/tuple/include/boost/tuple/tuple_io.hpp @@ -0,0 +1,339 @@ +// tuple_io.hpp -------------------------------------------------------------- + +// Copyright (C) 2001 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// 2001 Gary Powell (gary.powell@sierra.com) +// +// 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) +// For more information, see http://www.boost.org + +// ---------------------------------------------------------------------------- + +#ifndef BOOST_TUPLE_IO_HPP +#define BOOST_TUPLE_IO_HPP + +#include +#include + +#include + +#include + +// This is ugly: one should be using twoargument isspace since whitspace can +// be locale dependent, in theory at least. +// not all libraries implement have the two-arg version, so we need to +// use the one-arg one, which one should get with but there seem +// to be exceptions to this. + +#if !defined (BOOST_NO_STD_LOCALE) + +#include // for two-arg isspace + +#else + +#include // for one-arg (old) isspace +#include // Metrowerks does not find one-arg isspace from cctype + +#endif + +namespace boost { +namespace tuples { + +namespace detail { + +class format_info { +public: + + enum manipulator_type { open, close, delimiter }; + BOOST_STATIC_CONSTANT(int, number_of_manipulators = delimiter + 1); +private: + + static int get_stream_index (int m) + { + static const int stream_index[number_of_manipulators] + = { std::ios::xalloc(), std::ios::xalloc(), std::ios::xalloc() }; + + return stream_index[m]; + } + + format_info(const format_info&); + format_info(); + + +public: + + template + static CharType get_manipulator(std::basic_ios& i, + manipulator_type m) { + // The manipulators are stored as long. + // A valid instanitation of basic_stream allows CharType to be any POD, + // hence, the static_cast may fail (it fails if long is not convertible + // to CharType + CharType c = static_cast(i.iword(get_stream_index(m)) ); + // parentheses and space are the default manipulators + if (!c) { + switch(m) { + case detail::format_info::open : c = i.widen('('); break; + case detail::format_info::close : c = i.widen(')'); break; + case detail::format_info::delimiter : c = i.widen(' '); break; + } + } + return c; + } + + + template + static void set_manipulator(std::basic_ios& i, + manipulator_type m, CharType c) { + // The manipulators are stored as long. + // A valid instanitation of basic_stream allows CharType to be any POD, + // hence, the static_cast may fail (it fails if CharType is not + // convertible long. + i.iword(get_stream_index(m)) = static_cast(c); + } +}; + +} // end of namespace detail + +template +class tuple_manipulator { + const detail::format_info::manipulator_type mt; + CharType f_c; +public: + explicit tuple_manipulator(detail::format_info::manipulator_type m, + CharType c = CharType()) + : mt(m), f_c(c) {} + + template + void set(std::basic_ios &io) const { + detail::format_info::set_manipulator(io, mt, f_c); + } +}; + + +template +inline std::basic_ostream& +operator<<(std::basic_ostream& o, const tuple_manipulator& m) { + m.set(o); + return o; +} + +template +inline std::basic_istream& +operator>>(std::basic_istream& i, const tuple_manipulator& m) { + m.set(i); + return i; +} + + +template +inline tuple_manipulator set_open(const CharType c) { + return tuple_manipulator(detail::format_info::open, c); +} + +template +inline tuple_manipulator set_close(const CharType c) { + return tuple_manipulator(detail::format_info::close, c); +} + +template +inline tuple_manipulator set_delimiter(const CharType c) { + return tuple_manipulator(detail::format_info::delimiter, c); +} + + + + + +// ------------------------------------------------------------- +// printing tuples to ostream in format (a b c) +// parentheses and space are defaults, but can be overriden with manipulators +// set_open, set_close and set_delimiter + +namespace detail { + +// Note: The order of the print functions is critical +// to let a conforming compiler find and select the correct one. + + +template +inline std::basic_ostream& +print(std::basic_ostream& o, const cons& t) { + return o << t.head; +} + + +template +inline std::basic_ostream& +print(std::basic_ostream& o, const null_type&) { + return o; +} + +template +inline std::basic_ostream& +print(std::basic_ostream& o, const cons& t) { + + const CharType d = format_info::get_manipulator(o, format_info::delimiter); + + o << t.head; + + o << d; + + return print(o, t.tail); +} + +template +inline bool handle_width(std::basic_ostream& o, const T& t) { + std::streamsize width = o.width(); + if(width == 0) return false; + + std::basic_ostringstream ss; + + ss.copyfmt(o); + ss.tie(0); + ss.width(0); + + ss << t; + o << ss.str(); + + return true; +} + + +} // namespace detail + + +template +inline std::basic_ostream& +operator<<(std::basic_ostream& o, + const null_type& t) { + if (!o.good() ) return o; + if (detail::handle_width(o, t)) return o; + + const CharType l = + detail::format_info::get_manipulator(o, detail::format_info::open); + const CharType r = + detail::format_info::get_manipulator(o, detail::format_info::close); + + o << l; + o << r; + + return o; +} + +template +inline std::basic_ostream& +operator<<(std::basic_ostream& o, + const cons& t) { + if (!o.good() ) return o; + if (detail::handle_width(o, t)) return o; + + const CharType l = + detail::format_info::get_manipulator(o, detail::format_info::open); + const CharType r = + detail::format_info::get_manipulator(o, detail::format_info::close); + + o << l; + + detail::print(o, t); + + o << r; + + return o; +} + + +// ------------------------------------------------------------- +// input stream operators + +namespace detail { + + +template +inline std::basic_istream& +extract_and_check_delimiter( + std::basic_istream &is, format_info::manipulator_type del) +{ + const CharType d = format_info::get_manipulator(is, del); + +#if defined (BOOST_NO_STD_LOCALE) + const bool is_delimiter = !isspace(d); +#elif defined ( BOOST_BORLANDC ) + const bool is_delimiter = !std::use_facet< std::ctype< CharType > > + (is.getloc() ).is( std::ctype_base::space, d); +#else + const bool is_delimiter = (!std::isspace(d, is.getloc()) ); +#endif + + CharType c; + if (is_delimiter) { + is >> c; + if (is.good() && c!=d) { + is.setstate(std::ios::failbit); + } + } else { + is >> std::ws; + } + return is; +} + + +template +inline std::basic_istream & +read (std::basic_istream &is, cons& t1) { + + if (!is.good()) return is; + + return is >> t1.head; +} + +template +inline std::basic_istream& +read(std::basic_istream &is, cons& t1) { + + if (!is.good()) return is; + + is >> t1.head; + + + extract_and_check_delimiter(is, format_info::delimiter); + + return read(is, t1.tail); +} + +} // end namespace detail + + +template +inline std::basic_istream& +operator>>(std::basic_istream &is, null_type&) { + + if (!is.good() ) return is; + + detail::extract_and_check_delimiter(is, detail::format_info::open); + detail::extract_and_check_delimiter(is, detail::format_info::close); + + return is; +} + +template +inline std::basic_istream& +operator>>(std::basic_istream& is, cons& t1) { + + if (!is.good() ) return is; + + detail::extract_and_check_delimiter(is, detail::format_info::open); + + detail::read(is, t1); + + detail::extract_and_check_delimiter(is, detail::format_info::close); + + return is; +} + + +} // end of namespace tuples +} // end of namespace boost + +#endif // BOOST_TUPLE_IO_HPP diff --git a/libs/tuple/index.html b/libs/tuple/index.html new file mode 100644 index 00000000..437c1e73 --- /dev/null +++ b/libs/tuple/index.html @@ -0,0 +1,13 @@ + + + + + +Automatic redirection failed, please go to doc/html/tuple_users_guide.html
+

© Copyright Beman Dawes, 2001

+

Distributed under the Boost Software License, Version 1.0. (See accompanying +file LICENSE_1_0.txt or copy +at www.boost.org/LICENSE_1_0.txt)

+ + diff --git a/libs/tuple/meta/libraries.json b/libs/tuple/meta/libraries.json new file mode 100644 index 00000000..9de7dbf6 --- /dev/null +++ b/libs/tuple/meta/libraries.json @@ -0,0 +1,18 @@ +{ + "key": "tuple", + "name": "Tuple", + "authors": [ + "Jaakko Järvi" + ], + "description": "Ease definition of functions returning multiple values, and more.", + "std": [ + "tr1" + ], + "category": [ + "Data" + ], + "maintainers": [ + "Jaakko Jarvi " + ], + "cxxstd": "03" +} diff --git a/libs/tuple/test/CMakeLists.txt b/libs/tuple/test/CMakeLists.txt new file mode 100644 index 00000000..9ee9e26f --- /dev/null +++ b/libs/tuple/test/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright 2018, 2019 Peter Dimov +# 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 + +include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST) + +if(HAVE_BOOST_TEST) + +boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::tuple Boost::core) + +endif() diff --git a/libs/tuple/test/Jamfile b/libs/tuple/test/Jamfile new file mode 100644 index 00000000..fe90abca --- /dev/null +++ b/libs/tuple/test/Jamfile @@ -0,0 +1,12 @@ +# Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +# Distributed under the Boost Software License, Version 1.0. + +import testing ; + +run tuple_test_bench.cpp ; +run io_test.cpp ; +run another_tuple_test_bench.cpp ; +run std_tuple_size.cpp ; +run std_tuple_element.cpp ; +run structured_bindings.cpp ; +run quick.cpp ; diff --git a/libs/tuple/test/README b/libs/tuple/test/README new file mode 100644 index 00000000..6047c49a --- /dev/null +++ b/libs/tuple/test/README @@ -0,0 +1,16 @@ +To compile the + +libs/tuple/test/*.cpp + +files, you need to set include paths +for boost. +For example, in libs/tuple/test directory you would type (using g++): + +g++ -I../../.. tuple_test_bench.cpp + +The following is not true anymore: + + If you want to use tuple_io, you need to compile and link src/tuple.cpp: + g++ -I../../.. ../src/tuple.cpp io_test.cpp + +Thanks to Hartmut Kaiser's suggestion, the tuple.cpp is not needed anymore. diff --git a/libs/tuple/test/another_tuple_test_bench.cpp b/libs/tuple/test/another_tuple_test_bench.cpp new file mode 100644 index 00000000..153548ec --- /dev/null +++ b/libs/tuple/test/another_tuple_test_bench.cpp @@ -0,0 +1,162 @@ +// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// +// 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) + +// For more information, see http://www.boost.org + + +// another_test_bench.cpp -------------------------------- + +// This file has various tests to see that things that shouldn't +// compile, don't compile. + +// Defining any of E1 to E5 or E7 to E11 opens some illegal code that +// should cause the compliation to fail. + +#include "boost/tuple/tuple.hpp" + +#include "boost/core/lightweight_test.hpp" + +#include +#include + +using namespace boost; +using namespace boost::tuples; + + +template void dummy(const T&) {} + +class A {}; class B {}; class C {}; + +// A non-copyable class +class no_copy { + no_copy(const no_copy&) {} +public: + no_copy() {}; +}; + +no_copy y; + +#ifdef E1 +tuple v1; // should faild +#endif + + +#ifdef E2 +char cs[10]; +tuple v3; // should fail, arrays must be stored as references +#endif + +// a class without a public default constructor +class no_def_constructor { + no_def_constructor() {} +public: + no_def_constructor(std::string) {} // can be constructed with a string +}; + +void foo1() { + +#ifdef E3 + dummy(tuple()); + // should fail + +#endif +} + +void foo2() { +// testing default values +#ifdef E4 + dummy(tuple()); // should fail, not defaults for references + dummy(tuple()); // likewise +#endif + +#ifdef E5 + double dd = 5; + dummy(tuple(dd+3.14)); // should fail, temporary to non-const reference +#endif +} + + + +// make_tuple ------------------------------------------ + + + void foo3() { +#ifdef E7 + std::make_pair("Doesn't","Work"); // fails +#endif + // make_tuple("Does", "Work"); // this should work +} + + + +// - testing element access + +void foo4() +{ + double d = 2.7; + A a; + tuple t(1, d, a); + const tuple ct = t; + (void)ct; +#ifdef E8 + get<0>(ct) = 5; // can't assign to const +#endif + +#ifdef E9 + get<4>(t) = A(); // can't assign to const +#endif +#ifdef E10 + dummy(get<5>(ct)); // illegal index +#endif +} + +// testing copy and assignment with implicit conversions between elements +// testing tie + + class AA {}; + class BB : public AA {}; + struct CC { CC() {} CC(const BB& b) {} }; + struct DD { operator CC() const { return CC(); }; }; + + void foo5() { + tuple t; + (void)t; + tuple aaa; + tuple bbb(aaa); + (void)bbb; + // tuple a = t; + // a = t; + } + + +// testing tie +// testing assignment from std::pair +void foo7() { + + tuple a; +#ifdef E11 + a = std::make_pair(1, 2); // should fail, tuple is of length 3, not 2 +#endif + + dummy(a); +} + + + +// -------------------------------- +// ---------------------------- +int main() { + + foo1(); + foo2(); + foo3(); + foo4(); + foo5(); + + foo7(); + + return boost::report_errors(); +} diff --git a/libs/tuple/test/cmake_install_test/CMakeLists.txt b/libs/tuple/test/cmake_install_test/CMakeLists.txt new file mode 100644 index 00000000..ce332499 --- /dev/null +++ b/libs/tuple/test/cmake_install_test/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright 2018, 2019 Peter Dimov +# 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 + +cmake_minimum_required(VERSION 3.5...3.16) + +project(cmake_install_test LANGUAGES CXX) + +find_package(boost_tuple REQUIRED) + +add_executable(main main.cpp) +target_link_libraries(main Boost::tuple) + +enable_testing() +add_test(main main) + +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) diff --git a/libs/tuple/test/cmake_install_test/main.cpp b/libs/tuple/test/cmake_install_test/main.cpp new file mode 100644 index 00000000..4c7dafad --- /dev/null +++ b/libs/tuple/test/cmake_install_test/main.cpp @@ -0,0 +1,18 @@ +// Copyright 2017, 2021 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +#define BOOST_TEST(expr) assert(expr) +#define BOOST_TEST_EQ(x1, x2) assert((x1)==(x2)) + +int main() +{ + boost::tuple tp( 1, 2, 3 ); + + BOOST_TEST_EQ( boost::get<0>(tp), 1 ); + BOOST_TEST_EQ( boost::get<1>(tp), 2 ); + BOOST_TEST_EQ( boost::get<2>(tp), 3 ); +} diff --git a/libs/tuple/test/cmake_subdir_test/CMakeLists.txt b/libs/tuple/test/cmake_subdir_test/CMakeLists.txt new file mode 100644 index 00000000..ff20e856 --- /dev/null +++ b/libs/tuple/test/cmake_subdir_test/CMakeLists.txt @@ -0,0 +1,40 @@ +# Copyright 2018, 2019 Peter Dimov +# 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 + +cmake_minimum_required(VERSION 3.5...3.20) + +project(cmake_subdir_test LANGUAGES CXX) + +add_subdirectory(../.. boostorg/tuple) + +set(deps + +# Primary dependencies + +config +core +static_assert +type_traits + +# Secondary dependencies + +assert +throw_exception +) + +foreach(dep IN LISTS deps) + + add_subdirectory(../../../${dep} boostorg/${dep}) + +endforeach() + +# --target check + +add_executable(quick ../quick.cpp) +target_link_libraries(quick Boost::tuple Boost::core) + +enable_testing() +add_test(quick quick) + +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) diff --git a/libs/tuple/test/io_test.cpp b/libs/tuple/test/io_test.cpp new file mode 100644 index 00000000..64dea1f7 --- /dev/null +++ b/libs/tuple/test/io_test.cpp @@ -0,0 +1,147 @@ +// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// +// 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) + +// For more information, see http://www.boost.org + +// -- io_test.cpp ----------------------------------------------- +// +// Testing the I/O facilities of tuples + +#define _CRT_SECURE_NO_WARNINGS // std::tmpnam + +#include "boost/tuple/tuple_io.hpp" +#include "boost/tuple/tuple_comparison.hpp" + +#include "boost/core/lightweight_test.hpp" + +#include +#include +#include +#include +#include +#include + +#if defined BOOST_NO_STRINGSTREAM +#include +#else +#include +#endif + +#define BOOST_CHECK BOOST_TEST + +using namespace boost; + +#if defined BOOST_NO_STRINGSTREAM +typedef std::ostrstream useThisOStringStream; +typedef std::istrstream useThisIStringStream; +#else +typedef std::ostringstream useThisOStringStream; +typedef std::istringstream useThisIStringStream; +#endif + +int main() { + using boost::tuples::set_close; + using boost::tuples::set_open; + using boost::tuples::set_delimiter; + + useThisOStringStream os1; + + // Set format [a, b, c] for os1 + os1 << set_open('['); + os1 << set_close(']'); + os1 << set_delimiter(','); + os1 << make_tuple(1, 2, 3); + BOOST_CHECK (os1.str() == std::string("[1,2,3]") ); + + { + useThisOStringStream os2; + // Set format (a:b:c) for os2; + os2 << set_open('('); + os2 << set_close(')'); + os2 << set_delimiter(':'); +#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + os2 << make_tuple("TUPU", "HUPU", "LUPU", 4.5); + BOOST_CHECK (os2.str() == std::string("(TUPU:HUPU:LUPU:4.5)") ); +#endif + } + + // The format is still [a, b, c] for os1 + os1 << make_tuple(1, 2, 3); + BOOST_CHECK (os1.str() == std::string("[1,2,3][1,2,3]") ); + + // check empty tuple. + useThisOStringStream os3; + os3 << make_tuple(); + BOOST_CHECK (os3.str() == std::string("()") ); + os3 << set_open('['); + os3 << set_close(']'); + os3 << make_tuple(); + BOOST_CHECK (os3.str() == std::string("()[]") ); + + // check width + useThisOStringStream os4; + os4 << std::setw(10) << make_tuple(1, 2, 3); + BOOST_CHECK (os4.str() == std::string(" (1 2 3)") ); + + std::string fn = std::tmpnam( 0 ); + + std::ofstream tmp( fn.c_str() ); + +#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + tmp << make_tuple("One", "Two", 3); +#endif + tmp << set_delimiter(':'); + tmp << make_tuple(1000, 2000, 3000) << std::endl; + + tmp.close(); + + // When teading tuples from a stream, manipulators must be set correctly: + std::ifstream tmp3( fn.c_str() ); + tuple j; + +#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + tmp3 >> j; + BOOST_CHECK (tmp3.good() ); +#endif + + tmp3 >> set_delimiter(':'); + tuple i; + tmp3 >> i; + BOOST_CHECK (tmp3.good() ); + + tmp3.close(); + + std::remove( fn.c_str() ); + + // reading tuple in format (a b c); + useThisIStringStream is1("(100 200 300)"); + + tuple ti1; + BOOST_CHECK(bool(is1 >> ti1)); + BOOST_CHECK(ti1 == make_tuple(100, 200, 300)); + + useThisIStringStream is2("()"); + tuple<> ti2; + BOOST_CHECK(bool(is2 >> ti2)); + useThisIStringStream is3("[]"); + is3 >> set_open('['); + is3 >> set_close(']'); + BOOST_CHECK(bool(is3 >> ti2)); + + // Make sure that whitespace between elements + // is skipped. + useThisIStringStream is4("(100 200 300)"); + + BOOST_CHECK(bool(is4 >> std::noskipws >> ti1)); + BOOST_CHECK(ti1 == make_tuple(100, 200, 300)); + + // Note that strings are problematic: + // writing a tuple on a stream and reading it back doesn't work in + // general. If this is wanted, some kind of a parseable string class + // should be used. + + return boost::report_errors(); +} diff --git a/libs/tuple/test/quick.cpp b/libs/tuple/test/quick.cpp new file mode 100644 index 00000000..c78dde50 --- /dev/null +++ b/libs/tuple/test/quick.cpp @@ -0,0 +1,16 @@ +// Copyright 2023 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include + +int main() +{ + boost::tuple tp( 1, 2, 3 ); + + BOOST_TEST_EQ( boost::get<0>(tp), 1 ); + BOOST_TEST_EQ( boost::get<1>(tp), 2 ); + BOOST_TEST_EQ( boost::get<2>(tp), 3 ); + + return boost::report_errors(); +} diff --git a/libs/tuple/test/std_tuple_element.cpp b/libs/tuple/test/std_tuple_element.cpp new file mode 100644 index 00000000..762d1fad --- /dev/null +++ b/libs/tuple/test/std_tuple_element.cpp @@ -0,0 +1,56 @@ +// Copyright 2017 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include +#include +#include +#include + +#if defined(BOOST_NO_CXX11_HDR_TUPLE) + +BOOST_PRAGMA_MESSAGE("Skipping std::tuple_element tests for lack of ") +int main() {} + +#else + +#include + +template void test() +{ + BOOST_TEST_TRAIT_TRUE((boost::is_same::type, E>)); + + typedef typename Tp::inherited Tp2; + BOOST_TEST_TRAIT_TRUE((boost::is_same::type, E>)); +} + +template struct X +{ +}; + +int main() +{ + test const>, 0, X<0> const>(); + + test const, X<1> const>, 0, X<0> const>(); + test const, X<1> const>, 1, X<1> const>(); + + test const, X<1> const, X<2> const>, 0, X<0> const>(); + test const, X<1> const, X<2> const>, 1, X<1> const>(); + test const, X<1> const, X<2> const>, 2, X<2> const>(); + + test const, X<1> const, X<2> const, X<3> const>, 0, X<0> const>(); + test const, X<1> const, X<2> const, X<3> const>, 1, X<1> const>(); + test const, X<1> const, X<2> const, X<3> const>, 2, X<2> const>(); + test const, X<1> const, X<2> const, X<3> const>, 3, X<3> const>(); + + test const, X<1> const, X<2> const, X<3> const, X<4> const>, 0, X<0> const>(); + test const, X<1> const, X<2> const, X<3> const, X<4> const>, 1, X<1> const>(); + test const, X<1> const, X<2> const, X<3> const, X<4> const>, 2, X<2> const>(); + test const, X<1> const, X<2> const, X<3> const, X<4> const>, 3, X<3> const>(); + test const, X<1> const, X<2> const, X<3> const, X<4> const>, 4, X<4> const>(); + + return boost::report_errors(); +} + +#endif diff --git a/libs/tuple/test/std_tuple_size.cpp b/libs/tuple/test/std_tuple_size.cpp new file mode 100644 index 00000000..5525f63e --- /dev/null +++ b/libs/tuple/test/std_tuple_size.cpp @@ -0,0 +1,61 @@ +// Copyright 2017 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include +#include +#include + +#if defined(BOOST_NO_CXX11_HDR_TUPLE) + +BOOST_PRAGMA_MESSAGE("Skipping std::tuple_size tests for lack of ") +int main() {} + +#else + +#include + +template void test( std::size_t x ) +{ + BOOST_TEST_EQ( std::tuple_size< Tp >::value, x ); + BOOST_TEST_EQ( std::tuple_size< typename Tp::inherited >::value, x ); +} + +struct V +{ +}; + +int main() +{ + test< boost::tuple<> >( 0 ); + test< boost::tuple >( 1 ); + test< boost::tuple >( 2 ); + test< boost::tuple >( 3 ); + test< boost::tuple >( 4 ); + test< boost::tuple >( 5 ); + test< boost::tuple >( 6 ); + test< boost::tuple >( 7 ); + test< boost::tuple >( 8 ); + test< boost::tuple >( 9 ); + test< boost::tuple >( 10 ); + +#if !defined(BOOST_NO_CXX11_DECLTYPE) + + BOOST_TEST_EQ( std::tuple_size::value, 0 ); + BOOST_TEST_EQ( std::tuple_size::value, 1 ); + BOOST_TEST_EQ( std::tuple_size::value, 2 ); + BOOST_TEST_EQ( std::tuple_size::value, 3 ); + BOOST_TEST_EQ( std::tuple_size::value, 4 ); + BOOST_TEST_EQ( std::tuple_size::value, 5 ); + BOOST_TEST_EQ( std::tuple_size::value, 6 ); + BOOST_TEST_EQ( std::tuple_size::value, 7 ); + BOOST_TEST_EQ( std::tuple_size::value, 8 ); + BOOST_TEST_EQ( std::tuple_size::value, 9 ); + BOOST_TEST_EQ( std::tuple_size::value, 10 ); + +#endif + + return boost::report_errors(); +} + +#endif diff --git a/libs/tuple/test/structured_bindings.cpp b/libs/tuple/test/structured_bindings.cpp new file mode 100644 index 00000000..432ba0a4 --- /dev/null +++ b/libs/tuple/test/structured_bindings.cpp @@ -0,0 +1,77 @@ +// Copyright 2017 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include +#include +#include + +#if defined(BOOST_NO_CXX17_STRUCTURED_BINDINGS) + +BOOST_PRAGMA_MESSAGE("Skipping structured bindings test, not supported") +int main() {} + +#else + +int main() +{ + // make_tuple + + { + auto [x1] = boost::make_tuple( 1 ); + BOOST_TEST_EQ( x1, 1 ); + } + + { + auto [x1, x2] = boost::make_tuple( 1, 2 ); + BOOST_TEST_EQ( x1, 1 ); + BOOST_TEST_EQ( x2, 2 ); + } + + { + auto [x1, x2, x3] = boost::make_tuple( 1, 2, 3 ); + BOOST_TEST_EQ( x1, 1 ); + BOOST_TEST_EQ( x2, 2 ); + BOOST_TEST_EQ( x3, 3 ); + } + + { + auto [x1, x2, x3, x4] = boost::make_tuple( 1, 2, 3, 4 ); + BOOST_TEST_EQ( x1, 1 ); + BOOST_TEST_EQ( x2, 2 ); + BOOST_TEST_EQ( x3, 3 ); + BOOST_TEST_EQ( x4, 4 ); + } + + // tuple + + { + auto [x1] = boost::tuple( 1 ); + BOOST_TEST_EQ( x1, 1 ); + } + + { + auto [x1, x2] = boost::tuple( 1, 2 ); + BOOST_TEST_EQ( x1, 1 ); + BOOST_TEST_EQ( x2, 2 ); + } + + { + auto [x1, x2, x3] = boost::tuple( 1, 2, 3 ); + BOOST_TEST_EQ( x1, 1 ); + BOOST_TEST_EQ( x2, 2 ); + BOOST_TEST_EQ( x3, 3 ); + } + + { + auto [x1, x2, x3, x4] = boost::tuple( 1, 2, 3, 4 ); + BOOST_TEST_EQ( x1, 1 ); + BOOST_TEST_EQ( x2, 2 ); + BOOST_TEST_EQ( x3, 3 ); + BOOST_TEST_EQ( x4, 4 ); + } + + return boost::report_errors(); +} + +#endif diff --git a/libs/tuple/test/tuple_test_bench.cpp b/libs/tuple/test/tuple_test_bench.cpp new file mode 100644 index 00000000..f635df8c --- /dev/null +++ b/libs/tuple/test/tuple_test_bench.cpp @@ -0,0 +1,490 @@ +// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) +// +// 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) + +// For more information, see http://www.boost.org + +// tuple_test_bench.cpp -------------------------------- + +#include "boost/tuple/tuple.hpp" +#include "boost/tuple/tuple_comparison.hpp" + +#include "boost/type_traits/is_const.hpp" +#include "boost/ref.hpp" +#include "boost/core/lightweight_test.hpp" + +#include +#include + +#define BOOST_CHECK BOOST_TEST + +using namespace boost; + +// ---------------------------------------------------------------------------- +// helpers +// ---------------------------------------------------------------------------- + +class A {}; +class B {}; +class C {}; + +// classes with different kinds of conversions +class AA {}; +class BB : public AA {}; +struct CC { CC() {} CC(const BB&) {} }; +struct DD { operator CC() const { return CC(); }; }; + +// something to prevent warnings for unused variables +template void dummy(const T&) {} + +// no public default constructor +class foo { +public: + explicit foo(int v) : val(v) {} + + bool operator==(const foo& other) const { + return val == other.val; + } + +private: + foo() {} + int val; +}; + +// another class without a public default constructor +class no_def_constructor { + no_def_constructor() {} +public: + no_def_constructor(std::string) {} +}; + +// A non-copyable class +class no_copy { + no_copy(const no_copy&) {} +public: + no_copy() {}; +}; + + +// ---------------------------------------------------------------------------- +// Testing different element types -------------------------------------------- +// ---------------------------------------------------------------------------- + + +typedef tuple t1; + +typedef tuple t2; +typedef tuple t3; +typedef tuple > t4; +typedef tuple, bool, void*> t5; +typedef tuple t6; + +# if !defined(BOOST_BORLANDC) || BOOST_BORLANDC > 0x0551 +typedef tuple t7; +#endif + +// ----------------------------------------------------------------------- +// -tuple construction tests --------------------------------------------- +// ----------------------------------------------------------------------- + + +no_copy y; +tuple x = tuple(y); // ok + +char cs[10]; +tuple v2(cs); // ok + +void +construction_test() +{ + + // Note, the get function can be called without the tuples:: qualifier, + // as it is lifted to namespace boost with a "using tuples::get" but + // MSVC 6.0 just cannot find get without the namespace qualifier + + tuple t1; + BOOST_CHECK(get<0>(t1) == int()); + + tuple t2(5.5f); + BOOST_CHECK(get<0>(t2) > 5.4f && get<0>(t2) < 5.6f); + + tuple t3(foo(12)); + BOOST_CHECK(get<0>(t3) == foo(12)); + + tuple t4(t2); + BOOST_CHECK(get<0>(t4) > 5.4 && get<0>(t4) < 5.6); + + tuple t5; + BOOST_CHECK(get<0>(t5) == int()); + BOOST_CHECK(get<1>(t5) == float()); + + tuple t6(12, 5.5f); + BOOST_CHECK(get<0>(t6) == 12); + BOOST_CHECK(get<1>(t6) > 5.4f && get<1>(t6) < 5.6f); + + tuple t7(t6); + BOOST_CHECK(get<0>(t7) == 12); + BOOST_CHECK(get<1>(t7) > 5.4f && get<1>(t7) < 5.6f); + + tuple t8(t6); + BOOST_CHECK(get<0>(t8) == 12); + BOOST_CHECK(get<1>(t8) > 5.4f && get<1>(t8) < 5.6f); + + dummy( + tuple( + std::string("Jaba"), // ok, since the default + std::string("Daba"), // constructor is not used + std::string("Doo") + ) + ); + +// testing default values + dummy(tuple()); + dummy(tuple(1)); + dummy(tuple(1,3.14)); + + + // dummy(tuple()); // should fail, not defaults for references + // dummy(tuple()); // likewise + + double dd = 5; + dummy(tuple(dd)); // ok + + dummy(tuple(dd+3.14)); // ok, but dangerous + + // dummy(tuple(dd+3.14)); // should fail, + // // temporary to non-const reference +} + + +// ---------------------------------------------------------------------------- +// - testing element access --------------------------------------------------- +// ---------------------------------------------------------------------------- + +void element_access_test() +{ + double d = 2.7; + A a; + tuple t(1, d, a, 2); + const tuple ct = t; + + int i = get<0>(t); + int i2 = get<3>(t); + + BOOST_CHECK(i == 1 && i2 == 2); + + int j = get<0>(ct); + BOOST_CHECK(j == 1); + + get<0>(t) = 5; + BOOST_CHECK(t.head == 5); + + // get<0>(ct) = 5; // can't assign to const + + double e = get<1>(t); + BOOST_CHECK(e > 2.69 && e < 2.71); + + get<1>(t) = 3.14+i; + BOOST_CHECK(get<1>(t) > 4.13 && get<1>(t) < 4.15); + + // get<4>(t) = A(); // can't assign to const + // dummy(get<5>(ct)); // illegal index + + ++get<0>(t); + BOOST_CHECK(get<0>(t) == 6); + + BOOST_STATIC_ASSERT((boost::is_const >::type>::value != true)); +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + BOOST_STATIC_ASSERT((boost::is_const >::type>::value)); +#endif + + BOOST_STATIC_ASSERT((boost::is_const >::type>::value != true)); +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + BOOST_STATIC_ASSERT((boost::is_const >::type>::value)); +#endif + + + dummy(i); dummy(i2); dummy(j); dummy(e); // avoid warns for unused variables +} + + +// ---------------------------------------------------------------------------- +// - copying tuples ----------------------------------------------------------- +// ---------------------------------------------------------------------------- + + + +void +copy_test() +{ + tuple t1(4, 'a'); + tuple t2(5, 'b'); + t2 = t1; + BOOST_CHECK(get<0>(t1) == get<0>(t2)); + BOOST_CHECK(get<1>(t1) == get<1>(t2)); + + tuple t3(2, "a"); + t3 = t1; + BOOST_CHECK((double)get<0>(t1) == get<0>(t3)); + BOOST_CHECK(get<1>(t1) == get<1>(t3)[0]); + +// testing copy and assignment with implicit conversions between elements +// testing tie + + tuple t; + tuple a(t); + a = t; + + int i; char c; double d; + tie(i, c, d) = make_tuple(1, 'a', 5.5); + + BOOST_CHECK(i==1); + BOOST_CHECK(c=='a'); + BOOST_CHECK(d>5.4 && d<5.6); +} + +void +mutate_test() +{ + tuple t1(5, 12.2f, true, foo(4)); + get<0>(t1) = 6; + get<1>(t1) = 2.2f; + get<2>(t1) = false; + get<3>(t1) = foo(5); + + BOOST_CHECK(get<0>(t1) == 6); + BOOST_CHECK(get<1>(t1) > 2.1f && get<1>(t1) < 2.3f); + BOOST_CHECK(get<2>(t1) == false); + BOOST_CHECK(get<3>(t1) == foo(5)); +} + +// ---------------------------------------------------------------------------- +// make_tuple tests ----------------------------------------------------------- +// ---------------------------------------------------------------------------- + +void +make_tuple_test() +{ + tuple t1 = make_tuple(5, 'a'); + BOOST_CHECK(get<0>(t1) == 5); + BOOST_CHECK(get<1>(t1) == 'a'); + + tuple t2; + t2 = boost::make_tuple((short int)2, std::string("Hi")); + BOOST_CHECK(get<0>(t2) == 2); + BOOST_CHECK(get<1>(t2) == "Hi"); + + + A a = A(); B b; + const A ca = a; + make_tuple(boost::cref(a), b); + make_tuple(boost::ref(a), b); + make_tuple(boost::ref(a), boost::cref(b)); + + make_tuple(boost::ref(ca)); + +// the result of make_tuple is assignable: + BOOST_CHECK(make_tuple(2, 4, 6) == + (make_tuple(1, 2, 3) = make_tuple(2, 4, 6))); + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + make_tuple("Donald", "Daisy"); // should work; +#endif + // std::make_pair("Doesn't","Work"); // fails + +// You can store a reference to a function in a tuple + tuple adf(make_tuple_test); + + dummy(adf); // avoid warning for unused variable + +// But make_tuple doesn't work +// with function references, since it creates a const qualified function type + +// make_tuple(make_tuple_test); + +// With function pointers, make_tuple works just fine + +#if !defined(BOOST_BORLANDC) || BOOST_BORLANDC > 0x0551 + make_tuple(&make_tuple_test); +#endif + +// NOTE: +// +// wrapping it the function reference with ref helps on gcc 2.95.2. +// on edg 2.43. it results in a catastrophic error? + +// make_tuple(ref(foo3)); + +// It seems that edg can't use implicitly the ref's conversion operator, e.g.: +// typedef void (&func_t) (void); +// func_t fref = static_cast(ref(make_tuple_test)); // works fine +// func_t fref = ref(make_tuple_test); // error + +// This is probably not a very common situation, so currently +// I don't know how which compiler is right (JJ) +} + +void +tie_test() +{ + int a; + char b; + foo c(5); + + tie(a, b, c) = make_tuple(2, 'a', foo(3)); + BOOST_CHECK(a == 2); + BOOST_CHECK(b == 'a'); + BOOST_CHECK(c == foo(3)); + + tie(a, tuples::ignore, c) = make_tuple((short int)5, false, foo(5)); + BOOST_CHECK(a == 5); + BOOST_CHECK(b == 'a'); + BOOST_CHECK(c == foo(5)); + +// testing assignment from std::pair + int i, j; + tie (i, j) = std::make_pair(1, 2); + BOOST_CHECK(i == 1 && j == 2); + + tuple ta; +#ifdef E11 + ta = std::make_pair(1, 2); // should fail, tuple is of length 3, not 2 +#endif + + dummy(ta); +} + + +// ---------------------------------------------------------------------------- +// - testing tuple equality ------------------------------------------------- +// ---------------------------------------------------------------------------- + +void +equality_test() +{ + tuple t1(5, 'a'); + tuple t2(5, 'a'); + BOOST_CHECK(t1 == t2); + + tuple t3(5, 'b'); + tuple t4(2, 'a'); + BOOST_CHECK(t1 != t3); + BOOST_CHECK(t1 != t4); + BOOST_CHECK(!(t1 != t2)); +} + + +// ---------------------------------------------------------------------------- +// - testing tuple comparisons ----------------------------------------------- +// ---------------------------------------------------------------------------- + +void +ordering_test() +{ + tuple t1(4, 3.3f); + tuple t2(5, 3.3f); + tuple t3(5, 4.4); + BOOST_CHECK(t1 < t2); + BOOST_CHECK(t1 <= t2); + BOOST_CHECK(t2 > t1); + BOOST_CHECK(t2 >= t1); + BOOST_CHECK(t2 < t3); + BOOST_CHECK(t2 <= t3); + BOOST_CHECK(t3 > t2); + BOOST_CHECK(t3 >= t2); + +} + + +// ---------------------------------------------------------------------------- +// - testing cons lists ------------------------------------------------------- +// ---------------------------------------------------------------------------- +void cons_test() +{ + using tuples::cons; + using tuples::null_type; + + cons a(1, null_type()); + cons > b(2,a); + int i = 3; + cons > > c(i, b); + BOOST_CHECK(make_tuple(3,2,1)==c); + + cons > > x; + dummy(x); +} + +// ---------------------------------------------------------------------------- +// - testing const tuples ----------------------------------------------------- +// ---------------------------------------------------------------------------- +void const_tuple_test() +{ + const tuple t1(5, 3.25f); + BOOST_CHECK(get<0>(t1) == 5); + BOOST_CHECK(get<1>(t1) == 3.25f); +} + +// ---------------------------------------------------------------------------- +// - testing length ----------------------------------------------------------- +// ---------------------------------------------------------------------------- +void tuple_length_test() +{ + typedef tuple t1; + using tuples::cons; + typedef cons > > t1_cons; + typedef tuple<> t2; + typedef tuples::null_type t3; + + BOOST_STATIC_ASSERT(tuples::length::value == 3); + BOOST_STATIC_ASSERT(tuples::length::value == 3); + BOOST_STATIC_ASSERT(tuples::length::value == 0); + BOOST_STATIC_ASSERT(tuples::length::value == 0); + +} + +// ---------------------------------------------------------------------------- +// - testing swap ----------------------------------------------------------- +// ---------------------------------------------------------------------------- +void tuple_swap_test() +{ + tuple t1(1, 2.0f, 3.0), t2(4, 5.0f, 6.0); + swap(t1, t2); + BOOST_CHECK(get<0>(t1) == 4); + BOOST_CHECK(get<1>(t1) == 5.0f); + BOOST_CHECK(get<2>(t1) == 6.0); + BOOST_CHECK(get<0>(t2) == 1); + BOOST_CHECK(get<1>(t2) == 2.0f); + BOOST_CHECK(get<2>(t2) == 3.0); + + int i = 1,j = 2; + boost::tuple t3(i), t4(j); + swap(t3, t4); + BOOST_CHECK(i == 2); + BOOST_CHECK(j == 1); +} + + + +// ---------------------------------------------------------------------------- +// - main --------------------------------------------------------------------- +// ---------------------------------------------------------------------------- + +int main() { + + construction_test(); + element_access_test(); + copy_test(); + mutate_test(); + make_tuple_test(); + tie_test(); + equality_test(); + ordering_test(); + cons_test(); + const_tuple_test(); + tuple_length_test(); + tuple_swap_test(); + + return boost::report_errors(); +} diff --git a/libs/type_traits/test/check_type.hpp b/libs/type_traits/test/check_type.hpp new file mode 100644 index 00000000..8cbd385f --- /dev/null +++ b/libs/type_traits/test/check_type.hpp @@ -0,0 +1,76 @@ + +// (C) Copyright John Maddock 2000. +// Use, modification and distribution are subject to 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) + +#ifndef BOOST_CHECK_TYPE_HPP +#define BOOST_CHECK_TYPE_HPP + +#include "test.hpp" +#include + +/* +macro: +BOOST_CHECK_TYPE(type_expression, expected_type) + +type_expression: an expression that evaluates to a typename. +expected_value: the type we expect to find. +*/ + +#ifdef BOOST_BORLANDC +#pragma option -w-8008 -w-8066 -w-8019 +#endif + +#ifdef TEST_VIA_STATIC_ASSERT + +#define BOOST_CHECK_TYPE(type_expression, expected_type) static_assert(::boost::is_same< type_expression, expected_type >::value, BOOST_STRINGIZE(type_expression) " == " BOOST_STRINGIZE(expected_type)) + +#define BOOST_CHECK_TYPE3(type_expression, type_expression_suffix, expected_type) static_assert(::boost::is_same< type_expression, type_expression_suffix, expected_type >::value, BOOST_STRINGIZE(type_expression) "," BOOST_STRINGIZE(type_expression_suffix) " == " BOOST_STRINGIZE(expected_type)) + +#define BOOST_CHECK_TYPE4(type_expression, suffix1, suffix2, expected_type) static_assert(::boost::is_same< type_expression, suffix1, suffix2, expected_type >::value, BOOST_STRINGIZE(type_expression) "," BOOST_STRINGIZE(suffix1) "," BOOST_STRINGIZE(suffix2) " == " BOOST_STRINGIZE(expected_type)) + +#else + +#define BOOST_CHECK_TYPE(type_expression, expected_type)\ +do{\ + if(!::boost::is_same< type_expression, expected_type >::value){\ + BOOST_CHECK_MESSAGE(false, "The expression: \"" << BOOST_STRINGIZE(expression)\ + << "\" did not have the expected type:\n\tevaluating: boost::is_same<"\ + << BOOST_STRINGIZE(type_expression) << ", " << BOOST_STRINGIZE(expected_type)\ + << ">" << "\n\tfound: "\ + << typeid(::boost::is_same< type_expression, expected_type >).name());\ + }else\ + BOOST_CHECK_MESSAGE(true, "Validating Type Expression: \""\ + << BOOST_STRINGIZE(expression) << "\"");\ +}while(0) + +#define BOOST_CHECK_TYPE3(type_expression, type_expression_suffix, expected_type)\ +do{\ + if(!::boost::is_same< type_expression, type_expression_suffix, expected_type >::value){\ + BOOST_CHECK_MESSAGE(false, "The expression: \"" << BOOST_STRINGIZE(expression)\ + << "\" did not have the expected type:\n\tevaluating: boost::is_same<"\ + << BOOST_STRINGIZE((type_expression, type_expression_suffix)) << ", " << BOOST_STRINGIZE(expected_type)\ + << ">" << "\n\tfound: "\ + << typeid(::boost::is_same< type_expression, type_expression_suffix, expected_type >).name());\ + }else\ + BOOST_CHECK_MESSAGE(true, "Validating Type Expression: \""\ + << BOOST_STRINGIZE(expression) << "\"");\ +}while(0) + +#define BOOST_CHECK_TYPE4(type_expression, suffix1, suffix2, expected_type)\ +do{\ + if(!::boost::is_same< type_expression, suffix1, suffix2, expected_type >::value){\ + BOOST_CHECK_MESSAGE(false, "The expression: \"" << BOOST_STRINGIZE(expression)\ + << "\" did not have the expected type:\n\tevaluating: boost::is_same<"\ + << BOOST_STRINGIZE((type_expression, suffix1, suffix2)) << ", " << BOOST_STRINGIZE(expected_type)\ + << ">" << "\n\tfound: "\ + << typeid(::boost::is_same< type_expression, suffix1, suffix2, expected_type >).name());\ + }else\ + BOOST_CHECK_MESSAGE(true, "Validating Type Expression: \""\ + << BOOST_STRINGIZE(expression) << "\"");\ +}while(0) + +#endif + +#endif diff --git a/libs/type_traits/test/test.hpp b/libs/type_traits/test/test.hpp new file mode 100644 index 00000000..9dcbd355 --- /dev/null +++ b/libs/type_traits/test/test.hpp @@ -0,0 +1,494 @@ + +// (C) Copyright John Maddock 2000. +// Use, modification and distribution are subject to 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) + +#ifndef TT_TEST_HPP +#define TT_TEST_HPP + +#include +#include + +#if defined(_WIN32_WCE) && defined(BOOST_MSVC) +#pragma warning(disable:4201) +#endif + +#include +#include +#include + +#ifdef TEST_CUDA_DEVICE +#define TEST_VIA_STATIC_ASSERT +#endif + +#ifdef BOOST_BORLANDC +// we have to turn off these warnings otherwise we get swamped by the things: +#pragma option -w-8008 -w-8066 +#endif + +#ifdef _MSC_VER +// We have to turn off warnings that occur within the test suite: +#pragma warning(disable:4127) +#endif +#ifdef BOOST_INTEL +// remark #1418: external function definition with no prior declaration +// remark #981: operands are evaluated in unspecified order +#pragma warning(disable:1418 981) +#endif + +#ifdef BOOST_INTEL +// turn off warnings from this header: +#pragma warning(push) +#pragma warning(disable:444) +#endif + +// +// basic configuration: +// +#ifdef TEST_STD + +#define tt std::tr1 + +//#define TYPE_TRAITS(x) +//#define TYPE_COMPARE(x) +//#define TYPE_TRANSFORM(x) + +#else + +#define tt boost + +//#define TYPE_TRAITS(x) BOOST_STRINGIZE(boost/type_traits/x.hpp) +//#define TYPE_COMPARE(x) BOOST_STRINGIZE(boost/type_traits/x.hpp) +//#define TYPE_TRANSFORM(x) BOOST_STRINGIZE(boost/type_traits/x.hpp) + +#endif + +// +// replacements for Unit test macros: +// +int error_count = 0; + +#define BOOST_CHECK_MESSAGE(pred, message)\ + do{\ + if(!(pred))\ + {\ + std::cerr << __FILE__ << ":" << __LINE__ << ": " << message << std::endl;\ + ++error_count;\ + }\ + }while(0) + +#define BOOST_WARN_MESSAGE(pred, message)\ + do{\ + if(!(pred))\ + {\ + std::cerr << __FILE__ << ":" << __LINE__ << ": " << message << std::endl;\ + }\ + }while(0) + +#define BOOST_TEST_MESSAGE(message)\ + do{ std::cout << __FILE__ << ":" << __LINE__ << ": " << message << std::endl; }while(0) + +#ifdef TEST_CUDA_DEVICE +#define BOOST_CHECK(pred) pred +#else +#define BOOST_CHECK(pred)\ + do{ \ + if(!(pred)){\ + std::cout << __FILE__ << ":" << __LINE__ << ": Error in " << BOOST_STRINGIZE(pred) << std::endl;\ + ++error_count;\ + } \ + }while(0) +#endif + +#ifdef TEST_CUDA_DEVICE +#define TT_TEST_BEGIN(trait_name)\ + __global__ void test_proc(){ +#define TT_TEST_END } +#define BOOST_TT_PROC __device__ +#else +#define TT_TEST_BEGIN(trait_name)\ + int main(){ +#define TT_TEST_END return error_count; } +#define BOOST_TT_PROC +#endif + +#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !BOOST_WORKAROUND(BOOST_GCC, < 40704) + +#define TRANSFORM_CHECK_ALIASES(name, from_suffix, to_suffix)\ + BOOST_CHECK_TYPE(bool to_suffix, name##_t);\ + BOOST_CHECK_TYPE(char to_suffix, name##_t);\ + BOOST_CHECK_TYPE(wchar_t to_suffix, name##_t);\ + BOOST_CHECK_TYPE(signed char to_suffix, name##_t);\ + BOOST_CHECK_TYPE(unsigned char to_suffix, name##_t);\ + BOOST_CHECK_TYPE(short to_suffix, name##_t);\ + BOOST_CHECK_TYPE(unsigned short to_suffix, name##_t);\ + BOOST_CHECK_TYPE(int to_suffix, name##_t);\ + BOOST_CHECK_TYPE(unsigned int to_suffix, name##_t);\ + BOOST_CHECK_TYPE(long to_suffix, name##_t);\ + BOOST_CHECK_TYPE(unsigned long to_suffix, name##_t);\ + BOOST_CHECK_TYPE(float to_suffix, name##_t);\ + BOOST_CHECK_TYPE(long double to_suffix, name##_t);\ + BOOST_CHECK_TYPE(double to_suffix, name##_t);\ + BOOST_CHECK_TYPE(UDT to_suffix, name##_t);\ + BOOST_CHECK_TYPE(enum1 to_suffix, name##_t); + +#else + +#define TRANSFORM_CHECK_ALIASES(name, from_suffix, to_suffix) /**/ + +#endif + +#define TRANSFORM_CHECK(name, from_suffix, to_suffix)\ + TRANSFORM_CHECK_ALIASES(name, from_suffix, to_suffix)\ + BOOST_CHECK_TYPE(bool to_suffix, name::type);\ + BOOST_CHECK_TYPE(char to_suffix, name::type);\ + BOOST_CHECK_TYPE(wchar_t to_suffix, name::type);\ + BOOST_CHECK_TYPE(signed char to_suffix, name::type);\ + BOOST_CHECK_TYPE(unsigned char to_suffix, name::type);\ + BOOST_CHECK_TYPE(short to_suffix, name::type);\ + BOOST_CHECK_TYPE(unsigned short to_suffix, name::type);\ + BOOST_CHECK_TYPE(int to_suffix, name::type);\ + BOOST_CHECK_TYPE(unsigned int to_suffix, name::type);\ + BOOST_CHECK_TYPE(long to_suffix, name::type);\ + BOOST_CHECK_TYPE(unsigned long to_suffix, name::type);\ + BOOST_CHECK_TYPE(float to_suffix, name::type);\ + BOOST_CHECK_TYPE(long double to_suffix, name::type);\ + BOOST_CHECK_TYPE(double to_suffix, name::type);\ + BOOST_CHECK_TYPE(UDT to_suffix, name::type);\ + BOOST_CHECK_TYPE(enum1 to_suffix, name::type); + +#define BOOST_DUMMY_MACRO_PARAM /**/ + +#define BOOST_DECL_TRANSFORM_TEST(name, type, from, to)\ +BOOST_TT_PROC void name(){ TRANSFORM_CHECK(type, from, to) } +#define BOOST_DECL_TRANSFORM_TEST3(name, type, from)\ +BOOST_TT_PROC void name(){ TRANSFORM_CHECK(type, from, BOOST_DUMMY_MACRO_PARAM) } +#define BOOST_DECL_TRANSFORM_TEST2(name, type, to)\ +BOOST_TT_PROC void name(){ TRANSFORM_CHECK(type, BOOST_DUMMY_MACRO_PARAM, to) } +#define BOOST_DECL_TRANSFORM_TEST0(name, type)\ +BOOST_TT_PROC void name(){ TRANSFORM_CHECK(type, BOOST_DUMMY_MACRO_PARAM, BOOST_DUMMY_MACRO_PARAM) } + + + +// +// VC++ emits an awful lot of warnings unless we define these: +#ifdef BOOST_MSVC +# pragma warning(disable:4800) +#endif + +// +// define some test types: +// +enum enum_UDT{ one, two, three }; +struct UDT +{ + UDT(); + ~UDT(); + UDT(const UDT&); + UDT& operator=(const UDT&); + int i; + + void f1(); + int f2(); + int f3(int); + int f4(int, float); +#ifdef __cpp_noexcept_function_type + void f5()noexcept; + int f6(int)noexcept(true); + double f7()noexcept(false); +#endif +}; + +typedef void(*f1)(); +typedef int(*f2)(int); +typedef int(*f3)(int, bool); +typedef void (UDT::*mf1)(); +typedef int (UDT::*mf2)(); +typedef int (UDT::*mf3)(int); +typedef int (UDT::*mf4)(int, float); +typedef int (UDT::*mp); +typedef int (UDT::*cmf)(int) const; +#ifdef __cpp_noexcept_function_type +typedef void (UDT::*mf5)()noexcept; +typedef int (UDT::*mf6)(int)noexcept; +typedef double (UDT::*mf7)()noexcept; +#endif +typedef int (UDT::*mf8)(...); + +// cv-qualifiers applied to reference types should have no effect +// declare these here for later use with is_reference and remove_reference: +# ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable: 4181) +# elif defined(BOOST_INTEL) +# pragma warning(push) +# pragma warning(disable: 21) +# elif defined(BOOST_CLANG) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wignored-qualifiers" +# endif +// +// This is intentional: +// r_type and cr_type should be the same type +// but some compilers wrongly apply cv-qualifiers +// to reference types (this may generate a warning +// on some compilers): +// +typedef int& r_type; +#ifndef BOOST_INTEL +typedef const r_type cr_type; +#else +// recent Intel compilers generate a hard error on the above: +typedef r_type cr_type; +#endif +# ifdef BOOST_MSVC +# pragma warning(pop) +# elif defined(BOOST_INTEL) +# pragma warning(pop) +# pragma warning(disable: 985) // identifier truncated in debug information +# elif defined(BOOST_CLANG) +# pragma clang diagnostic pop +# endif + +struct POD_UDT { int x; }; +struct empty_UDT +{ + empty_UDT(); + empty_UDT(const empty_UDT&); + ~empty_UDT(); + empty_UDT& operator=(const empty_UDT&); + bool operator==(const empty_UDT&)const; +}; +struct empty_POD_UDT +{ + bool operator==(const empty_POD_UDT&)const + { return true; } +}; +union union_UDT +{ + int x; + double y; + ~union_UDT(){} +}; +union POD_union_UDT +{ + int x; + double y; +}; +union empty_union_UDT +{ + ~empty_union_UDT(){} +}; +union empty_POD_union_UDT{}; + +struct nothrow_copy_UDT +{ + nothrow_copy_UDT(); + nothrow_copy_UDT(const nothrow_copy_UDT&)throw(); + ~nothrow_copy_UDT(){} + nothrow_copy_UDT& operator=(const nothrow_copy_UDT&); + bool operator==(const nothrow_copy_UDT&)const + { return true; } +}; + +struct nothrow_assign_UDT +{ + nothrow_assign_UDT(); + nothrow_assign_UDT(const nothrow_assign_UDT&); + ~nothrow_assign_UDT(){}; + nothrow_assign_UDT& operator=(const nothrow_assign_UDT&)throw(){ return *this; } + bool operator==(const nothrow_assign_UDT&)const + { return true; } +}; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +struct nothrow_move_UDT +{ + nothrow_move_UDT(); + nothrow_move_UDT(nothrow_move_UDT&&) throw(); + nothrow_move_UDT& operator=(nothrow_move_UDT&&) throw(); + bool operator==(const nothrow_move_UDT&)const + { return true; } +}; +#endif + + +struct nothrow_construct_UDT +{ + nothrow_construct_UDT()throw(); + nothrow_construct_UDT(const nothrow_construct_UDT&); + ~nothrow_construct_UDT(){}; + nothrow_construct_UDT& operator=(const nothrow_construct_UDT&){ return *this; } + bool operator==(const nothrow_construct_UDT&)const + { return true; } +}; + +class Base { }; + +class Derived : public Base { }; +class Derived2 : public Base { }; +class MultiBase : public Derived, public Derived2 {}; +class PrivateBase : private Base {}; + +class NonDerived { }; + +enum enum1 +{ + one_,two_ +}; + +enum enum2 +{ + three_,four_ +}; + +#ifndef BOOST_NO_CXX11_SCOPED_ENUMS + +enum class scoped_enum { one, two, three }; + +#endif + +struct VB +{ + virtual ~VB(){}; +}; + +struct VD : public VB +{ + ~VD(){}; +}; +// +// struct non_pointer: +// used to verify that is_pointer does not return +// true for class types that implement operator void*() +// +struct non_pointer +{ + operator void*(){return this;} +}; +struct non_int_pointer +{ + int i; + operator int*(){return &i;} +}; +struct int_constructible +{ + int_constructible(int); +}; +struct int_convertible +{ + operator int(); +}; +// +// struct non_empty: +// used to verify that is_empty does not emit +// spurious warnings or errors. +// +struct non_empty : private boost::noncopyable +{ + int i; +}; +// +// abstract base classes: +struct test_abc1 +{ + test_abc1(); + virtual ~test_abc1(); + test_abc1(const test_abc1&); + test_abc1& operator=(const test_abc1&); + virtual void foo() = 0; + virtual void foo2() = 0; +}; + +struct test_abc2 +{ + virtual ~test_abc2(); + virtual void foo() = 0; + virtual void foo2() = 0; +}; + +struct test_abc3 : public test_abc1 +{ + virtual void foo3() = 0; +}; + +struct incomplete_type; + +struct polymorphic_base +{ + virtual ~polymorphic_base(); + virtual void method(); +}; + +struct polymorphic_derived1 : public polymorphic_base +{ +}; + +struct polymorphic_derived2 : public polymorphic_base +{ + virtual void method(); +}; + +#ifndef BOOST_NO_CXX11_FINAL +struct final_UDT final +{}; +struct polymorphic_derived_final final : public polymorphic_derived2 +{}; +#endif + + +struct virtual_inherit1 : public virtual Base { }; +struct virtual_inherit2 : public virtual_inherit1 { }; +struct virtual_inherit3 : private virtual Base {}; +struct virtual_inherit4 : public virtual boost::noncopyable {}; +struct virtual_inherit5 : public virtual int_convertible {}; +struct virtual_inherit6 : public virtual Base { virtual ~virtual_inherit6()throw(); }; + +typedef void foo0_t(); +typedef void foo1_t(int); +typedef void foo2_t(int&, double); +typedef void foo3_t(int&, bool, int, int); +typedef void foo4_t(int, bool, int*, int[], int, int, int, int, int); + +struct trivial_except_construct +{ + trivial_except_construct(); + int i; +}; + +struct trivial_except_destroy +{ + ~trivial_except_destroy(); + int i; +}; + +struct trivial_except_copy +{ + trivial_except_copy(trivial_except_copy const&); + int i; +}; + +struct trivial_except_assign +{ + trivial_except_assign& operator=(trivial_except_assign const&); + int i; +}; + +template +struct wrap +{ + T t; + int j; +protected: + wrap(); + wrap(const wrap&); + wrap& operator=(const wrap&); +}; + +#ifdef BOOST_INTEL +#pragma warning(pop) +#endif + +#endif + diff --git a/libs/utility/.gitattributes b/libs/utility/.gitattributes new file mode 100644 index 00000000..3e84d7c7 --- /dev/null +++ b/libs/utility/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain diff --git a/libs/utility/.github/workflows/ci.yml b/libs/utility/.github/workflows/ci.yml new file mode 100644 index 00000000..4427512b --- /dev/null +++ b/libs/utility/.github/workflows/ci.yml @@ -0,0 +1,470 @@ +# Copyright 2021-2022 Andrey Semashev +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +name: CI + +on: + pull_request: + push: + branches: + - master + - develop + - feature/** + +concurrency: + group: ${{format('{0}:{1}', github.repository, github.ref)}} + cancel-in-progress: true + +env: + GIT_FETCH_JOBS: 8 + NET_RETRY_COUNT: 5 + DEFAULT_BUILD_VARIANT: debug,release + +jobs: + posix: + defaults: + run: + shell: bash + + strategy: + fail-fast: false + matrix: + include: + # Linux, gcc + - toolset: gcc-4.7 + cxxstd: "11" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - g++-4.7 + - toolset: gcc-4.8 + cxxstd: "11" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - g++-4.8 + - toolset: gcc-4.9 + cxxstd: "11" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - g++-4.9 + - toolset: gcc-5 + cxxstd: "11,14,1z" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - g++-5 + - toolset: gcc-6 + cxxstd: "11,14,1z" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - g++-6 + - toolset: gcc-7 + cxxstd: "11,14,17" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - g++-7 + - toolset: gcc-8 + cxxstd: "11,14,17,2a" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - g++-8 + - toolset: gcc-9 + cxxstd: "11,14,17,2a" + os: ubuntu-20.04 + install: + - g++-9 + - toolset: gcc-10 + cxxstd: "11,14,17,20" + os: ubuntu-20.04 + install: + - g++-10 + - toolset: gcc-11 + cxxstd: "11,14,17,20,23" + os: ubuntu-22.04 + install: + - g++-11 + - toolset: gcc-12 + cxxstd: "11,14,17,20,23" + os: ubuntu-22.04 + install: + - g++-12 + - name: UBSAN + toolset: gcc-11 + cxxstd: "11,14,17,20,23" + ubsan: 1 + build_variant: debug + os: ubuntu-22.04 + install: + - g++-11 + + # Linux, clang + - toolset: clang + compiler: clang++-3.5 + cxxstd: "11" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - clang-3.5 + - toolset: clang + compiler: clang++-3.6 + cxxstd: "11,14" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - clang-3.6 + - toolset: clang + compiler: clang++-3.7 + cxxstd: "11,14" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - clang-3.7 + - toolset: clang + compiler: clang++-3.8 + cxxstd: "11,14" + os: ubuntu-latest + container: ubuntu:16.04 + install: + - clang-3.8 + - toolset: clang + compiler: clang++-3.9 + cxxstd: "11,14" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-3.9 + - toolset: clang + compiler: clang++-4.0 + cxxstd: "11,14" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-4.0 + - toolset: clang + compiler: clang++-5.0 + cxxstd: "11,14,1z" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-5.0 + - toolset: clang + compiler: clang++-6.0 + cxxstd: "11,14,17" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-6.0 + - toolset: clang + compiler: clang++-7 + cxxstd: "11,14,17" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-7 + # Note: clang-8 does not fully support C++20, so it is not compatible with libstdc++-8 in this mode + - toolset: clang + compiler: clang++-8 + cxxstd: "11,14,17,2a" + os: ubuntu-latest + container: ubuntu:18.04 + install: + - clang-8 + - g++-7 + gcc_toolchain: 7 + - toolset: clang + compiler: clang++-9 + cxxstd: "11,14,17,2a" + os: ubuntu-20.04 + install: + - clang-9 + - toolset: clang + compiler: clang++-10 + cxxstd: "11,14,17,20" + os: ubuntu-20.04 + install: + - clang-10 + - toolset: clang + compiler: clang++-11 + cxxstd: "11,14,17,20" + os: ubuntu-22.04 + install: + - clang-11 + - toolset: clang + compiler: clang++-12 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-12 + - g++-11 + gcc_toolchain: 11 + - toolset: clang + compiler: clang++-13 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-13 + - g++-11 + gcc_toolchain: 11 + - toolset: clang + compiler: clang++-14 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-14 + - g++-11 + gcc_toolchain: 11 + - toolset: clang + compiler: clang++-15 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-15 + - g++-11 + gcc_toolchain: 11 + - toolset: clang + compiler: clang++-16 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-16 + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + - toolset: clang + compiler: clang++-16 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: + - clang-16 + - libc++-16-dev + - libc++abi-16-dev + sources: + - "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main" + source_keys: + - "https://apt.llvm.org/llvm-snapshot.gpg.key" + cxxflags: -stdlib=libc++ + linkflags: -stdlib=libc++ + - name: UBSAN + toolset: clang + compiler: clang++-15 + cxxstd: "11,14,17,20,2b" + cxxflags: -stdlib=libc++ + linkflags: -stdlib=libc++ + ubsan: 1 + build_variant: debug + os: ubuntu-22.04 + install: + - clang-15 + - libc++-15-dev + - libc++abi-15-dev + + - toolset: clang + cxxstd: "11,14,17,2a" + os: macos-11 + + timeout-minutes: 60 + runs-on: ${{matrix.os}} + container: ${{matrix.container}} + + steps: + - name: Setup environment + run: | + if [ -f "/etc/debian_version" ] + then + echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV + export DEBIAN_FRONTEND=noninteractive + fi + if [ -n "${{matrix.container}}" ] + then + echo "GHA_CONTAINER=${{matrix.container}}" >> $GITHUB_ENV + if [ -f "/etc/debian_version" ] + then + apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + if [ "$(apt-cache search "^python-is-python3$" | wc -l)" -ne 0 ] + then + PYTHON_PACKAGE="python-is-python3" + else + PYTHON_PACKAGE="python" + fi + apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common tzdata wget curl apt-transport-https ca-certificates make build-essential g++ $PYTHON_PACKAGE python3 perl git cmake + fi + fi + git config --global pack.threads 0 + + - uses: actions/checkout@v3 + + - name: Install packages + if: matrix.install + run: | + declare -a SOURCE_KEYS SOURCES + if [ -n "${{join(matrix.source_keys, ' ')}}" ] + then + SOURCE_KEYS=("${{join(matrix.source_keys, '" "')}}") + fi + if [ -n "${{join(matrix.sources, ' ')}}" ] + then + SOURCES=("${{join(matrix.sources, '" "')}}") + fi + for key in "${SOURCE_KEYS[@]}" + do + for i in {1..$NET_RETRY_COUNT} + do + echo "Adding key: $key" + wget -O - "$key" | sudo apt-key add - && break || sleep 2 + done + done + if [ ${#SOURCES[@]} -gt 0 ] + then + APT_ADD_REPO_COMMON_ARGS=("-y") + APT_ADD_REPO_SUPPORTED_ARGS="$(apt-add-repository --help | perl -ne 'if (/^\s*-n/) { print "n"; } elsif (/^\s*-P/) { print "P"; } elsif (/^\s*-S/) { print "S"; } elsif (/^\s*-U/) { print "U"; }')" + if [ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*n*}" ] + then + APT_ADD_REPO_COMMON_ARGS+=("-n") + fi + APT_ADD_REPO_HAS_SOURCE_ARGS="$([ -n "$APT_ADD_REPO_SUPPORTED_ARGS" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*P*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*S*}" -a -z "${APT_ADD_REPO_SUPPORTED_ARGS##*U*}" ] && echo 1 || echo 0)" + for source in "${SOURCES[@]}" + do + for i in {1..$NET_RETRY_COUNT} + do + APT_ADD_REPO_ARGS=("${APT_ADD_REPO_COMMON_ARGS[@]}") + if [ $APT_ADD_REPO_HAS_SOURCE_ARGS -ne 0 ] + then + case "$source" in + "ppa:"*) + APT_ADD_REPO_ARGS+=("-P") + ;; + "deb "*) + APT_ADD_REPO_ARGS+=("-S") + ;; + *) + APT_ADD_REPO_ARGS+=("-U") + ;; + esac + fi + APT_ADD_REPO_ARGS+=("$source") + echo "apt-add-repository ${APT_ADD_REPO_ARGS[@]}" + sudo -E apt-add-repository "${APT_ADD_REPO_ARGS[@]}" && break || sleep 2 + done + done + fi + sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update + sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y ${{join(matrix.install, ' ')}} + + - name: Setup GCC Toolchain + if: matrix.gcc_toolchain + run: | + GCC_TOOLCHAIN_ROOT="$HOME/gcc-toolchain" + echo "GCC_TOOLCHAIN_ROOT=\"$GCC_TOOLCHAIN_ROOT\"" >> $GITHUB_ENV + MULTIARCH_TRIPLET="$(dpkg-architecture -qDEB_HOST_MULTIARCH)" + mkdir -p "$GCC_TOOLCHAIN_ROOT" + ln -s /usr/include "$GCC_TOOLCHAIN_ROOT/include" + ln -s /usr/bin "$GCC_TOOLCHAIN_ROOT/bin" + mkdir -p "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET" + ln -s "/usr/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" + + - name: Setup Boost + run: | + echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY + LIBRARY=${GITHUB_REPOSITORY#*/} + echo LIBRARY: $LIBRARY + echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV + echo GITHUB_BASE_REF: $GITHUB_BASE_REF + echo GITHUB_REF: $GITHUB_REF + REF=${GITHUB_BASE_REF:-$GITHUB_REF} + REF=${REF#refs/heads/} + echo REF: $REF + BOOST_BRANCH=develop && [ "$REF" = "master" ] && BOOST_BRANCH=master || true + echo BOOST_BRANCH: $BOOST_BRANCH + BUILD_JOBS=$((nproc || sysctl -n hw.ncpu) 2> /dev/null) + echo "BUILD_JOBS=$BUILD_JOBS" >> $GITHUB_ENV + echo "CMAKE_BUILD_PARALLEL_LEVEL=$BUILD_JOBS" >> $GITHUB_ENV + DEPINST_ARGS=() + GIT_VERSION="$(git --version | sed -e 's/git version //')" + GIT_HAS_JOBS=1 + if [ -f "/etc/debian_version" ] + then + if $(dpkg --compare-versions "$GIT_VERSION" lt 2.8.0) + then + GIT_HAS_JOBS=0 + fi + else + declare -a GIT_VER=(${GIT_VERSION//./ }) + declare -a GIT_MIN_VER=(2 8 0) + for ((i=0; i<${#GIT_VER[@]}; i++)) + do + if [ -z "${GIT_MIN_VER[i]}" ] + then + GIT_MIN_VER[i]=0 + fi + if [ "${GIT_VER[i]}" -lt "${GIT_MIN_VER[i]}" ] + then + GIT_HAS_JOBS=0 + break + fi + done + fi + if [ "$GIT_HAS_JOBS" -ne 0 ] + then + DEPINST_ARGS+=("--git_args" "--jobs $GIT_FETCH_JOBS") + fi + cd .. + git clone -b "$BOOST_BRANCH" --depth 1 "https://github.com/boostorg/boost.git" "boost-root" + cd boost-root + mkdir -p libs/$LIBRARY + cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY + git submodule update --init tools/boostdep + DEPINST_ARGS+=("$LIBRARY") + python tools/boostdep/depinst/depinst.py "${DEPINST_ARGS[@]}" + if [ -z "${{matrix.cmake_tests}}" ] + then + ./bootstrap.sh + ./b2 headers + if [ -n "${{matrix.compiler}}" -o -n "$GCC_TOOLCHAIN_ROOT" ] + then + echo -n "using ${{matrix.toolset}} : : ${{matrix.compiler}}" > ~/user-config.jam + if [ -n "$GCC_TOOLCHAIN_ROOT" ] + then + echo -n " : \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\" \"--gcc-toolchain=$GCC_TOOLCHAIN_ROOT\"" >> ~/user-config.jam + fi + echo " ;" >> ~/user-config.jam + fi + fi + + - name: Run tests + if: matrix.cmake_tests == '' + run: | + cd ../boost-root + B2_ARGS=("-j" "$BUILD_JOBS" "toolset=${{matrix.toolset}}" "cxxstd=${{matrix.cxxstd}}") + if [ -n "${{matrix.build_variant}}" ] + then + B2_ARGS+=("variant=${{matrix.build_variant}}") + else + B2_ARGS+=("variant=$DEFAULT_BUILD_VARIANT") + fi + if [ -n "${{matrix.threading}}" ] + then + B2_ARGS+=("threading=${{matrix.threading}}") + fi + if [ -n "${{matrix.ubsan}}" ] + then + export UBSAN_OPTIONS="print_stacktrace=1" + B2_ARGS+=("cxxflags=-fsanitize=undefined -fno-sanitize-recover=undefined" "linkflags=-fsanitize=undefined -fuse-ld=gold" "define=UBSAN=1" "debug-symbols=on" "visibility=global") + fi + if [ -n "${{matrix.cxxflags}}" ] + then + B2_ARGS+=("cxxflags=${{matrix.cxxflags}}") + fi + if [ -n "${{matrix.linkflags}}" ] + then + B2_ARGS+=("linkflags=${{matrix.linkflags}}") + fi + B2_ARGS+=("libs/$LIBRARY/test") + ./b2 "${B2_ARGS[@]}" diff --git a/libs/utility/Assignable.html b/libs/utility/Assignable.html new file mode 100644 index 00000000..d3b31576 --- /dev/null +++ b/libs/utility/Assignable.html @@ -0,0 +1,109 @@ + + + + + + + + Assignable + + + + C++ Boost
+ +

Assignable

+ +

Description

+ +

A type is Assignable if it is possible to assign one object of the type + to another object of that type.

+ +

Notation

+ + + + + + + + + + + + + + + + + + + +
Tis type that is a model of Assignable
tis an object of type T
uis an object of type T or possibly const + T
+ +

Definitions

+ +

Valid expressions

+ + + + + + + + + + + + + + + + + + + + + +
NameExpressionReturn typeSemantics
Assignmentt = uT&t is equivalent to u
+ +

Models

+ +
    +
  • int
  • + +
  • std::pair
  • +
+ +

See also

+ +

DefaultConstructible + and CopyConstructible

+
+ +

Valid HTML 4.01 Transitional

+ +

Revised + 05 December, 2006

+ + + + + + + +
Copyright © 2000Jeremy Siek, Univ.of + Notre Dame (jsiek@lsc.nd.edu)
+ +

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/libs/utility/CMakeLists.txt b/libs/utility/CMakeLists.txt new file mode 100644 index 00000000..5fc33a19 --- /dev/null +++ b/libs/utility/CMakeLists.txt @@ -0,0 +1,24 @@ +# Copyright 2018 Peter Dimov +# Copyright 2018 Andrey Semashev +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.5...3.20) + +project(boost_utility VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) + +add_library(boost_utility INTERFACE) +add_library(Boost::utility ALIAS boost_utility) + +target_include_directories(boost_utility INTERFACE include) + +target_link_libraries(boost_utility + INTERFACE + Boost::config + Boost::core + Boost::io + Boost::preprocessor + Boost::static_assert + Boost::throw_exception + Boost::type_traits +) diff --git a/libs/utility/Collection.html b/libs/utility/Collection.html new file mode 100644 index 00000000..b92ddd6e --- /dev/null +++ b/libs/utility/Collection.html @@ -0,0 +1,534 @@ + + + + + + + + Collection + + + +

boost logo
+ Collection

+ +

Description

+ +

A Collection is a concept similar to the STL Container concept. A + Collection provides iterators for accessing a range of elements and + provides information about the number of elements in the Collection. + However, a Collection has fewer requirements than a Container. The + motivation for the Collection concept is that there are many useful + Container-like types that do not meet the full requirements of Container, + and many algorithms that can be written with this reduced set of + requirements. To summarize the reduction in requirements:

+ +
    +
  • It is not required to "own" its elements: the lifetime of an element + in a Collection does not have to match the lifetime of the Collection + object, though the lifetime of the element should cover the lifetime of + the Collection object.
  • + +
  • The semantics of copying a Collection object is not defined (it could + be a deep or shallow copy or not even support copying).
  • + +
  • The associated reference type of a Collection does not have to be a + real C++ reference.
  • +
Because of the reduced requirements, some care must be taken when + writing code that is meant to be generic for all Collection types. In + particular, a Collection object should be passed by-reference since + assumptions can not be made about the behaviour of the copy constructor. + +

Associated types

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Value typeX::value_typeThe type of the object stored in a Collection. If the + Collection is mutable then the value type must be Assignable. Otherwise + the value type must be CopyConstructible.
Iterator typeX::iteratorThe type of iterator used to iterate through a + Collection's elements. The iterator's value type is expected to be the + Collection's value type. A conversion from the iterator type to the + const iterator type must exist. The iterator type must be an InputIterator.
Const iterator typeX::const_iteratorA type of iterator that may be used to examine, but + not to modify, a Collection's elements.
Reference typeX::referenceA type that behaves like a reference to the + Collection's value type. [1]
Const reference typeX::const_referenceA type that behaves like a const reference to the + Collection's value type.
Pointer typeX::pointerA type that behaves as a pointer to the Collection's + value type.
Distance typeX::difference_typeA signed integral type used to represent the distance + between two of the Collection's iterators. This type must be the same + as the iterator's distance type.
Size typeX::size_typeAn unsigned integral type that can represent any + nonnegative value of the Collection's distance type.
+ +

Notation

+ + + + + + + + + + + + + + + + + + + +
XA type that is a model of Collection.
a, bObject of type X.
TThe value type of X.
+ +

Valid expressions

+ +

The following expressions must be valid.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameExpressionReturn type
Beginning of rangea.begin()iterator if a is mutable, + const_iterator otherwise
End of rangea.end()iterator if a is mutable, + const_iterator otherwise
Sizea.size()size_type
Empty Collectiona.empty()Convertible to bool
Swapa.swap(b)void
+ +

Expression semantics

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameExpressionSemanticsPostcondition
Beginning of rangea.begin()Returns an iterator pointing to the first element in + the Collection.a.begin() is either dereferenceable or + past-the-end. It is past-the-end if and only if a.size() == + 0.
End of rangea.end()Returns an iterator pointing one past the last element + in the Collection.a.end() is past-the-end.
Sizea.size()Returns the size of the Collection, that is, its + number of elements.a.size() >= 0
Empty Collectiona.empty()Equivalent to a.size() == 0. (But possibly + faster.) 
Swapa.swap(b)Equivalent to swap(a,b) 
+ +

Complexity guarantees

+ +

begin() and end() are amortized constant time.

+ +

size() is at most linear in the Collection's size. + empty() is amortized constant time.

+ +

swap() is at most linear in the size of the two + collections.

+ +

Invariants

+ + + + + + + + + + + + + + + + + + + +
Valid rangeFor any Collection a, [a.begin(), + a.end()) is a valid range.
Range sizea.size() is equal to the distance from + a.begin() to a.end().
CompletenessAn algorithm that iterates through the range + [a.begin(), a.end()) will pass through every element of + a.
+ +

Models

+ +
    +
  • array
  • + +
  • array_ptr
  • + +
  • vector<bool>
  • +
+ +

Collection Refinements

+ +

There are quite a few concepts that refine the Collection concept, + similar to the concepts that refine the Container concept. Here is a brief + overview of the refining concepts.

+ +

ForwardCollection

+ +

The elements are arranged in some order that does not change + spontaneously from one iteration to the next. As a result, a + ForwardCollection is EqualityComparable + and LessThanComparable. + In addition, the iterator type of a ForwardCollection is a + MultiPassInputIterator which is just an InputIterator with the added + requirements that the iterator can be used to make multiple passes through + a range, and that if it1 == it2 and it1 is + dereferenceable then ++it1 == ++it2. The ForwardCollection also + has a front() method.

+ + + + + + + + + + + + + + + + + + + + + +
NameExpressionReturn typeSemantics
Fronta.front()reference if a is mutable,
+ const_reference otherwise.
Equivalent to *(a.begin()).
+ +

ReversibleCollection

+ +

The container provides access to iterators that traverse in both + directions (forward and reverse). The iterator type must meet all of the + requirements of BidirectionalIterator + except that the reference type does not have to be a real C++ reference. + The ReversibleCollection adds the following requirements to those of + ForwardCollection.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameExpressionReturn typeSemantics
Beginning of rangea.rbegin()reverse_iterator if a is mutable, + const_reverse_iterator otherwise.Equivalent to + X::reverse_iterator(a.end()).
End of rangea.rend()reverse_iterator if a is mutable, + const_reverse_iterator otherwise.Equivalent to + X::reverse_iterator(a.begin()).
Backa.back()reference if a is mutable,
+ const_reference otherwise.
Equivalent to *(--a.end()).
+ +

SequentialCollection

+ +

The elements are arranged in a strict linear order. No extra methods are + required.

+ +

RandomAccessCollection

+ +

The iterators of a RandomAccessCollection satisfy all of the + requirements of RandomAccessIterator + except that the reference type does not have to be a real C++ reference. In + addition, a RandomAccessCollection provides an element access operator.

+ + + + + + + + + + + + + + + + + + + + + +
NameExpressionReturn typeSemantics
Element Accessa[n]reference if a is mutable, + const_reference otherwise.Returns the nth element of the Collection. n + must be convertible to size_type. Precondition: 0 <= n + < a.size().
+ +

Notes

+ +

[1] The reference type does not have to be a + real C++ reference. The requirements of the reference type depend on the + context within which the Collection is being used. Specifically it depends + on the requirements the context places on the value type of the Collection. + The reference type of the Collection must meet the same requirements as the + value type. In addition, the reference objects must be equivalent to the + value type objects in the collection (which is trivially true if they are + the same object). Also, in a mutable Collection, an assignment to the + reference object must result in an assignment to the object in the + Collection (again, which is trivially true if they are the same object, but + non-trivial if the reference type is a proxy class).

+ +

See also

+ +

Container

+
+ +

Valid HTML 4.01 Transitional

+ +

Revised + 05 + December, 2006

+ + + + + + + +
Copyright © 2000Jeremy + Siek, Univ.of Notre Dame and C++ Library & Compiler Group/SGI + (jsiek@engr.sgi.com)
+ +

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/libs/utility/CopyConstructible.html b/libs/utility/CopyConstructible.html new file mode 100644 index 00000000..6a7ce655 --- /dev/null +++ b/libs/utility/CopyConstructible.html @@ -0,0 +1,185 @@ + + + + + + + + Copy Constructible + + + + C++ Boost
+ +

Copy Constructible

+ +

Description

+ +

A type is Copy Constructible if it is possible to copy objects of that + type.

+ +

Notation

+ + + + + + + + + + + + + + + + + + + +
Tis type that is a model of Copy Constructible
tis an object of type T
uis an object of type const T
+ +

Definitions

+ +

Valid expressions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameExpressionReturn typeSemantics
Copy constructorT(t)Tt is equivalent to T(t)
Copy constructor +
+T(u)
+
+
Tu is equivalent to T(u)
Destructor +
+t.~T()
+
+
T 
Address Operator +
+&t
+
+
T*denotes the address of t
Address Operator +
+&u
+
+
T*denotes the address of u
+ +

Models

+ +
    +
  • int
  • + +
  • std::pair
  • +
+ +

Concept Checking Class

+
+  template <class T>
+  struct CopyConstructibleConcept
+  {
+    void constraints() {
+      T a(b);            // require copy constructor
+      T* ptr = &a;       // require address of operator
+      const_constraints(a);
+      ignore_unused_variable_warning(ptr);
+    }
+    void const_constraints(const T& a) {
+      T c(a);            // require const copy constructor
+      const T* ptr = &a; // require const address of operator
+      ignore_unused_variable_warning(c);
+      ignore_unused_variable_warning(ptr);
+    }
+    T b;
+  };
+
+ +

See also

+ +

Default + Constructible and Assignable

+
+ +

Valid HTML 4.01 Transitional

+ +

Revised + 05 + December, 2006

+ + + + + + + +
Copyright © 2000Jeremy Siek, Univ.of + Notre Dame (jsiek@lsc.nd.edu)
+ +

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/libs/utility/LessThanComparable.html b/libs/utility/LessThanComparable.html new file mode 100644 index 00000000..15b938fc --- /dev/null +++ b/libs/utility/LessThanComparable.html @@ -0,0 +1,210 @@ + + + + + + + + + + LessThanComparable + + + + C++ Boost
+ +

LessThanComparable

+ +

Description

+ +

A type is LessThanComparable if it is ordered: it must be possible to + compare two objects of that type using operator<, and + operator< must be a strict weak ordering relation.

+ +

Refinement of

+ +

Associated types

+ +

Notation

+ + + + + + + + + + + + + +
XA type that is a model of LessThanComparable
x, y, zObject of type X
+ +

Definitions

+ +

Consider the relation !(x < y) && !(y < x). If + this relation is transitive (that is, if !(x < y) && !(y + < x) && !(y < z) && !(z < y) implies !(x + < z) && !(z < x)), then it satisfies the mathematical + definition of an equivalence relation. In this case, operator< + is a strict weak ordering.

+ +

If operator< is a strict weak ordering, and if each + equivalence class has only a single element, then operator< is + a total ordering.

+ +

Valid expressions

+ + + + + + + + + + + + + + + + + + + + + +
NameExpressionType requirementsReturn type
Lessx < y Convertible to bool
+ +

Expression semantics

+ + + + + + + + + + + + + + + + + + + + + + + +
NameExpressionPreconditionSemanticsPostcondition
Lessx < yx and y are in the domain of + < 
+ +

Complexity guarantees

+ +

Invariants

+ + + + + + + + + + + + + + + + + + + +
Irreflexivityx < x must be false.
Antisymmetryx < y implies !(y < x) [2]
Transitivityx < y and y < z implies x + < z [3]
+ +

Models

+ +
    +
  • int
  • +
+ +

Notes

+ +

[1] Only operator< is fundamental; + the other inequality operators are essentially syntactic sugar.

+ +

[2] Antisymmetry is a theorem, not an axiom: it + follows from irreflexivity and transitivity.

+ +

[3] Because of irreflexivity and transitivity, + operator< always satisfies the definition of a partial + ordering. The definition of a strict weak ordering is stricter, + and the definition of a total ordering is stricter still.

+ +

See also

+ +

EqualityComparable, + StrictWeakOrdering
+

+
+ +

Valid HTML 4.01 Transitional

+ +

Revised + 05 + December, 2006

+ + + + + + + +
Copyright © 2000Jeremy Siek, Univ.of + Notre Dame (jsiek@lsc.nd.edu)
+ +

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/libs/utility/MultiPassInputIterator.html b/libs/utility/MultiPassInputIterator.html new file mode 100644 index 00000000..e331ca3a --- /dev/null +++ b/libs/utility/MultiPassInputIterator.html @@ -0,0 +1,95 @@ + + + + + + + + MultiPassInputIterator + + + + C++ Boost
+ +

Multi-Pass Input Iterator

+ +

This concept is a refinement of Input Iterator, adding + the requirements that the iterator can be used to make multiple passes + through a range, and that if it1 == it2 and it1 is + dereferenceable then ++it1 == ++it2. The Multi-Pass Input Iterator + is very similar to the Forward Iterator. + The only difference is that a Forward Iterator + requires the reference type to be value_type&, + whereas MultiPassInputIterator is like Input Iterator in that + the reference type merely has to be convertible to + value_type.

+ +

Design Notes

+ +

comments by Valentin Bonnard:

+ +

I think that introducing Multi-Pass Input Iterator isn't the right + solution. Do you also want to define Multi-Pass Bidirectionnal Iterator and + Multi-Pass Random Access Iterator ? I don't, definitly. It only confuses + the issue. The problem lies into the existing hierarchy of iterators, which + mixes movabillity, modifiabillity and lvalue-ness, and these are clearly + independant.

+ +

The terms Forward, Bidirectionnal and Random Access are about + movabillity and shouldn't be used to mean anything else. In a completly + orthogonal way, iterators can be immutable, mutable, or neither. Lvalueness + of iterators is also orthogonal with immutabillity. With these clean + concepts, your Multi-Pass Input Iterator is just called a Forward + Iterator.

+ +

Other translations are:
+ std::Forward Iterator -> ForwardIterator & Lvalue Iterator
+ std::Bidirectionnal Iterator -> Bidirectionnal Iterator & Lvalue + Iterator
+ std::Random Access Iterator -> Random Access Iterator & Lvalue + Iterator

+ +

Note that in practice the only operation not allowed on my Forward + Iterator which is allowed on std::Forward Iterator is &*it. I + think that &* is rarely needed in generic code.

+ +

reply by Jeremy Siek:

+ +

The above analysis by Valentin is right on. Of course, there is the + problem with backward compatibility. The current STL implementations are + based on the old definition of Forward Iterator. The right course of action + is to get Forward Iterator, etc. changed in the C++ standard. Once that is + done we can drop Multi-Pass Input Iterator.

+
+ +

Valid HTML 4.01 Transitional

+ +

Revised + 05 + December, 2006

+ + + + + + + +
Copyright © 2000Jeremy Siek, Univ.of + Notre Dame (jsiek@lsc.nd.edu)
+ +

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/libs/utility/OptionalPointee.html b/libs/utility/OptionalPointee.html new file mode 100644 index 00000000..c3c7e44e --- /dev/null +++ b/libs/utility/OptionalPointee.html @@ -0,0 +1,159 @@ + + +OptionalPointee Concept + + +C++ Boost + +
+

Concept: OptionalPointee

+ +

Description

+A type is a model of OptionalPointee if it points to (or refers to) a value +that may not exist. That is, if it has a pointee which might be valid +(existent) or invalid (inexistent); and it is possible to test whether the +pointee is valid or not. +This model does not imply pointer semantics: i.e., it does not imply shallow copy nor +aliasing. +

Notation

+ + + + + + + + + +
T is a type that is a model of OptionalPointee
t is an object of type T or possibly const T
+

Definitions

+

Valid expressions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name Expression Return type Semantics
Value Access *t T&If the pointee is valid returns a reference to + the pointee.
+ If the pointee is invalid the result is undefined.
Value Access t->xyz T*If the pointee is valid returns a builtin pointer to the pointee.
+ If the pointee is invalid the result is undefined (It might not even return NULL).
+
Validity Test bool(t) bool If the pointee is valid returns true.
+ If the pointee is invalid returns false.
Invalidity Test !t bool If the pointee is valid returns false.
+ If the pointee is invalid returns true.
+ + +

Models

+ +
    +
  • pointers, both builtin and smart. +
  • boost::optional<> +
+ +
+

OptionalPointee and relational operations

+

This concept does not define any particular semantic for relational operations, therefore, +a type which models this concept might have either shallow or deep relational semantics.
+For instance, pointers, which are models of OptionalPointee, have shallow relational operators: +comparisons of pointers do not involve comparisons of pointees. +This makes sense for pointers because they have shallow copy semantics.
+But boost::optional<T>, on the other hand, which is also a model of OptionalPointee, has +deep-copy and deep-relational semantics.
+If generic code is written for this concept, it is important not to use relational +operators directly because the semantics might be different depending on the actual type.
+Still, the concept itsef can be used to define deep relational tests that can +be used in generic code with any type which models OptionalPointee:

+ +

Equivalence relation:

+
template<class OptionalPointee>
+inline
+bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y )
+{
+  return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ;
+}
+template<class OptionalPointee>
+struct equal_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
+{
+  bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
+    { return equal_pointees(x,y) ; }
+} ;
+
+

The preceding generic function and function object have the following semantics:
+If both x and y have valid pointees, it compares values via (*x == *y).
+If only one has a valid pointee, returns false.
+If both have invalid pointees, returns true.

+ +

Less-than relation:

+
template<class OptionalPointee>
+inline
+bool less_pointees ( OptionalPointee const& x, OptionalPointee const& y )
+{
+  return !y ? false : ( !x ? true : (*x) < (*y) ) ;
+}
+template<class OptionalPointee>
+struct less_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
+{
+  bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
+    { return less_pointees(x,y) ; }
+} ;
+
+

The preceding generic function and function object have the following semantics:
+If y has an invalid pointee, returns false.
+Else, if x has an invalid pointee, returns true.
+Else, ( x and y have valid pointees), compares values via (*x < +*y).

+


+All these functions and function +objects are is implemented in compare_pointees.hpp

+

Notice that OptionalPointee does not imply aliasing (and optional<> for instance does not alias); +so direct usage of relational operators with the implied aliasing of shallow semantics +-as with pointers- should not be used with generic code written for this concept.

+ +

Acknowledgements

+

Based on the original concept developed by Augustus Saunders. + +
+

+
+ + +
Copyright © 2003 +Fernando Cacciola +
+ +

Distributed under the Boost Software License, Version 1.0. See +www.boost.org/LICENSE_1_0.txt

+ + + diff --git a/libs/utility/README.md b/libs/utility/README.md new file mode 100644 index 00000000..7608f684 --- /dev/null +++ b/libs/utility/README.md @@ -0,0 +1,26 @@ +# ![Boost.Utility](doc/logo.png) + +Boost.Utility, part of collection of the [Boost C++ Libraries](https://github.com/boostorg), provides a number of smaller components, too small to be called libraries in their own right. See the documentation for the list of components. + +### Directories + +* **doc** - Documentation sources +* **include** - Interface headers of Boost.Utility +* **test** - Boost.Utility unit tests + +### More information + +* [Documentation](https://boost.org/libs/utility) +* [Report bugs](https://github.com/boostorg/utility/issues/new). Be sure to mention Boost version, Boost.Utility component, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well. +* Submit your patches as pull requests against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). + +### Build status + +Branch | GitHub Actions | AppVeyor | Test Matrix | Dependencies | +:-------------: | -------------- | -------- | ----------- | ------------ | +[`master`](https://github.com/boostorg/utility/tree/master) | [![GitHub Actions](https://github.com/boostorg/utility/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/boostorg/utility/actions?query=branch%3Amaster) | [![AppVeyor](https://ci.appveyor.com/api/projects/status/g09ehuy2o6aq42th/branch/master?svg=true)](https://ci.appveyor.com/project/Lastique/utility/branch/master) | [![Tests](https://img.shields.io/badge/matrix-master-brightgreen.svg)](http://www.boost.org/development/tests/master/developer/utility.html) | [![Dependencies](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/utility.html) +[`develop`](https://github.com/boostorg/utility/tree/develop) | [![GitHub Actions](https://github.com/boostorg/utility/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/boostorg/utility/actions?query=branch%3Adevelop) | [![AppVeyor](https://ci.appveyor.com/api/projects/status/g09ehuy2o6aq42th/branch/develop?svg=true)](https://ci.appveyor.com/project/Lastique/utility/branch/develop) | [![Tests](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](http://www.boost.org/development/tests/develop/developer/utility.html) | [![Dependencies](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/utility.html) + +### License + +Distributed under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). diff --git a/libs/utility/appveyor.yml b/libs/utility/appveyor.yml new file mode 100644 index 00000000..69df0595 --- /dev/null +++ b/libs/utility/appveyor.yml @@ -0,0 +1,88 @@ +# Copyright 2016-2019 Peter Dimov +# Copyright 2019, 2022 Andrey Semashev +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) + +version: 1.0.{build}-{branch} + +shallow_clone: true + +branches: + only: + - master + - develop + - /feature\/.*/ + +environment: + matrix: + - TOOLSET: msvc-14.0 + ADDRMD: 32,64 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - TOOLSET: msvc-14.1 + CXXSTD: 14,17,latest + ADDRMD: 32,64 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + - TOOLSET: msvc-14.2 + ADDRMD: 32,64 + CXXSTD: 14,17,20,latest + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + - TOOLSET: msvc-14.3 + ADDRMD: 32,64 + CXXSTD: 14,17,20,latest + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + - TOOLSET: clang-win + ADDRMD: 32 + CXXSTD: 14,17,latest + ENV_SCRIPT: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + - TOOLSET: clang-win + ADDRMD: 64 + CXXSTD: 14,17,latest + ENV_SCRIPT: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + - TOOLSET: gcc + CXXSTD: 11,14,1z + ADDPATH: C:\cygwin\bin; + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - TOOLSET: gcc + CXXSTD: 11,14,1z + ADDPATH: C:\cygwin64\bin; + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - TOOLSET: gcc + CXXSTD: 11,14,1z + ADDPATH: C:\mingw\bin; + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - TOOLSET: gcc + CXXSTD: 11,14,1z + ADDPATH: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin; + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - TOOLSET: gcc + CXXSTD: 11,14,17 + ADDPATH: C:\mingw-w64\x86_64-7.3.0-posix-seh-rt_v5-rev0\mingw64\bin; + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - TOOLSET: gcc + CXXSTD: 11,14,17,2a + ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin; + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + +install: + - set GIT_FETCH_JOBS=8 + - set BOOST_BRANCH=develop + - if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master + - cd .. + - git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root + - cd boost-root + - git submodule update --init tools/boostdep + - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\utility + - python tools/boostdep/depinst/depinst.py %DEPINST_ARG_INCLUDE_EXAMPLES% --git_args "--jobs %GIT_FETCH_JOBS%" utility + - cmd /c bootstrap + - b2 headers + +build: off + +test_script: + - PATH=%ADDPATH%%PATH% + - if not "%ENV_SCRIPT%" == "" call "%ENV_SCRIPT%" + - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% + - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% + - b2 -j %NUMBER_OF_PROCESSORS% libs/utility/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release diff --git a/libs/utility/call_traits.htm b/libs/utility/call_traits.htm new file mode 100644 index 00000000..7852a91a --- /dev/null +++ b/libs/utility/call_traits.htm @@ -0,0 +1,19 @@ + + + Boost.CallTraits + + + +Automatic redirection failed, please go to +./doc/html/utility/utilities/call_traits.html +
+ + Boost.CallTraits
+
+ 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/libs/utility/checked_delete.html b/libs/utility/checked_delete.html new file mode 100644 index 00000000..98e7f7ae --- /dev/null +++ b/libs/utility/checked_delete.html @@ -0,0 +1,19 @@ + + + Boost.Utility + + + +Automatic redirection failed, please go to +../core/doc/html/core/checked_delete.html +
+ + Boost.Utility
+
+ 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/libs/utility/compressed_pair.htm b/libs/utility/compressed_pair.htm new file mode 100644 index 00000000..bdc198dc --- /dev/null +++ b/libs/utility/compressed_pair.htm @@ -0,0 +1,19 @@ + + + Boost.Utility + + + +Automatic redirection failed, please go to +./doc/html/utility/utilities/compressed_pair.html +
+ + Boost.Utility
+
+ 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/libs/utility/doc/BOOST_BINARY.qbk b/libs/utility/doc/BOOST_BINARY.qbk new file mode 100644 index 00000000..8abf94ad --- /dev/null +++ b/libs/utility/doc/BOOST_BINARY.qbk @@ -0,0 +1,81 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / 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) + /] + +[/===============] +[#sec:BOOST_BINARY] +[section Binary Integer Literals] +[/===============] + +[section Introduction] + +The macro `BOOST_BINARY` is used for the representation of binary +literals. It takes as an argument a binary number arranged as an +arbitrary amount of 1s and 0s in groupings of length 1 to 8, with +groups separated by spaces. The macro serves as a replacement for +[@https://en.cppreference.com/w/cpp/language/integer_literal binary integer literals], +adopted in C++14. + +The type of the literal yielded is determined by the same rules as +those of [@https://en.cppreference.com/w/cpp/language/integer_literal hex and octal literals]. +By implementation, this macro expands directly to an octal literal during preprocessing, so +there is no overhead at runtime and the result is usable in any place that an octal literal +would be. + +In order to directly support binary literals with suffixes, +additional macros of the form `BOOST_BINARY_XXX` are also +provided, where `XXX` is a standard integer suffix in all capital +letters. + +In addition, LL and ULL suffixes may be used for representing +`long long` and `unsigned long long` types in compilers which provide +them as an extension. + +The `BOOST_BINARY` family of macros resides in the header +[@../../../../boost/utility/binary.hpp ]. + +[endsect] + +[section Example] + +``` +void foo( int ); + +void foo( unsigned long ); + +void bar() +{ + int value1 = BOOST_BINARY( 100 111000 01 1 110 ); + + unsigned long value2 = BOOST_BINARY_UL( 100 001 ); // unsigned long + + long long value3 = BOOST_BINARY_LL( 11 000 ); // long long if supported + + __assert__( BOOST_BINARY( 10010 ) + & BOOST_BINARY( 11000 ) + == BOOST_BINARY( 10000 ) + ); + + foo( BOOST_BINARY( 1010 ) ); // calls the first foo + + foo( BOOST_BINARY_LU( 1010 ) ); // calls the second foo +} +``` + +[endsect] + +[/===============] +[xinclude tmp/boost_binary_reference.xml] +[/===============] + + +[section Acknowledgments] + +Contributed by Matt Calabrese. + +[endsect] + +[endsect] diff --git a/libs/utility/doc/Jamfile.v2 b/libs/utility/doc/Jamfile.v2 new file mode 100644 index 00000000..6883c2a7 --- /dev/null +++ b/libs/utility/doc/Jamfile.v2 @@ -0,0 +1,413 @@ +# Copyright John Maddock 2005. Use, modification, and distribution are +# subject to 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) + +import project ; +import doxygen ; +import quickbook ; + +project boost/libs/utility/doc ; + +path-constant INCLUDES : ../../.. ; +path-constant boost-images : ../../../doc/src/images ; + +# Generate XML doxygen reference for base_from_member component in base_from_member_reference.xml +doxygen base_from_member_reference + : + $(INCLUDES)/boost/utility/base_from_member.hpp + : + tmp + ENABLE_PREPROCESSING=YES + EXPAND_ONLY_PREDEF=YES + EXTRACT_ALL=NO + EXTRACT_PRIVATE=NO + HIDE_UNDOC_MEMBERS=YES + MACRO_EXPANSION=YES + "PREDEFINED= \\ + BOOST_UTILITY_DOCS \\ + BOOST_SYMBOL_VISIBLE= \\ + BOOST_FORCEINLINE=inline \\ + BOOST_GPU_ENABLED= \\ + BOOST_STATIC_ASSERT(x)= \\ + BOOST_STATIC_ASSERT_MSG(x,y)= \\ + BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\ + BOOST_RV_REF(x)=\"x&&\" \\ + BOOST_NESTED_TEMPLATE=template \\ + BOOST_CONSTEXPR=constexpr \\ + BOOST_CXX14_CONSTEXPR=constexpr \\ + BOOST_OPERATORS_CONSTEXPR=constexpr \\ + BOOST_CONSTEXPR_OR_CONST=constexpr \\ + BOOST_NOEXCEPT=noexcept \\ + BOOST_NOEXCEPT_IF(x)=noexcept(x) \\ + BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\ + BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\ + BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\ + BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\ + BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\ + BOOST_REF_CONST=const" + "EXCLUDE_SYMBOLS= \\ + detail \\ + F \\ + result_of_has_result_type_impl \\ + conditional \\ + boost::operators_impl" + "boost.doxygen.reftitle=Reference" + "boost.doxygen.refid=base_from_member.reference" + ; + +# Generate XML doxygen reference for boost_binary component in boost_binary_reference.xml +doxygen boost_binary_reference + : + $(INCLUDES)/boost/utility/binary.hpp + : + tmp + ENABLE_PREPROCESSING=YES + EXPAND_ONLY_PREDEF=YES + EXTRACT_ALL=NO + EXTRACT_PRIVATE=NO + HIDE_UNDOC_MEMBERS=YES + MACRO_EXPANSION=YES + "PREDEFINED= \\ + BOOST_UTILITY_DOCS \\ + BOOST_SYMBOL_VISIBLE= \\ + BOOST_FORCEINLINE=inline \\ + BOOST_GPU_ENABLED= \\ + BOOST_STATIC_ASSERT(x)= \\ + BOOST_STATIC_ASSERT_MSG(x,y)= \\ + BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\ + BOOST_RV_REF(x)=\"x&&\" \\ + BOOST_NESTED_TEMPLATE=template \\ + BOOST_CONSTEXPR=constexpr \\ + BOOST_CXX14_CONSTEXPR=constexpr \\ + BOOST_OPERATORS_CONSTEXPR=constexpr \\ + BOOST_CONSTEXPR_OR_CONST=constexpr \\ + BOOST_NOEXCEPT=noexcept \\ + BOOST_NOEXCEPT_IF(x)=noexcept(x) \\ + BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\ + BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\ + BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\ + BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\ + BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\ + BOOST_REF_CONST=const" + "EXCLUDE_SYMBOLS= \\ + detail \\ + F \\ + result_of_has_result_type_impl \\ + conditional \\ + boost::operators_impl" + "boost.doxygen.reftitle=Reference" + "boost.doxygen.refid=boost_binary.reference" + ; + +# Generate XML doxygen reference for call_traits component in call_traits_reference.xml +doxygen call_traits_reference + : + $(INCLUDES)/boost/call_traits.hpp + $(INCLUDES)/boost/detail/call_traits.hpp + : + tmp + ENABLE_PREPROCESSING=YES + EXPAND_ONLY_PREDEF=YES + EXTRACT_ALL=NO + EXTRACT_PRIVATE=NO + HIDE_UNDOC_MEMBERS=YES + MACRO_EXPANSION=YES + "PREDEFINED= \\ + BOOST_UTILITY_DOCS \\ + BOOST_SYMBOL_VISIBLE= \\ + BOOST_FORCEINLINE=inline \\ + BOOST_GPU_ENABLED= \\ + BOOST_STATIC_ASSERT(x)= \\ + BOOST_STATIC_ASSERT_MSG(x,y)= \\ + BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\ + BOOST_RV_REF(x)=\"x&&\" \\ + BOOST_NESTED_TEMPLATE=template \\ + BOOST_CONSTEXPR=constexpr \\ + BOOST_CXX14_CONSTEXPR=constexpr \\ + BOOST_OPERATORS_CONSTEXPR=constexpr \\ + BOOST_CONSTEXPR_OR_CONST=constexpr \\ + BOOST_NOEXCEPT=noexcept \\ + BOOST_NOEXCEPT_IF(x)=noexcept(x) \\ + BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\ + BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\ + BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\ + BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\ + BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\ + BOOST_REF_CONST=const" + "EXCLUDE_SYMBOLS= \\ + detail \\ + F \\ + result_of_has_result_type_impl \\ + conditional \\ + boost::operators_impl" + "boost.doxygen.reftitle=Reference" + "boost.doxygen.refid=call_traits.reference" + ; + +# Generate XML doxygen reference for compressed_pair component in compressed_pair_reference.xml +doxygen compressed_pair_reference + : + $(INCLUDES)/boost/compressed_pair.hpp + $(INCLUDES)/boost/detail/compressed_pair.hpp + : + tmp + ENABLE_PREPROCESSING=YES + EXPAND_ONLY_PREDEF=YES + EXTRACT_ALL=NO + EXTRACT_PRIVATE=NO + HIDE_UNDOC_MEMBERS=YES + MACRO_EXPANSION=YES + "PREDEFINED= \\ + BOOST_UTILITY_DOCS \\ + BOOST_SYMBOL_VISIBLE= \\ + BOOST_FORCEINLINE=inline \\ + BOOST_GPU_ENABLED= \\ + BOOST_STATIC_ASSERT(x)= \\ + BOOST_STATIC_ASSERT_MSG(x,y)= \\ + BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\ + BOOST_RV_REF(x)=\"x&&\" \\ + BOOST_NESTED_TEMPLATE=template \\ + BOOST_CONSTEXPR=constexpr \\ + BOOST_CXX14_CONSTEXPR=constexpr \\ + BOOST_OPERATORS_CONSTEXPR=constexpr \\ + BOOST_CONSTEXPR_OR_CONST=constexpr \\ + BOOST_NOEXCEPT=noexcept \\ + BOOST_NOEXCEPT_IF(x)=noexcept(x) \\ + BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\ + BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\ + BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\ + BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\ + BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\ + BOOST_REF_CONST=const" + "EXCLUDE_SYMBOLS= \\ + detail \\ + F \\ + result_of_has_result_type_impl \\ + conditional \\ + boost::operators_impl" + "boost.doxygen.reftitle=Reference" + "boost.doxygen.refid=compressed_pair.reference" + ; + +# Generate XML doxygen reference for in_place_factory component in in_place_factory_reference.xml +doxygen in_place_factory_reference + : + $(INCLUDES)/boost/utility/in_place_factory.hpp + $(INCLUDES)/boost/utility/typed_in_place_factory.hpp + : + tmp + ENABLE_PREPROCESSING=YES + EXPAND_ONLY_PREDEF=YES + EXTRACT_ALL=NO + EXTRACT_PRIVATE=NO + HIDE_UNDOC_MEMBERS=YES + MACRO_EXPANSION=YES + "PREDEFINED= \\ + BOOST_UTILITY_DOCS \\ + BOOST_SYMBOL_VISIBLE= \\ + BOOST_FORCEINLINE=inline \\ + BOOST_GPU_ENABLED= \\ + BOOST_STATIC_ASSERT(x)= \\ + BOOST_STATIC_ASSERT_MSG(x,y)= \\ + BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\ + BOOST_RV_REF(x)=\"x&&\" \\ + BOOST_NESTED_TEMPLATE=template \\ + BOOST_CONSTEXPR=constexpr \\ + BOOST_CXX14_CONSTEXPR=constexpr \\ + BOOST_OPERATORS_CONSTEXPR=constexpr \\ + BOOST_CONSTEXPR_OR_CONST=constexpr \\ + BOOST_NOEXCEPT=noexcept \\ + BOOST_NOEXCEPT_IF(x)=noexcept(x) \\ + BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\ + BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\ + BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\ + BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\ + BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\ + BOOST_REF_CONST=const" + "EXCLUDE_SYMBOLS= \\ + detail \\ + F \\ + result_of_has_result_type_impl \\ + conditional \\ + boost::operators_impl" + "boost.doxygen.reftitle=Reference" + "boost.doxygen.refid=in_place_factory.reference" + ; + +# Generate XML doxygen reference for operators component in operators_reference.xml +# we skip operators_reference because operators.hpp is not adapted for doxygen + +# Generate XML doxygen reference for result_of component in result_of_reference.xml +doxygen result_of_reference + : + $(INCLUDES)/boost/utility/result_of.hpp + : + tmp + ENABLE_PREPROCESSING=YES + EXPAND_ONLY_PREDEF=YES + EXTRACT_ALL=NO + EXTRACT_PRIVATE=NO + HIDE_UNDOC_MEMBERS=YES + MACRO_EXPANSION=YES + "PREDEFINED= \\ + BOOST_UTILITY_DOCS \\ + BOOST_SYMBOL_VISIBLE= \\ + BOOST_FORCEINLINE=inline \\ + BOOST_GPU_ENABLED= \\ + BOOST_STATIC_ASSERT(x)= \\ + BOOST_STATIC_ASSERT_MSG(x,y)= \\ + BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\ + BOOST_RV_REF(x)=\"x&&\" \\ + BOOST_NESTED_TEMPLATE=template \\ + BOOST_CONSTEXPR=constexpr \\ + BOOST_CXX14_CONSTEXPR=constexpr \\ + BOOST_OPERATORS_CONSTEXPR=constexpr \\ + BOOST_CONSTEXPR_OR_CONST=constexpr \\ + BOOST_NOEXCEPT=noexcept \\ + BOOST_NOEXCEPT_IF(x)=noexcept(x) \\ + BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\ + BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\ + BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\ + BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\ + BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\ + BOOST_REF_CONST=const" + "EXCLUDE_SYMBOLS= \\ + detail \\ + F \\ + result_of_has_result_type_impl \\ + conditional \\ + boost::operators_impl" + "boost.doxygen.reftitle=Reference" + "boost.doxygen.refid=result_of.reference" + ; + +# Generate XML doxygen reference for string_view component in string_view_reference.xml +doxygen string_view_reference + : + $(INCLUDES)/boost/utility/string_view.hpp + : + tmp + ENABLE_PREPROCESSING=YES + EXPAND_ONLY_PREDEF=YES + EXTRACT_ALL=NO + EXTRACT_PRIVATE=NO + HIDE_UNDOC_MEMBERS=YES + MACRO_EXPANSION=YES + "PREDEFINED= \\ + BOOST_UTILITY_DOCS \\ + BOOST_SYMBOL_VISIBLE= \\ + BOOST_FORCEINLINE=inline \\ + BOOST_GPU_ENABLED= \\ + BOOST_STATIC_ASSERT(x)= \\ + BOOST_STATIC_ASSERT_MSG(x,y)= \\ + BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\ + BOOST_RV_REF(x)=\"x&&\" \\ + BOOST_NESTED_TEMPLATE=template \\ + BOOST_CONSTEXPR=constexpr \\ + BOOST_CXX14_CONSTEXPR=constexpr \\ + BOOST_OPERATORS_CONSTEXPR=constexpr \\ + BOOST_CONSTEXPR_OR_CONST=constexpr \\ + BOOST_NOEXCEPT=noexcept \\ + BOOST_NOEXCEPT_IF(x)=noexcept(x) \\ + BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\ + BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\ + BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\ + BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\ + BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\ + BOOST_REF_CONST=const" + "EXCLUDE_SYMBOLS= \\ + detail \\ + F \\ + result_of_has_result_type_impl \\ + conditional \\ + boost::operators_impl" + "boost.doxygen.reftitle=Reference" + "boost.doxygen.refid=string_view.reference" + ; + +# Generate XML doxygen reference for value_init component in value_init_reference.xml +doxygen value_init_reference + : + $(INCLUDES)/boost/utility/value_init.hpp + : + tmp + ENABLE_PREPROCESSING=YES + EXPAND_ONLY_PREDEF=YES + EXTRACT_ALL=NO + EXTRACT_PRIVATE=NO + HIDE_UNDOC_MEMBERS=YES + MACRO_EXPANSION=YES + "PREDEFINED= \\ + BOOST_UTILITY_DOCS \\ + BOOST_SYMBOL_VISIBLE= \\ + BOOST_FORCEINLINE=inline \\ + BOOST_GPU_ENABLED= \\ + BOOST_STATIC_ASSERT(x)= \\ + BOOST_STATIC_ASSERT_MSG(x,y)= \\ + BOOST_STATIC_CONSTANT(x,y)=\"static constexpr x y\" \\ + BOOST_RV_REF(x)=\"x&&\" \\ + BOOST_NESTED_TEMPLATE=template \\ + BOOST_CONSTEXPR=constexpr \\ + BOOST_CXX14_CONSTEXPR=constexpr \\ + BOOST_OPERATORS_CONSTEXPR=constexpr \\ + BOOST_CONSTEXPR_OR_CONST=constexpr \\ + BOOST_NOEXCEPT=noexcept \\ + BOOST_NOEXCEPT_IF(x)=noexcept(x) \\ + BOOST_NOEXCEPT_OR_NOTHROW=noexcept \\ + BOOST_COPY_ASSIGN_REF(x)=\"x const&\" \\ + BOOST_DEFAULTED_FUNCTION(x,y)=\"x = default;\" \\ + BOOST_DELETED_FUNCTION(x)=\"x = delete;\" \\ + BOOST_EXPLICIT_OPERATOR_BOOL()=\"explicit operator bool() const;\" \\ + BOOST_REF_CONST=const" + "EXCLUDE_SYMBOLS= \\ + detail \\ + F \\ + result_of_has_result_type_impl \\ + conditional \\ + boost::operators_impl" + "boost.doxygen.reftitle=Reference" + "boost.doxygen.refid=value_init.reference" + ; + +# Generate main.xml boostbook documentation from main.qbk quickbook documentation +xml main : main.qbk ; + +# Generate ./html documentation from main.xml boostbook documentation +# Each doxygen reference in quickbook files with [xinclude tmp/_reference.xml] becomes: +# +# in boostbook. +# All of these commands give the reference the id "utility.reference" +boostbook standalone_main + : + main + : + base_from_member_reference + boost_binary_reference + call_traits_reference + compressed_pair_reference + in_place_factory_reference + result_of_reference + string_view_reference + value_init_reference + # File name of HTML output: + # root.filename=main + boost.root=../../../.. + pdf:"boost.url.prefix=http://www.boost.org/doc/libs/release/libs/utility/doc/html" + # How far down we chunk nested sections: no more than two so utility component pages include their reference + chunk.section.depth=2 # 8 + # Don't put the first section on the same page as the TOC: + chunk.first.sections=1 # 1 + # How far down sections get TOC: 2 so we show each Utility component in main page but no more than that + toc.section.depth=2 # 2 + # Max depth in each TOC: 2 so we show each Utility component in main page but no more than that + toc.max.depth=2 # 2 + # How far down we go with TOC's in main page: 2 so each Utility component page has 1 level TOC + generate.section.toc.level=2 # 2 + ; + +############################################################################### +alias boostdoc ; +explicit boostdoc ; + +alias boostrelease : standalone_main ; +explicit boostrelease ; diff --git a/libs/utility/doc/base_from_member.qbk b/libs/utility/doc/base_from_member.qbk new file mode 100644 index 00000000..f23707b6 --- /dev/null +++ b/libs/utility/doc/base_from_member.qbk @@ -0,0 +1,376 @@ +[/ + Copyright 2001, 2003, 2004, 2012 Daryle Walker. + Copyright (c) 2021, Alan Freitas + + Distributed under the Boost Software License, Version 1.0. + + See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt +] + +[section:base_from_member Base from Member] +[block''''''] + +[section Introduction] + +The class templates __base_from_member__ support the base-from-member idiom. +When developing a class, sometimes a base class needs to be initialized +with a member of the current class. As a na\u00EFve example: + +``` +#include /* for std::streambuf */ +#include /* for std::ostream */ + +class fdoutbuf + : public __std_streambuf__ +{ +public: + explicit fdoutbuf( int fd ); + //... +}; + +class fdostream + : public __std_ostream__ +{ +protected: + fdoutbuf buf; +public: + explicit fdostream( int fd ) + : buf( fd ), __std_ostream__( &buf ) {} + //... +}; +``` + +This is undefined because C++'s initialization order mandates that the base +class is initialized before the member it uses. [@http://www.moocat.org R. +Samuel Klatchko] developed a way around this by using the initialization +order in his favor. Base classes are initialized in order of declaration, so +moving the desired member to another base class, that is initialized before +the desired base class, can ensure proper initialization. + +A custom base class can be made for this idiom: + + #include /* for std::streambuf */ + #include /* for std::ostream */ + + class fdoutbuf + : public __std_streambuf__ + { + public: + explicit fdoutbuf( int fd ); + //... + }; + + struct fdostream_pbase + { + fdoutbuf sbuffer; + + explicit fdostream_pbase( int fd ) + : sbuffer( fd ) {} + }; + + class fdostream + : private fdostream_pbase + , public __std_ostream__ + { + typedef fdostream_pbase pbase_type; + typedef __std_ostream__ base_type; + + public: + explicit fdostream( int fd ) + : pbase_type( fd ), base_type( &sbuffer ) {} + //... + }; + +Other projects can use similar custom base classes. The technique is basic +enough to make a template, with a sample template class in this library. +The main template parameter is the type of the enclosed member. The +template class has several (explicit) constructor member templates, which +implicitly type the constructor arguments and pass them to the member. The +template class uses implicit copy construction and assignment, cancelling +them if the enclosed member is non-copyable. + +Manually coding a base class may be better if the construction and/or +copying needs are too complex for the supplied template class, or if the +compiler is not advanced enough to use it. + +Since base classes are unnamed, a class cannot have multiple (direct) base +classes of the same type. The supplied template class has an extra template +parameter, an integer, that exists solely to provide type differentiation. +This parameter has a default value so a single use of a particular member +type does not need to concern itself with the integer. + + +[endsect] + +[section Synopsis] + + #include /* exposition only */ + + #ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY + #define BOOST_BASE_FROM_MEMBER_MAX_ARITY 10 + #endif + + template < typename MemberType, int UniqueID = 0 > + class __base_from_member__ + { + protected: + MemberType member; + + #if ``['C++11 is in use]`` + template< typename ...T > + explicit constexpr __base_from_member__( T&& ...x ) + noexcept( __std_is_nothrow_constructible__::value ); + #else + __base_from_member__(); + + template< typename T1 > + explicit __base_from_member__( T1 x1 ); + + template< typename T1, typename T2 > + __base_from_member__( T1 x1, T2 x2 ); + + //... + + template< typename T1, typename T2, typename T3, typename T4, + typename T5, typename T6, typename T7, typename T8, typename T9, + typename T10 > + __base_from_member__( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, + T8 x8, T9 x9, T10 x10 ); + #endif + }; + + template < typename MemberType, int UniqueID > + class __base_from_member__ + { + protected: + MemberType& member; + + explicit constexpr __base_from_member__( MemberType& x ) + noexcept; + }; + +The class template has a first template parameter `MemberType` representing +the type of the based-member. It has a last template parameter `UniqueID`, +that is an `int`, to differentiate between multiple base classes that use +the same based-member type. The last template parameter has a default value +of zero if it is omitted. The class template has a protected data member +called `member` that the derived class can use for later base classes or +itself. + +If the appropriate features of C++11 are present, there will be a single +constructor template. It implements ['perfect forwarding] to the best +constructor call of `member` if any. The constructor template is marked +both `constexpr` and `explicit`. The former will be ignored if the +corresponding inner constructor call of `member` does not have the marker. +The latter binds the other way; always taking effect, even when the inner +constructor call does not have the marker. The constructor template +propagates the `noexcept` status of the inner constructor call. The +constructor template has a trailing parameter with a default value that +disables the template when its signature is too close to the signatures of +the automatically-defined non-template copy- and/or move-constructors of +__base_from_member__. + +On earlier-standard compilers, there is a default constructor and several +constructor member templates. These constructor templates can take as many +arguments (currently up to ten) as possible and pass them to a constructor +of the data member. + +A specialization for member references offers a single constructor taking +a `MemberType&`, which is the only way to initialize a reference. + +Since C++ does not allow any way to explicitly state the template parameters +of a templated constructor, make sure that the arguments are already close +as possible to the actual type used in the data member's desired constructor. +Explicit conversions may be necessary. + +The `BOOST_BASE_FROM_MEMBER_MAX_ARITY` macro constant specifies the maximum +argument length for the constructor templates. The constant may be overridden +if more (or less) argument configurations are needed. The constant may be +read for code that is expandable like the class template and needs to +maintain the same maximum size. (Example code would be a class that uses +this class template as a base class for a member with a flexible set of +constructors.) This constant is ignored when C++11 features are present. + +[endsect] + +[section Basic Usage] + +With the starting example, the `fdoutbuf` sub-object needs to be +encapsulated in a base class that is inherited before `__std_ostream__`. + +``` +#include + +#include // for std::streambuf +#include // for __std_ostream__ + +class fdoutbuf + : public __std_streambuf__ +{ +public: + explicit fdoutbuf( int fd ); + //... +}; + +class fdostream + : private __boost_base_from_member__ + , public __std_ostream__ +{ + // Helper typedef's + typedef __boost_base_from_member__ pbase_type; + typedef __std_ostream__ base_type; + +public: + explicit fdostream( int fd ) + : pbase_type( fd ), base_type( &member ){} + //... +}; +``` + +The base-from-member idiom is an implementation detail, so it should not +be visible to the clients (or any derived classes) of `fdostream`. Due to +the initialization order, the `fdoutbuf` sub-object will get initialized +before the `__std_ostream__` sub-object does, making the former sub-object +safe to use in the latter sub-object's construction. Since the `fdoutbuf` +sub-object of the final type is the only sub-object with the name `member` +that name can be used unqualified within the final class. + +[endsect] + +[section Multiple Sub-Objects] + +The base-from-member class templates should commonly involve only one +base-from-member sub-object, usually for attaching a stream-buffer to an +I/O stream. The next example demonstrates how to use multiple +base-from-member sub-objects and the resulting qualification issues. + +``` +#include + +#include /* for NULL */ + +struct an_int +{ + int y; + + an_int( float yf ); +}; + +class switcher +{ +public: + switcher(); + switcher( double, int * ); + //... +}; + +class flow_regulator +{ +public: + flow_regulator( switcher &, switcher & ); + //... +}; + +template < unsigned Size > +class fan +{ +public: + explicit fan( switcher ); + //... +}; + +class system + : private __boost_base_from_member__ + , private __boost_base_from_member__ + , private __boost_base_from_member__ + , private __boost_base_from_member__ + , protected flow_regulator + , public fan<6> +{ + // Helper typedef's + typedef __boost_base_from_member__ pbase0_type; + typedef __boost_base_from_member__ pbase1_type; + typedef __boost_base_from_member__ pbase2_type; + typedef __boost_base_from_member__ pbase3_type; + + typedef flow_regulator base1_type; + typedef fan<6> base2_type; + +public: + system( double x ); + //... +}; + +system::system( double x ) + : pbase0_type( 0.2 ) + , pbase1_type() + , pbase2_type( -16, &this->pbase0_type::member.y ) + , pbase3_type( x, static_cast(NULL) ) + , base1_type( pbase3_type::member, pbase1_type::member ) + , base2_type( pbase2_type::member ) +{ + //... +} +``` + +The final class has multiple sub-objects with the name `member`, so any +use of that name needs qualification by a name of the appropriate base +type. Using `typedef`s ease mentioning the base types. + +However, the fix introduces a new problem when a pointer is needed. Using the +address operator with a sub-object qualified with its class's name results in a +pointer-to-member (here, having a type of `an_int __boost_base_from_member__::*`) +instead of a pointer to the member (having a type of `an_int*`). +The new problem is fixed by qualifying the sub-object with `this->` and is needed +just for pointers, and not for references or values. + +There are some argument conversions in the initialization. The constructor +argument for `pbase0_type` is converted from `double` to `float`. The first +constructor argument for `pbase2_type` is converted from `int` to `double`. + +The second constructor argument for `pbase3_type` is a special case of +necessary conversion; all forms of the null-pointer literal in C++ (except +`nullptr` from C++11) also look like compile-time integral expressions, so +C++ always interprets such code as an integer when it has overloads that can +take either an integer or a pointer. + +The last conversion is necessary for the compiler to call a constructor form +with the exact pointer type used in `switcher`'s constructor. (If C++11's +__nullptr__ is used, it still needs a conversion if multiple pointer types can +be accepted in a constructor call but `__std_nullptr_t__` cannot.) + +[endsect] + +[/===============] +[xinclude tmp/base_from_member_reference.xml] +[/===============] + +[section Acknowledgments] + +Author: Walker, Daryle + +Copyright 2001, 2003, 2004, 2012 Daryle Walker + +* [@http://www.boost.org/people/ed_brey.htm Ed Brey] suggested some interface + changes. + +* [@http://www.moocat.org R. Samuel Klatchko] ([@mailto:rsk@moocat.org + rsk@moocat.org], [@mailto:rsk@brightmail.com rsk@brightmail.com]) invented + the idiom of how to use a class member for initializing a base class. + +* [@http://www.boost.org/people/dietmar_kuehl.htm Dietmar Kuehl] popularized the + base-from-member idiom in his [@http://www.informatik.uni-konstanz.de/~kuehl/c++/iostream/ + IOStream example classes]. + +* Jonathan Turkanis supplied an implementation of generating the constructor + templates that can be controlled and automated with macros. The + implementation uses the [@boost:/libs/preprocessor/index.html Preprocessor library]. + +* [@http://www.boost.org/people/daryle_walker.html">Daryle Walker] started the + library. Contributed the test file [@../../../test/base_from_member_test.cpp + base_from_member_test.cpp]. + +[endsect] + +[endsect] diff --git a/libs/utility/doc/call_traits.qbk b/libs/utility/doc/call_traits.qbk new file mode 100644 index 00000000..9ca0e97b --- /dev/null +++ b/libs/utility/doc/call_traits.qbk @@ -0,0 +1,443 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / + / 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) + /] + +[/===============] +[section Call Traits] +[/===============] + +[section Introduction] + +All of the contents of [@../../../../boost/call_traits.hpp ``] are +defined inside `namespace boost`. + +The template class __call_traits_T__ encapsulates the +"best" method to pass a parameter of some type `T` to or +from a function, and consists of a collection of `typedef`s defined +as in the table below. The purpose of __call_traits__ is to ensure +that problems like [link sec:refs "references to references"] +never occur, and that parameters are passed in the most efficient +manner possible, as in the [link sec:examples examples]. In each +case, if your existing practice is to use the type defined on the +left, then replace it with the __call_traits__ defined type on the +right. + +Note that for compilers that do not support either partial +specialization or member templates, no benefit will occur from +using __call_traits__: the __call_traits__ defined types will always be +the same as the existing practice in this case. In addition if +only member templates and not partial template specialisation is +support by the compiler (for example Visual C++ 6) then +__call_traits__ cannot be used with array types, although it can still be +used to solve the reference to reference problem. + +[table __call_traits__ types + [[Existing practice] [__call_traits__ equivalent] [Description] [Notes]] + [ + [`T` + + (return by value) + ] + [ + __call_traits_T__`::value_type` + ] + [ + Defines a type that represents the "value" of type `T`. + + Use this for functions that return by value, or possibly for stored values of type `T`. + ] + [2] + ] + [ + [`T&` + + (return value) + ] + [ + __call_traits_T__`::reference` + ] + [ + Defines a type that represents a reference to type `T`. + + Use for functions that would normally return a `T&`. + ] + [1] + ] + [ + [`const T&` + + (return value) + ] + [ + __call_traits_T__`::const_reference` + ] + [ + Defines a type that represents a constant reference to type `T`. + + Use for functions that would normally return a `const T&`. + ] + [1] + ] + [ + [`const T&` + + (function parameter) + ] + [ + __call_traits_T__`::param_type` + ] + [ + Defines a type that represents the "best" way to pass a parameter of type `T` to a function. + ] + [1,3] + ] +] + +Notes: + +# If `T` is already reference type, then __call_traits__ is + defined such that [link sec:refs "references to references"] + do not occur (requires partial specialization). +# If `T` is an array type, then __call_traits__ defines `value_type` + as a "constant pointer to type" rather than an + "array of type" (requires partial specialization). + Note that if you are using `value_type` as a stored value + then this will result in storing a "constant pointer to + an array" rather than the array itself. This may or may + not be a good thing depending upon what you actually + need (in other words take care!). +# If `T` is a small built in type or a pointer, then `param_type` + is defined as `T const`, instead of `T const&`. This can + improve the ability of the compiler to optimize loops in + the body of the function if they depend upon the passed + parameter, the semantics of the passed parameter is + otherwise unchanged (requires partial specialization). + + +[endsect] +[section Copy constructibility] + +The following table defines which __call_traits__ types can always +be copy-constructed from which other types: + +[table Which __call_traits__ types can always be copy-constructed from which other types + [[] [To `T`] [To `value_type`] [To `reference`] [To `const_reference`] [To `param_type`]] + [[From `T`] [iff `T` is copy constructible] [iff `T` is copy constructible] [Yes] [Yes] [Yes]] + [[From `value_type`] [iff `T` is copy constructible] [iff `T` is copy constructible] [No] [No] [Yes]] + [[From `reference`] [iff `T` is copy constructible] [iff `T` is copy constructible] [Yes] [Yes] [Yes]] + [[From `const_reference`] [iff `T` is copy constructible] [No] [No] [Yes] [Yes]] + [[From `param_type`] [iff `T` is copy constructible] [iff `T` is copy constructible] [No] [No] [Yes]] +] + +If `T` is an assignable type the following assignments are possible: + +[table Which __call_traits__ types are assignable from which other types + [[] [To `T`] [To `value_type`] [To `reference`] [To `const_reference`] [To `param_type`]] + [[From `T`] [Yes] [Yes] [-] [-] [-]] + [[From `value_type`] [Yes] [Yes] [-] [-] [-]] + [[From `reference`] [Yes] [Yes] [-] [-] [-]] + [[From `const_reference`] [Yes] [Yes] [-] [-] [-]] + [[From `param_type`] [Yes] [Yes] [-] [-] [-]] +] +[endsect] + +[#sec:examples] +[section Examples] + +The following table shows the effect that __call_traits__ has on +various types. + +[table Examples of __call_traits__ types + [[] [__call_traits__::`value_type`] [__call_traits__::`reference`] [__call_traits__::`const_reference`] [__call_traits__::`param_type`] [Applies to:]] + [[From `my_class`] [`my_class`] [`my_class&`] [`const my_class&`] [`my_class const&`] [All user-defined types]] + [[From `int`] [`int`] [`int&`] [`const int&`] [`int const`] [All small built-in types]] + [[From `int*`] [`int*`] [`int*&`] [`int* const &`] [`int* const`] [All pointer types]] + [[From `int&`] [`int&`] [`int&`] [`const int&`] [`int&`] [All reference types]] + [[From `const int&`] [`const int&`] [`const int&`] [`const int&`] [`const int&`] [All constant reference types]] + [[From `int[3]`] [`const int*`] [`int(&)[3]`] [`const int(&)[3]`] [`const int* const`] [All array types]] + [[From `const int[3]`] [`const int*`] [`const int(&)[3]`] [`const int(&)[3]`] [`const int* const`] [All constant array types]] +] + +The table assumes the compiler supports partial +specialization: if it does not then all types behave in +the same way as the entry for "`my_class`", and +__call_traits__ can not be used with reference or array types. + +[section Example 1:] + +The following class is a trivial class that stores some type `T` +by value (see the [@../../../test/call_traits_test.cpp `call_traits_test.cpp`] +file). The aim is to illustrate how each of the available +__call_traits__ `typedef`s may be used: + +``` +template +struct contained +{ + // define our typedefs first, arrays are stored by value + // so value_type is not the same as result_type: + typedef typename __boost_call_traits__::param_type param_type; + typedef typename __boost_call_traits__::reference reference; + typedef typename __boost_call_traits__::const_reference const_reference; + typedef T value_type; + typedef typename __boost_call_traits__::value_type result_type; + + // stored value: + value_type v_; + + // constructors: + contained() {} + contained(param_type p) : v_(p){} + // return byval: + result_type value() { return v_; } + // return by_ref: + reference get() { return v_; } + const_reference const_get()const { return v_; } + // pass value: + void call(param_type p){} + +}; +``` +[endsect] + +[#sec:refs] +[section Example 2 (the reference to reference problem):] + +Consider the definition of __std_binder1st__: + +``` +template +class binder1st : + public __std_unary_function__ +{ +protected: + Operation op; + typename Operation::first_argument_type value; +public: + binder1st(const Operation& x, const typename Operation::first_argument_type& y); + typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const; +}; +``` + +Now consider what happens in the relatively common case that +the functor takes its second argument as a reference, that +implies that `Operation::second_argument_type` is a +reference type, `operator()` will now end up taking a +reference to a reference as an argument, and that is not +currently legal. The solution here is to modify `operator()` +to use __call_traits__: + +``` +typename Operation::result_type operator()(typename __call_traits__::param_type x) const; +``` + +Now in the case that `Operation::second_argument_type` +is a reference type, the argument is passed as a reference, and +the no "reference to reference" occurs. + +[endsect] + +[#sec:example3] +[section Example 3 (the `make_pair` problem):] + +If we pass the name of an array as one (or both) arguments to `__std_make_pair__`, +then template argument deduction deduces the passed parameter as +"const reference to array of `T`", this also applies to +string literals (which are really array literals). Consequently +instead of returning a pair of pointers, it tries to return a +pair of arrays, and since an array type is not copy-constructible +the code fails to compile. One solution is to explicitly cast the +arguments to __std_make_pair__ to pointers, but __call_traits__ provides a +better automatic solution that works safely even in generic code where the +cast might do the wrong thing: + +``` +template +__std_pair__< + typename __boost_call_traits__::value_type, + typename __boost_call_traits__::value_type> + make_pair(const T1& t1, const T2& t2) +{ + return __std_pair__< + typename __boost_call_traits__::value_type, + typename __boost_call_traits__::value_type>(t1, t2); +} +``` + +Here, the deduced argument types will be automatically +degraded to pointers if the deduced types are arrays, similar +situations occur in the standard binders and adapters: in +principle in any function that "wraps" a temporary +whose type is deduced. Note that the function arguments to +__std_make_pair__ are not expressed in terms of __call_traits__: doing so +would prevent template argument deduction from functioning. +[endsect] + +[#sec:example4] +[section Example 4 (optimising fill):] + +The __call_traits__ template will "optimize" the passing +of a small built-in type as a function parameter. This mainly has +an effect when the parameter is used within a loop body. + +In the following example (see [@boost:/libs/type_traits/examples/fill_example.cpp `fill_example.cpp`]), +a version of __std_fill__ is optimized in two ways: if the type +passed is a single byte built-in type then __std_memset__ is used to +effect the fill, otherwise a conventional C++ implementation is +used, but with the passed parameter "optimized" using +__call_traits__: + +``` +template +struct filler +{ + template + static void do_fill(I first, I last, typename __boost_call_traits__::param_type val) + { + while(first != last) + { + *first = val; + ++first; + } + } +}; + +template <> +struct filler +{ + template + static void do_fill(I first, I last, T val) + { + __std_memset__(first, val, last-first); + } +}; + +template +inline void fill(I first, I last, const T& val) +{ + enum { can_opt = boost::is_pointer::value + && boost::is_arithmetic::value + && (sizeof(T) == 1) }; + typedef filler filler_t; + filler_t::template do_fill(first, last, val); +} +``` + +The reason that this is "optimal" for small built-in types is that +with the value passed as `T const` instead of `const T&` the compiler is +able to tell both that the value is constant and that it is free +of aliases. With this information the compiler is able to cache +the passed value in a register, unroll the loop, or use +explicitly parallel instructions: if any of these are supported. +Exactly how much mileage you will get from this depends upon your +compiler - we could really use some accurate benchmarking +software as part of boost for cases like this. + +Note that the function arguments to fill are not expressed in +terms of __call_traits__: doing so would prevent template argument +deduction from functioning. Instead fill acts as a "thin +wrapper" that is there to perform template argument +deduction, the compiler will optimise away the call to fill all +together, replacing it with the call to `filler<>::do_fill`, +which does use __call_traits__. + +[endsect] +[endsect] + +[section Rationale] + +The following notes are intended to briefly describe the +rationale behind choices made in __call_traits__. + +All user-defined types follow "existing practice" and need no comment. + +Small built-in types, what the standard calls [@https://en.cppreference.com/w/cpp/language/types fundamental +types], differ from existing practice only in the `param_type` +`typedef`. In this case passing `T const` is compatible +with existing practice, but may improve performance in some cases +(see [link sec:example4 Example 4]). In any case this should never +be any worse than existing practice. + +Pointers follow the same rationale as small built-in types. + +For reference types the rationale follows [link sec:refs Example 2] +- references to references are not allowed, so the __call_traits__ +members must be defined such that these problems do +not occur. There is a proposal to modify the language such that +"a reference to a reference is a reference" (issue #106, +submitted by Bjarne Stroustrup). __call_traits_T__`::value_type` +and __call_traits_T__`::param_type` both provide the same effect +as that proposal, without the need for a language change. In +other words, it's a workaround. + +For array types, a function that takes an array as an argument +will degrade the array type to a pointer type: this means that +the type of the actual parameter is different from its declared +type, something that can cause endless problems in template code +that relies on the declared type of a parameter. + +For example: + +``` +template +struct A +{ + void foo(T t); +}; +``` + +In this case if we instantiate `A` then the declared type of +the parameter passed to member function `foo` is `int[2]`, but its +actual type is `const int*`. If we try to use the type `T` within the +function body, then there is a strong likelihood that our code will not compile: + +``` +template +void A::foo(T t) +{ + T dup(t); // doesn't compile for case that T is an array. +} +``` + +By using __call_traits__ the degradation from array to pointer is +explicit, and the type of the parameter is the same as it's +declared type: + +``` +template +struct A +{ + void foo(typename __call_traits__::value_type t); +}; + +template +void A::foo(typename __call_traits__::value_type t) +{ + typename __call_traits__::value_type dup(t); // OK even if T is an array type. +} +``` + +For `value_type` (return by value), again only a pointer may be +returned, not a copy of the whole array, and again __call_traits__ +makes the degradation explicit. The `value_type` member is useful +whenever an array must be explicitly degraded to a pointer - +[link sec:example3 Example 3] provides the test case. + +Footnote: the array specialisation for __call_traits__ is the least +well understood of all the __call_traits__ specialisations. If the given +semantics cause specific problems for you, or does not solve a particular +array-related problem, then I would be interested to hear about +it. Most people though will probably never need to use this +specialisation. + +[endsect] + +[/===============] +[xinclude tmp/call_traits_reference.xml] +[/===============] + +[endsect] diff --git a/libs/utility/doc/compressed_pair.qbk b/libs/utility/doc/compressed_pair.qbk new file mode 100644 index 00000000..154c8a76 --- /dev/null +++ b/libs/utility/doc/compressed_pair.qbk @@ -0,0 +1,98 @@ +[/ + Copyright 2000 Beman Dawes & John Maddock. + Copyright (c) 2021, Alan Freitas + + Distributed under the Boost Software License, Version 1.0. + + See accompanying file LICENSE_1_0.txt + or copy at http://boost.org/LICENSE_1_0.txt +] + +[section Compressed Pair] + +[section Introduction] + +All of the contents of [@../../../../boost/compressed_pair.hpp ``] are defined inside +`namespace boost`. + +The class __compressed_pair__ is very similar to __std_pair__. However, if either of +the template arguments are empty classes, then the +[@https://en.cppreference.com/w/cpp/language/ebo ['empty base-class optimisation]] +is applied to compress the size of the pair. + +[endsect] + +[section Synopsis] + +```cpp +template +class __compressed_pair__ +{ +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename __call_traits__::param_type first_param_type; + typedef typename __call_traits__::param_type second_param_type; + typedef typename __call_traits__::reference first_reference; + typedef typename __call_traits__::reference second_reference; + typedef typename __call_traits__::const_reference first_const_reference; + typedef typename __call_traits__::const_reference second_const_reference; + + compressed_pair() : base() {} + compressed_pair(first_param_type x, second_param_type y); + explicit compressed_pair(first_param_type x); + explicit compressed_pair(second_param_type y); + + compressed_pair& operator=(const compressed_pair&); + + first_reference first(); + first_const_reference first() const; + + second_reference second(); + second_const_reference second() const; + + void swap(compressed_pair& y); +}; +``` + +The two members of the pair can be accessed using the member functions +`first()` and `second()`. Note that not all member functions can be +instantiated for all template parameter types. In particular +__compressed_pair__ can be instantiated for reference and array types, +however in these cases the range of constructors that can be used is +limited. If types `T1` and `T2` are the same type, then there is only +one version of the single-argument constructor, and this constructor +initialises both values in the pair to the passed value. + +Note that if either member is a [@https://en.cppreference.com/w/cpp/named_req/PODType POD] +type, then that member is not zero-initialized by the __compressed_pair__ default constructor: +it is up to you to supply an initial value for these types if you want them to have +a default value. + +Note that __compressed_pair__ can not be instantiated if either of the +template arguments is a union type, unless there is compiler support for +[@boost:/libs/type_traits/index.html `boost::is_union`], or +if [@boost:/libs/type_traits/index.html `boost::is_union`] is +specialised for the union type. + +Finally, a word of caution for Visual C++ 6 users: if either argument is an +empty type, then assigning to that member will produce memory corruption, +unless the empty type has a "do nothing" assignment operator defined. This +is due to a bug in the way VC6 generates implicit assignment operators. + +[endsect] + +[/===============] +[xinclude tmp/compressed_pair_reference.xml] +[/===============] + +[section Acknowledgments] + +Based on contributions by Steve Cleary, Beman Dawes, Howard Hinnant and +John Maddock. + +Maintained by [@mailto:john@johnmaddock.co.uk John Maddock]. + +[endsect] + +[endsect] diff --git a/libs/utility/doc/in_place_factory.qbk b/libs/utility/doc/in_place_factory.qbk new file mode 100644 index 00000000..e69f3d66 --- /dev/null +++ b/libs/utility/doc/in_place_factory.qbk @@ -0,0 +1,308 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / + / 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) + /] + +[/===============] +[#sec:in_place_factory] +[section In-place Factory] +[/===============] + +[section Introduction] + +Suppose we have a class + +``` +struct X +{ + X ( int, __std_string__ ) ; +}; +``` + +And a container for it which supports an empty state. That is, a container which can contain zero objects: + +``` +struct C +{ + C() : contained_(0) {} + ~C() { delete contained_ ; } + X* contained_ ; +}; +``` + +A container designed to support an empty state typically does not require the contained type to be +__DefaultConstructible__, but it typically requires it to be __CopyConstructible__ as a mechanism to +initialize the object to store: + +``` +struct C +{ + C() : contained_(0) {} + C ( X const& v ) : contained_ ( new X(v) ) {} + ~C() { delete contained_ ; } + X* contained_ ; +}; +``` + +There is a subtle problem with this: since the mechanism used to initialize the stored object is copy construction, +there must exist a previously constructed source object to copy from. This object is likely to be temporary and serve +no purpose besides being the source: + +``` +void foo() +{ + // Temporary object created. + C c( X(123,"hello") ) ; +} +``` + +A solution to this problem is to support direct construction of the contained +object right in the container's storage. + +In this scheme, the user supplies the arguments for the `X` constructor +directly to the container: + +``` +struct C +{ + C() : contained_(0) {} + C ( X const& v ) : contained_ ( new X(v) ) {} + C ( int a0, __std_string__ a1 ) : contained_ ( new X(a0,a1) ) {} + ~C() { delete contained_ ; } + X* contained_ ; +}; +``` + +``` +void foo() +{ + // Wrapped object constructed in-place + // No temporary created. + C c(123,"hello"); +} +``` + +Clearly, this solution does not scale well since the container must duplicate all the constructor overloads +from the contained type, or at least all those which are to be supported directly in the container. + +[endsect] +[section Framework] + +This library proposes a framework to allow some containers to directly construct contained objects in-place without requiring +the entire set of constructor overloads from the contained type. It also allows the container to remove the __CopyConstructible__ +requirement from the contained type since objects can be directly constructed in-place without need of a copy. + +The only requirement on the container is that it must provide proper storage. That is, the container should be +correctly aligned and sized. Naturally, the container will typically support uninitialized storage to avoid the +in-place construction to override a fully-constructed object, as this would defeat the purpose of in-place construction. + +For this purpose, the framework provides two concepts called: InPlaceFactories and TypedInPlaceFactories. +Helpers to declare these classes are declared in [@../../../../boost/utility/in_place_factory.hpp ``] +and [@../../../../boost/utility/typed_in_place_factory.hpp ``]. + +Essentially, these classes hold a sequence of actual parameters and a method to construct an object in place using these parameters. +Each member of the family differs only in the number and type of the parameter list. The first family +takes the type of the object to construct directly in method provided for that +purpose, whereas the second family incorporates that type in the factory class +itself. From the container point of view, using the framework amounts to calling the +factory's method to contruct the object in place. From the user point of view, it amounts to creating +the right factory object to hold the parameters and pass it to the container. + +The following simplified example shows the basic idea. A complete example follows the formal specification of the framework: + +``` +struct C +{ + template + C ( InPlaceFactory const& aFactory ) + : + contained_ ( uninitialized_storage() ) + { + aFactory.template apply(contained_); + } + + ~C() + { + contained_ -> X::~X(); + delete[] contained_ ; + } + + char* uninitialized_storage() { return new char[sizeof(X)] ; } + + char* contained_ ; +}; + +void foo() +{ + C c( in_place(123,"hello") ) ; +} + +``` + +[endsect] +[section Specification] + +The following is the first member of the family of `InPlaceFactory` classes, along with its corresponding helper template function. +The rest of the family varies only in the number and type of template and constructor parameters. + + +``` +namespace boost { + +struct __in_place_factory_base__ {}; + +template +class in_place_factory : public __in_place_factory_base__ +{ + public: + in_place_factory ( A0 const& a0 ) : m_a0(a0) {} + + template< class T > + void apply ( void* address ) const + { + new (address) T(m_a0); + } + + private: + A0 const& m_a0 ; +}; + +template +in_place_factory in_place ( A0 const& a0 ) +{ + return in_place_factory(a0); +} + +} +``` + +Similarly, the following is the first member of the family of `typed_in_place_factory` classes, along with its corresponding +helper template function. The rest of the family varies only in the number and type of template and constructor parameters. + +``` +namespace boost { + +struct __typed_in_place_factory_base__ {}; + +template +class typed_in_place_factory : public __typed_in_place_factory_base__ +{ + public: + typed_in_place_factory ( A0 const& a0 ) : m_a0(a0) {} + + void apply ( void* address ) const + { + new (address) T(m_a0); + } + + private: + A0 const& m_a0 ; +}; + +template +typed_in_place_factory in_place ( A0 const& a0 ) +{ + return typed_in_place_factory(a0); +} +} +``` + +As you can see, the `in_place_factory` and `typed_in_place_factory` template classes vary only in the way they specify +the target type: in the first family, the type is given as a template argument to the apply member function while in the +second it is given directly as part of the factory class. + +When the container holds a unique non-polymorphic type, such as the case of [@boost:/libs/optional/index.html Boost.Optional], +it knows the exact dynamic-type of the contained object and can pass it to the `apply()` method of a non-typed factory. +In this case, end users can use an `in_place_factory` instance which can be constructed without the type of the object to construct. + +However, if the container holds heterogeneous or polymorphic objects, such as the case of [@boost:/libs/variant/index.html Boost.Variant], +the dynamic-type of the object to be constructed must be known by the factory. In this case, end users must use a `typed_in_place_factory` +instead. + +[endsect] +[section Container-side Usage] + +As shown in the introductory simplified example, the container class must contain methods that accept an instance of +these factories and pass the object's storage to the factory's apply method. + +However, the type of the factory class cannot be completely specified in the container class because that would +defeat the whole purpose of the factories which is to allow the container to accept a variadic argument list +for the constructor of its contained object. + +The correct function overload must be based on the only distinctive and common +characteristic of all the classes in each family: the base class. + +Depending on the container class, you can use `enable_if` to generate the right overload, or use the following +dispatch technique, which is used in the [@boost:/libs/optional/index.html Boost.Optional] class: + + +``` +struct C +{ + C() : contained_(0) {} + C ( X const& v ) : contained_ ( new X(v) ) {} + + template + C ( Expr const& expr ) + : + contained_ ( uninitialized_storage() ) + { + construct(expr,&expr); + } + + ~C() { delete contained_ ; } + + template + void construct ( InPlaceFactory const& aFactory, boost::__in_place_factory_base__* ) + { + aFactory.template apply(contained_); + } + + template + void construct ( TypedInPlaceFactory const& aFactory, boost::__typed_in_place_factory_base__* ) + { + aFactory.apply(contained_); + } + + X* uninitialized_storage() { return static_cast(new char[sizeof(X)]) ; } + + X* contained_ ; +}; +``` + +[endsect] +[section User-side Usage] + +End users pass to the container an instance of a factory object holding the actual parameters needed to construct the +contained object directly within the container. For this, the helper template function `in_place` is used. + +The call `in_place(a0,a1,a2,...,an)` constructs a (non-typed) `in_place_factory` instance with the given argument list. + +The call `in_place(a0,a1,a2,...,an)` constructs a `typed_in_place_factory` instance with the given argument list for the +type `T`. + +``` +void foo() +{ + C a( in_place(123, "hello") ) ; // in_place_factory passed + C b( in_place(456, "world") ) ; // typed_in_place_factory passed +} + +``` + +[endsect] + +[/===============] +[#boost.typed_in_place_factory_base] +[xinclude tmp/in_place_factory_reference.xml] +[/===============] + +[section Acknowledgments] + +Copyright Fernando Luis Cacciola Carballal, 2004 + +[endsect] +[endsect] diff --git a/libs/utility/doc/logo.png b/libs/utility/doc/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bd78a2b86b3889ec8ee7414e70a0d6b706f2609c GIT binary patch literal 10457 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 LQI)QdG70`4{$P^a literal 0 HcmV?d00001 diff --git a/libs/utility/doc/logo.svg b/libs/utility/doc/logo.svg new file mode 100644 index 00000000..41c47636 --- /dev/null +++ b/libs/utility/doc/logo.svg @@ -0,0 +1,539 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + UTILITY + + + + boost + + + + + + + + + diff --git a/libs/utility/doc/main.qbk b/libs/utility/doc/main.qbk new file mode 100644 index 00000000..f7574e12 --- /dev/null +++ b/libs/utility/doc/main.qbk @@ -0,0 +1,234 @@ +[/ + Copyright (c) 2021, Alan Freitas + + 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) + + Official repository: https://github.com/boostorg/utility +] + +[/############################################# + DOCUMENT INFO +###############################################] + +[library Boost.Utility + [id utility] + [quickbook 1.6] + [copyright 2001 Beman Dawes] + [purpose Utility Library] + [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]) + ] + [authors [Dawes, Beman]] + [category template] + [category generic] +] + +[template mdash[]'''—'''] +[template ndash[]'''–'''] +[template sect[]'''§'''] +[template hellip[]'''…'''] + +[template indexterm1[term1]''''''[term1]''''''] +[template indexterm2[term1 term2]''''''[term1]''''''[term2]''''''] + +[template include_file[path][^<''''''[path]''''''>]] +[template issue[n]'''#'''[n]''''''] + +[/ Named Requirements ] + +[def __Handler__ ['Handler]] +[def __Allocator__ [@https://en.cppreference.com/w/cpp/named_req/Allocator ['Allocator]]] +[def __CopyAssignable__ [@https://en.cppreference.com/w/cpp/named_req/CopyAssignable ['CopyAssignable]]] +[def __CopyConstructible__ [@https://en.cppreference.com/w/cpp/named_req/CopyConstructible ['CopyConstructible]]] +[def __Copyable__ [@https://en.cppreference.com/w/cpp/concepts/copyable ['Copyable]]] +[def __DefaultConstructible__ [@https://en.cppreference.com/w/cpp/named_req/DefaultConstructible ['DefaultConstructible]]] +[def __Hash__ [@https://en.cppreference.com/w/cpp/named_req/Hash ['Hash]]] +[def __InputIterator__ [@https://en.cppreference.com/w/cpp/named_req/InputIterator ['InputIterator]]] +[def __MoveAssignable__ [@https://en.cppreference.com/w/cpp/named_req/MoveAssignable ['MoveAssignable]]] +[def __MoveConstructible__ [@https://en.cppreference.com/w/cpp/named_req/MoveConstructible ['MoveConstructible]]] +[def __RandomAccessIterator__ [@https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator ['RandomAccessIterator]]] +[def __Regular__ [@https://en.cppreference.com/w/cpp/concepts/regular ['Regular]]] +[def __Swappable__ [@https://en.cppreference.com/w/cpp/named_req/Swappable ['Swappable]]] + +[/ Boost types ] +[/ (Macros are defined here because these macros are often referenced in other components) ] +[/ (operators macros link to the a table of operators because there's no doxygen reference for the operators) ] + +[def __BOOST_BINARY__ [link sec:BOOST_BINARY `BOOST_BINARY`]] +[def __in_place_factory__ [link sec:in_place_factory `in_place_factory`]] + +[def __boost_base_from_member__ [link boost.base_from_member `boost::base_from_member`]] +[def __boost_call_traits__ [link boost.call_traits `boost::call_traits`]] +[def __boost_result_of__ [link boost.result_of `boost::result_of`]] +[def __boost_tr1_result_of__ [link boost.tr1_result_of `boost::tr1_result_of`]] +[def __boost_string_view__ [link boost.basic_string_view `boost::string_view`]] +[def __boost_basic_string_view__ [link boost.basic_string_view `boost::basic_string_view`]] + +[def __additive1__ [link sec:arithmetic `additive1`]] +[def __additive2__ [link sec:arithmetic `additive2`]] +[def __arithmetic1__ [link sec:arithmetic `arithmetic1`]] +[def __arithmetic2__ [link sec:arithmetic `arithmetic2`]] +[def __base_from_member__ [link boost.base_from_member `base_from_member`]] +[def __basic_string_ref__ [link boost.basic_string_view `basic_string_ref`]] +[def __basic_string_view__ [link boost.basic_string_view `basic_string_view`]] +[def __bidirectional_iteratable__ [link sec:arithmetic `bidirectional_iteratable`]] +[def __bidirectional_iterator_helper__ [link sec:arithmetic `bidirectional_iterator_helper`]] +[def __bitwise1__ [link sec:arithmetic `bitwise1`]] +[def __bitwise2__ [link sec:arithmetic `bitwise2`]] +[def __call_traits__ [link boost.call_traits `call_traits`]] +[def __call_traits_T__ [link boost.call_traits `call_traits`]] +[def __call_traits_lt__T___ [link boost.call_traits `call_traits`]] +[def __call_traits_lt__T_lb_N_rb__gt___ [link boost.call_traits `call_traits< T[N]>`]] +[def __call_traits_lt__const_T_lb_N_rb__gt___ [link boost.call_traits `call_traits< const T[N]>`]] +[def __compressed_pair__ [link boost.compressed_pair `compressed_pair`]] +[def __decrementable__ [link sec:arithmetic `decrementable`]] +[def __dereferenceable__ [link sec:arithmetic `dereferenceable`]] +[def __equal_pointees__ [link sec:arithmetic `equal_pointees`]] +[def __equal_pointees_t__ [link sec:arithmetic `equal_pointees_t`]] +[def __equality_comparable1__ [link sec:arithmetic `equality_comparable1`]] +[def __equality_comparable2__ [link sec:arithmetic `equality_comparable2`]] +[def __equivalent1__ [link sec:arithmetic `equivalent1`]] +[def __equivalent2__ [link sec:arithmetic `equivalent2`]] +[def __euclidean_ring_operators1__ [link sec:arithmetic `euclidean_ring_operators1`]] +[def __euclidean_ring_operators2__ [link sec:arithmetic `euclidean_ring_operators2`]] +[def __field_operators1__ [link sec:arithmetic `field_operators1`]] +[def __field_operators2__ [link sec:arithmetic `field_operators2`]] +[def __forward_iteratable__ [link sec:arithmetic `forward_iteratable`]] +[def __forward_iterator_helper__ [link sec:arithmetic `forward_iterator_helper`]] +[def __get__ [link boost.get `get`]] +[def __hash_range__ [link boost.hash_range `hash_range`]] +[def __hash_value__ [link boost.hash_value `hash_value`]] +[def __in_place_factory_base__ [link boost.in_place_factory_base `in_place_factory_base`]] +[def __incrementable__ [link sec:arithmetic `incrementable`]] +[def __indexable__ [link sec:arithmetic `indexable`]] +[def __initialized__ [link boost.initialized `initialized`]] +[def __initialized_value__ [link boost.initialized_value `initialized_value`]] +[def __initialized_value_t__ [link boost.initialized_value_t `initialized_value_t`]] +[def __input_iteratable__ [link sec:arithmetic `input_iteratable`]] +[def __input_iterator_helper__ [link sec:arithmetic `input_iterator_helper`]] +[def __integer_arithmetic1__ [link sec:arithmetic `integer_arithmetic1`]] +[def __integer_arithmetic2__ [link sec:arithmetic `integer_arithmetic2`]] +[def __integer_multiplicative1__ [link sec:arithmetic `integer_multiplicative1`]] +[def __integer_multiplicative2__ [link sec:arithmetic `integer_multiplicative2`]] +[def __is_chained_base__ [link sec:arithmetic `is_chained_base`]] +[def __less_pointees__ [link boost.less_pointees `less_pointees`]] +[def __less_pointees_t__ [link boost.less_pointees_t `less_pointees_t`]] +[def __less_than_comparable1__ [link sec:arithmetic `less_than_comparable1`]] +[def __less_than_comparable2__ [link sec:arithmetic `less_than_comparable2`]] +[def __multiplicative1__ [link sec:arithmetic `multiplicative1`]] +[def __multiplicative2__ [link sec:arithmetic `multiplicative2`]] +[def __operator_eq__eq__ [link sec:arithmetic `operator==`]] +[def __operator_gt__ [link sec:arithmetic `operator_gt_`]] +[def __operator_gt__eq__ [link sec:arithmetic `operator>`]] +[def __operator_lt__ [link sec:arithmetic `operator<`]] +[def __operator_lt__eq__ [link sec:arithmetic `operator<=`]] +[def __operator_lt__lt__ [link sec:arithmetic `operator<<`]] +[def __operator_not__eq__ [link sec:arithmetic `operator!=`]] +[def __operators2__ [link sec:arithmetic `operators2`]] +[def __operators__ [link sec:arithmetic `operators`]] +[def __operators_lt_T__ [link sec:arithmetic `operators`]] +[def __ordered_euclidean_ring_operators1__ [link sec:arithmetic `ordered_euclidean_ring_operators1`]] +[def __ordered_euclidean_ring_operators2__ [link sec:arithmetic `ordered_euclidean_ring_operators2`]] +[def __ordered_euclidian_ring_operators1__ [link sec:arithmetic `ordered_euclidian_ring_operators1`]] +[def __ordered_euclidian_ring_operators2__ [link sec:arithmetic `ordered_euclidian_ring_operators2`]] +[def __ordered_field_operators1__ [link sec:arithmetic `ordered_field_operators1`]] +[def __ordered_field_operators2__ [link sec:arithmetic `ordered_field_operators2`]] +[def __ordered_ring_operators1__ [link sec:arithmetic `ordered_ring_operators1`]] +[def __ordered_ring_operators2__ [link sec:arithmetic `ordered_ring_operators2`]] +[def __output_iteratable__ [link sec:arithmetic `output_iteratable`]] +[def __output_iterator_helper__ [link sec:arithmetic `output_iterator_helper`]] +[def __partially_ordered1__ [link sec:arithmetic `partially_ordered1`]] +[def __partially_ordered2__ [link sec:arithmetic `partially_ordered2`]] +[def __random_access_iteratable__ [link sec:arithmetic `random_access_iteratable`]] +[def __random_access_iterator_helper__ [link sec:arithmetic `random_access_iterator_helper`]] +[def __result_of__ [link boost.result_of `result_of`]] +[def __ring_operators1__ [link sec:arithmetic `ring_operators1`]] +[def __ring_operators2__ [link sec:arithmetic `ring_operators2`]] +[def __shiftable1__ [link sec:arithmetic `shiftable1`]] +[def __shiftable2__ [link sec:arithmetic `shiftable2`]] +[def __string_ref__ [link boost.basic_string_view `string_ref`]] +[def __string_view__ [link boost.basic_string_view `string_view`]] +[def __swap__ [link sec:arithmetic `swap`]] +[def __totally_ordered1__ [link sec:arithmetic `totally_ordered1`]] +[def __totally_ordered2__ [link sec:arithmetic `totally_ordered2`]] +[def __tr1_result_of__ [link boost.tr1_result_of `tr1_result_of`]] +[def __typed_in_place_factory_base__ [link boost.typed_in_place_factory_base `typed_in_place_factory_base`]] +[def __u16string_ref__ [link boost.basic_string_view `u16string_ref`]] +[def __u16string_view__ [link boost.basic_string_view `u16string_view`]] +[def __u32string_ref__ [link boost.basic_string_view `u32string_ref`]] +[def __u32string_view__ [link boost.basic_string_view `u32string_view`]] +[def __unit_steppable__ [link sec:arithmetic `unit_steppable`]] +[def __value_initialized__ [link boost.value_initialized `value_initialized`]] +[def __wstring_ref__ [link boost.basic_string_view `wstring_ref`]] +[def __wstring_view__ [link boost.basic_string_view `wstring_view`]] + +[/ std:: types ] + +[def __assert__ [@https://en.cppreference.com/w/cpp/error/assert `assert`]] +[def __decltype__ [@https://en.cppreference.com/w/cpp/language/decltype `decltype`]] +[def __initializer_list__ [@https://en.cppreference.com/w/cpp/utility/initializer_list `std::initializer_list`]] +[def __nullptr__ [@https://en.cppreference.com/w/cpp/language/nullptr `nullptr`]] +[def __std_addressof__ [@https://en.cppreference.com/w/cpp/memory/addressof `std::addressof`]] +[def __std_array__ [@https://en.cppreference.com/w/cpp/container/array `std::array`]] +[def __std_basic_string__ [@https://en.cppreference.com/w/cpp/string/basic_string `std::basic_string`]] +[def __std_basic_string_view__ [@https://en.cppreference.com/w/cpp/string/basic_string_view `std::basic_string_view`]] +[def __std_binder1st__ [@https://en.cppreference.com/w/cpp/utility/functional/binder12 `std::binder1st`]] +[def __std_complex__ [@https://en.cppreference.com/w/cpp/numeric/complex `std::complex`]] +[def __std_declval__ [@https://en.cppreference.com/w/cpp/utility/declval `std::declval`]] +[def __std_enable_if__ [@https://en.cppreference.com/w/cpp/types/enable_if `std::enable_if`]] +[def __std_enable_if_t__ [@https://en.cppreference.com/w/cpp/types/enable_if `std::enable_if_t`]] +[def __std_fill__ [@https://en.cppreference.com/w/cpp/algorithm/fill `std::fill`]] +[def __std_hash__ [@https://en.cppreference.com/w/cpp/utility/hash `std::hash`]] +[def __std_initializer_list__ [@https://en.cppreference.com/w/cpp/utility/initializer_list `std::initializer_list`]] +[def __std_is_nothrow_constructible__ [@https://en.cppreference.com/w/cpp/types/is_constructible `std::is_nothrow_constructible`]] +[def __std_make_pair__ [@https://en.cppreference.com/w/cpp/utility/pair/make_pair `std::make_pair`]] +[def __std_memory_resource__ [@https://en.cppreference.com/w/cpp/memory/memory_resource `std::pmr::memory_resource`]] +[def __std_memset__ [@https://en.cppreference.com/w/cpp/string/byte/memset `std::memset`]] +[def __std_next__ [@https://en.cppreference.com/w/cpp/iterator/next `std::next`]] +[def __std_nullptr_t__ [@https://en.cppreference.com/w/cpp/types/nullptr_t `std::nullptr_t`]] +[def __std_ostream__ [@https://en.cppreference.com/w/cpp/io/basic_ostream `std::ostream`]] +[def __std_ostream__ [@https://en.cppreference.com/w/cpp/io/basic_ostream `__std_ostream__`]] +[def __std_pair__ [@https://en.cppreference.com/w/cpp/utility/pair `std::pair`]] +[def __std_polymorphic_allocator__ [@https://en.cppreference.com/w/cpp/memory/polymorphic_allocator `std::pmr::polymorphic_allocator`]] +[def __std_prev__ [@https://en.cppreference.com/w/cpp/iterator/prev `std::prev`]] +[def __std_ptrdiff_t__ [@https://en.cppreference.com/w/cpp/types/ptrdiff_t `std::ptrdiff_t`]] +[def __std_remove__ [@https://en.cppreference.com/w/cpp/algorithm/remove `std::remove`]] +[def __std_result_of__ [@https://en.cppreference.com/w/cpp/types/result_of `std::result_of`]] +[def __std_sort__ [@https://en.cppreference.com/w/cpp/algorithm/sort `std::sort`]] +[def __std_streambuf__ [@https://en.cppreference.com/w/cpp/header/streambuf `std::streambuf`]] +[def __std_string__ [@https://en.cppreference.com/w/cpp/string/basic_string `std::string`]] +[def __std_string_view__ [@https://en.cppreference.com/w/cpp/string/basic_string_view `std::string_view`]] +[def __std_unary_function__ [@https://en.cppreference.com/w/cpp/utility/functional/unary_function `std::unary_function`]] +[def __std_unordered_map__ [@https://en.cppreference.com/w/cpp/container/unordered_map `std::unordered_map`]] +[def __std_uses_allocator__ [@https://en.cppreference.com/w/cpp/memory/uses_allocator `std::uses_allocator`]] +[def __std_vector__ [@https://en.cppreference.com/w/cpp/container/vector `std::vector`]] + +[/ Dingbats ] + +[def __good__ [role green \u2714]] +[def __bad__ [role red \u2718]] + +[/-----------------------------------------------------------------------------] + +[include overview.qbk] + +[include utilities.qbk] + +[include other.qbk] + +[#sec:reference] +[section:ref Quick Reference] + +[/ Reference table ] +[xinclude quickref.xml] + +[/ Generated reference files ] +[/ [include reference.qbk] ] + +[/ Generated index ] +[/ [xinclude index.xml] ] + +[endsect] diff --git a/libs/utility/doc/operators.qbk b/libs/utility/doc/operators.qbk new file mode 100644 index 00000000..0e68f177 --- /dev/null +++ b/libs/utility/doc/operators.qbk @@ -0,0 +1,2008 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / + / 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) + /] + +[/===============] +[#sec:operators] +[section Operators] +[/===============] + +[section Introduction] + +The header [@../../../../boost/operators.hpp ``] supplies +several sets of class templates in `namespace boost`. These templates define +operators at namespace scope in terms of a minimal number of fundamental +operators provided by the class. + +[endsect] + +[#sec:rationale] +[section Rationale] + +Overloaded operators for class types typically occur in groups. If you +can write `x + y`, you probably also want to be able to write `x += y`. +If you can write `x < y,` you also want `x > y`, `x >= y,` and `x <= y`. + +Moreover, unless your class has really surprising behavior, some of these +related operators can be defined in terms of others (e.g. `x >= y` +is equivalent to `!(x < y)`). + +Replicating this boilerplate for multiple classes is both tedious and +error-prone. The [@../../../../boost/operators.hpp ``] templates +help by generating operators for you at namespace scope based on other +operators you have defined in your class. + +If, for example, you declare a class like this: + +``` +class MyInt + : boost::__operators__ +{ + bool operator<(const MyInt& x) const; + bool operator==(const MyInt& x) const; + MyInt& operator+=(const MyInt& x); + MyInt& operator-=(const MyInt& x); + MyInt& operator*=(const MyInt& x); + MyInt& operator/=(const MyInt& x); + MyInt& operator%=(const MyInt& x); + MyInt& operator|=(const MyInt& x); + MyInt& operator&=(const MyInt& x); + MyInt& operator^=(const MyInt& x); + MyInt& operator++(); + MyInt& operator--(); +}; +``` + +then the __operators__<> template adds more than a dozen additional operators, such as +`operator>`, `operator<=`, `operator>=`, and the binary `operator+`. + +[link sec:two_arg Two-argument forms] of the templates are also provided to allow interaction with other types. + +[#sec:semantics] +This is a ['Summary of Template Semantics]: + +# Each operator template completes the concept(s) it describes by defining overloaded operators for its target class. +# The name of an operator class template indicates the [link sec:concepts_note concept] that its target class will model. +# Usually, the target class uses an instantiation of the operator class template as a base class. Some operator templates support an + [link sec:explicit_instantiation alternate method]. +# The concept can be compound, i.e. it may represent a common combination of other, simpler concepts. +# Most operator templates require their target class to support operations related to the operators supplied by + the template. In accordance with widely accepted [@http://www.gotw.ca/gotw/004.htm coding style recommendations], the + target class is often required to supply the assignment counterpart operator of the concept's "main operator." + For example, the `addable` template requires `operator+=(T const&)` and in turn supplies `operator+(T const&, T const&)`. + +[#sec:concepts_note] + +['Note on the use of concepts]: The discussed concepts are not necessarily the standard library's +concepts, such as __CopyConstructible__, although some of them could +be; they are what we call ['concepts with a small 'c']. In +particular, they are different from the former ones in that they ['do +not] describe precise semantics of the operators they require to be +defined, except the requirements that (a) the semantics of the operators +grouped in one concept should be consistent (e.g. effects of +evaluating of `a += b` and `a = a + b` expressions should be the +same), and (b) that the return types of the operators should follow +semantics of return types of corresponding operators for built-in types +(e.g. `operator<` should return a type convertible to `bool`, and +`T::operator-=` should return type convertible to `T`). Such "loose" +requirements make `operators` library applicable to broader set of +target classes from different domains, i.e. eventually more useful. + +[endsect] + +[#sec:example] +[section Example] + +This example shows how some of the [link sec:arithmetic arithmetic +operator templates] can be used with a geometric point class +template. + +``` +template +class point // note: private inheritance is OK here! + : boost::addable< point // point + point + , boost::subtractable< point // point - point + , boost::dividable2< point, T // point / T + , boost::multipliable2< point, T // point * T, T * point + > > > > +{ +public: + point(T, T); + T x() const; + T y() const; + + point operator+=(const point&); + // point operator+(point, const point&) automatically + // generated by addable. + + point operator-=(const point&); + // point operator-(point, const point&) automatically + // generated by subtractable. + + point operator*=(T); + // point operator*(point, const T&) and + // point operator*(const T&, point) auto-generated + // by multipliable. + + point operator/=(T); + // point operator/(point, const T&) auto-generated + // by dividable. +private: + T x_; + T y_; +}; + +// now use the point<> class: +template +T length(const point p) +{ + return sqrt(p.x()*p.x() + p.y()*p.y()); +} + +const point right(0, 1); +const point up(1, 0); +const point pi_over_4 = up + right; +const point pi_over_4_normalized = pi_over_4 / length(pi_over_4); +``` + +[endsect] + +[#sec:usage] +[section Usage] + +[#sec:two_arg] +[h5 Two-Argument Template Forms] + +[#sec:two_arg_gen] + +The arguments to a binary operator commonly have identical types, but +it is not unusual to want to define operators which combine different +types. For [link sec:example example], one might want to multiply a +mathematical vector by a scalar. The two-argument template forms of the +arithmetic operator templates are supplied for this purpose. When +applying the two-argument form of a template, the desired return type of +the operators typically determines which of the two types in question +should be derived from the operator template. + +For example, if the result of `T + U` is of type `T`, then `T` (not `U`) +should be derived from [link table:addable2 `addable`]. The comparison +templates [link table:less_than_comparable2 `less_than_comparable`], +[link table:equality_comparable2 `equality_comparable`], +[link table:equivalent2 `equivalent`], and +[link table:partially_ordered2 `partially_ordered`] are exceptions to +this guideline, since the return type of the operators they define is `bool`. + +On compilers which do not support partial specialization, the +two-argument forms must be specified by using the names shown below with +the trailing `'2'`. The single-argument forms with the +trailing `'1'` are provided for symmetry and to enable certain +applications of the [link sec:chaining base class chaining] +technique. + +[#sec:mixed_arithmetics] + +['Mixed Arithmetics]: Another application of the + two-argument template forms is for mixed +arithmetics between a type `T` and a type `U` that +is convertible to `T`. In this case there are two ways where +the two-argument template forms are helpful: one is to provide the +respective signatures for operator overloading, the second is +performance. + +With respect to the operator overloading assume e.g. that +`U` is `int`, that `T` is an user-defined unlimited integer type, +and that `double operator-(double, const T&)` exists. + +If one wants to compute `int - T` and does not provide +`T operator-(int, const T&)`, the compiler will consider +`double operator-(double, const T&)` to be a better match +than `T operator-(const T&, const T&)`, which will probably +be different from the user's intention. + +To define a complete set of operator signatures, additional 'left' +forms of the two-argument template forms are provided +[link table:subtractable2_left `subtractable2_left`], +[link table:dividable2_left `dividable2_left`], and +[link table:modable2_left `modable2_left`] that +define the signatures for non-commutative operators where + `U` appears on the left hand side (`operator-(const U&, const T&)`, +`operator/(const U&, const T&)`, `operator%(const U&, const T&)`). + +With respect to the performance observe that when one uses the single +type binary operator for mixed type arithmetics, the type `U` +argument has to be converted to type `T`. In practice, +however, there are often more efficient implementations of, say +`T::operator-=(const U&)` that avoid unnecessary conversions +from `U` to `T`. + +The two-argument template forms of the arithmetic operator create +additional operator interfaces that use these more efficient implementations. +There is, however, no performance gain in the 'left' forms: they still need a +conversion from `U` to `T` and have an implementation equivalent to the code +that would be automatically created by the compiler if it considered the +single type binary operator to be the best match. + +[#sec:chaining] +[h5 Base Class Chaining and Object Size] + +Every operator class template, except the [link sec:ex_oprs arithmetic examples] +and the [link sec:iterator iterator helpers], has an additional, but optional, +template type parameter `B`. This parameter will be a publicly-derived base class of +the instantiated template. This means it must be a class type. It can be +used to avoid the bloating of object sizes that is commonly associated +with multiple-inheritance from several empty base classes. See the +[link sec:old_lib_note note for users of older versions] for more +details. + +To provide support for a group of operators, use the +`B` parameter to chain operator templates into a single-base +class hierarchy, demostrated in the [link sec:example usage example]. +The technique is also used by the composite operator templates to group +operator definitions. If a chain becomes too long for the compiler to +support, try replacing some of the operator templates with a single +grouped operator template that chains the old templates together; the +length limit only applies to the number of templates directly in the +chain, not those hidden in group templates. + +['Caveat]: to chain to a base class which is ['not] a Boost operator +template when using the [link sec:two_arg single-argument form] of a Boost +operator template, you must specify the operator template with the +trailing `'1'` in its name. Otherwise the library will assume you mean +to define a binary operation combining the class you intend to use as +a base class and the class you're deriving. + +[#sec:explicit_instantiation] +[h5 Separate Explicit Instantiation] + +On some compilers (e.g. Borland, GCC) even single-inheritance +seems to cause an increase in object size in some cases. If you are not +defining a class template, you may get better object-size performance by +avoiding derivation altogether, and instead explicitly instantiating the +operator template as follows: + +``` +class my_class // lose the inheritance... +{ + //... +}; + +// explicitly instantiate the operators I need. +template struct less_than_comparable; +template struct equality_comparable; +template struct incrementable; +template struct decrementable; +template struct addable; +template struct subtractable; +``` + + + +Note that some operator templates cannot use this workaround and must +be a base class of their primary operand type. Those templates define +operators which must be member functions, and the workaround needs the +operators to be independent `friend` functions. The relevant templates +are: + +* [link table:dereferenceable `dereferenceable<>`] +* [link table:indexable `indexable<>`] +* Any composite operator template that includes at least one of the above + +As Daniel Krugler pointed out, this technique violates C++11 [sect]14.6.5/2 \[temp.inject\] +and is thus non-portable. The reasoning is, that the operators injected by the instantiation +of e.g. `less_than_comparable` can not be found by ADL according to the +rules given by C++11 [sect]3.4.2/2 \[basic.lookup.argdep\], since `my_class` is not +an associated class of `less_than_comparable`. Thus only use this technique +if all else fails. + +[#sec:portability] +[h5 Requirement Portability] + +Many compilers (e.g. MSVC 6.3, GCC 2.95.2) will not enforce the +requirements in the operator template tables unless the operations which +depend on them are actually used. This is not standard-conforming +behavior. In particular, although it would be convenient to derive all +your classes which need binary operators from the [link table:operators1 `operators<>`] +and [link table:operators2 `operators2<>`] templates, regardless of +whether they implement all the requirements of those templates, this +shortcut is not portable. Even if this currently works with your +compiler, it may not work later. + +[endsect] + +[#sec:arithmetic] +[section Arithmetic Operators] + +The arithmetic operator templates ease the task of creating a custom +numeric type. Given a core set of operators, the templates add related +operators to the numeric class. These operations are like the ones the +standard arithmetic types have, and may include comparisons, adding, +incrementing, logical and bitwise manipulations, etc. Further, +since most numeric types need more than one of these operators, some +templates are provided to combine several of the basic operator templates +in one declaration. + +The requirements for the types used to instantiate the simple operator +templates are specified in terms of expressions which must be valid and +the expression's return type. The composite operator templates only list +what other templates they use. The supplied operations and requirements +of the composite operator templates can be inferred from the operations +and requirements of the listed components. + +[#sec:smpl_oprs] +[h5 Simple Arithmetic Operators] + +These templates are "simple" since they provide operators based on a +single operation the base type has to provide. They have an additional +optional template parameter `B`, which is not shown, for the +[link sec:chaining base class chaining] technique. + +The primary operand type `T` needs to be of class type, +built-in types are not supported. + +[table Notation + [[Key] [Description]] + [[`T`] [primary operand type]] + [[`t,t1`] [values of type `T`]] + [[`U`] [alternate operand type]] + [[`u`] [value of type `U`]] +] + +[table Simple Arithmetic Operator Template Classes + [[Template] [Supplied Operations] [Requirements] [Propagates constexpr]] + [ + [ + [#table:less_than_comparable1] `less_than_comparable` + + __less_than_comparable1__`` + ] + + [ + `bool operator>(const T&, const T&)` + + `bool operator<=(const T&, const T&)` + + `bool operator>=(const T&, const T&)` + ] + + [ + `t < t1`. + + Return convertible to `bool`. See the [link sec:ordering Ordering Note] + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:less_than_comparable2]`less_than_comparable` + + __less_than_comparable2__`` + ] + + [ + `bool operator<=(const T&, const U&)` + + `bool operator>=(const T&, const U&)` + + `bool operator>(const U&, const T&)` + + `bool operator<(const U&, const T&)` + + `bool operator<=(const U&, const T&)` + + `bool operator>=(const U&, const T&)` + ] + + [ + `t < u`. `t > u`. + + Returns convertible to `bool`. See the [link sec:ordering Ordering Note]. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:equality_comparable1]`equality_comparable` + + __equality_comparable1__`` + ] + + [ + `bool operator!=(const T&, const T&)` + ] + + [ + `t == t1`. + + Return convertible to `bool`. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:equality_comparable2]`equality_comparable` + + __equality_comparable2__`` + ] + + [ + `bool operator==(const U&, const T&)` + + `bool operator!=(const U&, const T&)` + + `bool operator!=(const T&, const U&)` + ] + + [ + `t == u`. + + Return convertible to `bool`. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:addable1]`addable` + + `addable1` + ] + + [ + `T operator+(const T&, const T&)` + ] + + [ + `T temp(t); temp += t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:addable2]`addable` + + `addable2` + ] + + [ + `T operator+(const T&, const U&)` + + `T operator+(const U&, const T& )` + ] + + [ + `T temp(t); temp += u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:subtractable1]`subtractable` + + `subtractable1` + ] + + [ + `T operator-(const T&, const T&)` + ] + + [ + `T temp(t); temp -= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:subtractable2]`subtractable` + + `subtractable2` + ] + + [ + `T operator-(const T&, const U&)` + ] + + [ + `T temp(t); temp -= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:subtractable2_left]`subtractable2_left` + ] + + [ + `T operator-(const U&, const T&)` + ] + + [ + `T temp(u); temp -= t`. + + Return convertible to `T`. + ] + + [No] + ] + + [ + [ + [#table:multipliable1]`multipliable` + + `multipliable1` + ] + + [ + `T operator*(const T&, const T&)` + ] + + [ + `T temp(t); temp *= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:multipliable2]`multipliable` + + `multipliable2` + ] + + [ + `T operator*(const T&, const U&)` + + `T operator*(const U&, const T&)` + ] + + [ + `T temp(t); temp *= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:dividable1]`dividable` + + `dividable1` + ] + + [ + `T operator/(const T&, const T&)` + ] + + [ + `T temp(t); temp /= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:dividable2]`dividable` + + `dividable2` + ] + + [ + `T operator/(const T&, const U&)` + ] + + [ + `T temp(t); temp /= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:dividable2_left]`dividable2_left` + ] + + [ + `T operator/(const U&, const T&)` + ] + + [ + `T temp(u); temp /= t`. + + Return convertible to `T`. + ] + + [No] + ] + + [ + [ + [#table:modable1]`modable` + + `modable1` + ] + + [ + `T operator%(const T&, const T&)` + ] + + [ + `T temp(t); temp %= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:modable2]`modable` + + `modable2` + ] + + [ + `T operator%(const T&, const U&)` + ] + + [ + `T temp(t); temp %= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:modable2_left]`modable2_left` + ] + + [ + `T operator%(const U&, const T&)` + ] + + [ + `T temp(u); temp %= t`. + + Return convertible to `T`. + ] + + [No] + ] + + [ + [ + [#table:orable1]`orable` + + `orable1` + ] + + [ + `T operator|(const T&, const T&)` + ] + + [ + `T temp(t); temp |= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:orable2]`orable` + + `orable2` + ] + + [ + `T operator|(const T&, const U&)` + + `T operator|(const U&, const T&)` + ] + + [ + `T temp(t); temp |= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:andable1]`andable` + + `andable1` + ] + + [ + `T operator&(const T&, const T&)` + ] + + [ + `T temp(t); temp &= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:andable2]`andable` + + `andable2` + ] + + [ + `T operator&(const T&, const U&)` + + `T operator&(const U&, const T&)` + ] + + [ + `T temp(t); temp &= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:xorable1]`xorable` + + `xorable1` + ] + + [ + `T operator^(const T&, const T&)` + ] + + [ + `T temp(t); temp ^= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:xorable2]`xorable` + + `xorable2` + ] + + [ + `T operator^(const T&, const U&)` + + `T operator^(const U&, const T&)` + ] + + [ + `T temp(t); temp ^= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:incrementable]`incrementable` + ] + + [ + `T operator++(T&, int)` + ] + + [ + `T temp(t); ++t` + + Return convertible to `T`. + ] + + [No] + ] + + [ + [ + [#table:decrementable]`decrementable` + ] + + [ + `T operator--(T&, int)` + ] + + [ + `T temp(t); --t;` + + Return convertible to `T`. + ] + + [No] + ] + + [ + [ + [#table:left_shiftable1]`left_shiftable` + + `left_shiftable1` + ] + + [ + `T operator<<(const T&, const T&)` + ] + + [ + `T temp(t); temp <<= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:left_shiftable2]`left_shiftable` + + `left_shiftable2` + ] + + [ + `T operator<<(const T&, const U&)` + ] + + [ + `T temp(t); temp <<= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:right_shiftable1]`right_shiftable` + + `right_shiftable1` + ] + + [ + `T operator>>(const T&, const T&)` + ] + + [ + `T temp(t); temp >>= t1`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:right_shiftable2]`right_shiftable` + + `right_shiftable2` + ] + + [ + `T operator>>(const T&, const U&)` + ] + + [ + `T temp(t); temp >>= u`. + + Return convertible to `T`. See the [link sec:symmetry Symmetry Note]. + ] + + [No] + ] + + [ + [ + [#table:equivalent1]`equivalent` + + __equivalent1__`` + ] + + [ + `bool operator==(const T&, const T&)` + ] + + [ + `t < t1`. + + Return convertible to `bool`. See the [link sec:ordering Ordering Note]. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:equivalent2]`equivalent` + + __equivalent2__`` + ] + + [ + `bool operator==(const T&, const U&)` + ] + + [ + `t < u`. `t > u`. + + Returns convertible to `bool`. See the [link sec:ordering Ordering Note]. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:partially_ordered1]`partially_ordered` + + __partially_ordered1__`` + ] + + [ + `bool operator>(const T&, const T&)` + + `bool operator<=(const T&, const T&)` + + `bool operator>=(const T&, const T&)` + ] + + [ + `t < t1`. `t == t1`. + + Returns convertible to `bool`. See the [link sec:ordering Ordering Note]. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] + + [ + [ + [#table:partially_ordered2]`partially_ordered` + + __partially_ordered2__`` + ] + + [ + `bool operator<=(const T&, const U&)` + + `bool operator>=(const T&, const U&)` + + `bool operator>(const U&, const T&)` + + `bool operator<(const U&, const T&)` + + `bool operator<=(const U&, const T&)` + + `bool operator>=(const U&, const T&)` + ] + + [ + `t < u`. `t > u`. `t == u`. + + Returns convertible to `bool`. See the [link sec:ordering Ordering Note]. + ] + + [ + Since `C++11`, except [@https://developercommunity.visualstudio.com/content/problem/414193/rejects-valid-constexpr-marked-friend-function-def.html MSVC < v19.22] + ] + ] +] + +[#sec:ordering] +['Ordering Note]: The [link table:less_than_comparable1 `less_than_comparable`] and +[link table:partially_ordered1 `partially_ordered`] templates provide the same set +of operations. However, the workings of [link table:less_than_comparable1 `less_than_comparable`] assume +that all values of type `T` can be placed in a total order. If +that is not true (e.g. Not-a-Number values in IEEE floating point +arithmetic), then [link table:partially_ordered1 `partially_ordered`] should be +used. The [link table:partially_ordered1 `partially_ordered`] template can +be used for a totally-ordered type, but it is not as efficient as +[link table:less_than_comparable1 `less_than_comparable`]. This +rule also applies for [link table:less_than_comparable2 `less_than_comparable`] and +[link table:partially_ordered2 `partially_ordered`] with respect to the ordering +of all `T` and `U` values, and for both versions of +[link table:equivalent1 `equivalent<>`]. The solution for +[link table:equivalent1 `equivalent<>`] is to write a custom +`operator==` for the target class. + +[#sec:symmetry] +['Symmetry Note]: Before talking about symmetry, we need to talk about optimizations to +understand the reasons for the different implementation styles of +operators. Let's have a look at `operator+` for a class +`T` as an example: + +``` +T operator+( const T& lhs, const T& rhs ) +{ + return T( lhs ) += rhs; +} +``` + +This would be a normal implementation of `operator+`, but it +is not an efficient one. An unnamed local copy of `lhs` is +created, `operator+=` is called on it and it is copied to the +function return value (which is another unnamed object of type +`T`). The standard doesn't generally allow the intermediate +object to be optimized away: + +[:['C++11 [sect]3.7.3/3 \[basic.stc.auto\]: Automatic storage duration:] If a variable with automatic storage +duration has initialization or a destructor with side effects, it shall not be destroyed before the end of +its block, nor shall it be eliminated as an optimization even if it appears to be unused, except that a class +object or its copy/move may be eliminated as specified in 12.8.] + +The reference to [sect]12.8 is important for us: + +[:['C++11 [sect]12.8/31 \[class.copy\]: Copying and moving class objects:] When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class +object, even if the copy/move constructor and/or destructor for the object have side effects. ([hellip]) This elision of copy/move +operations, called ['copy elision], is permitted in the following circumstances (which may be combined to +eliminate multiple copies): + +[mdash] in a `return` statement in a function with a class return type, when the expression is the name of a +non-volatile automatic object (other than a function or catch-clause parameter) with the same cv- +unqualified type as the function return type, the copy/move operation can be omitted by constructing +the automatic object directly into the function's return value + +([hellip])] + +This optimization is known as the named return value optimization ([@https://en.cppreference.com/w/cpp/language/copy_elision#Non-mandatory_elision_of_copy.2Fmove_.28since_C.2B.2B11.29_operations NRVO]), +which leads us to the following implementation for `operator+`: + +``` +T operator+( const T& lhs, const T& rhs ) +{ + T nrv( lhs ); + nrv += rhs; + return nrv; +} +``` + +Given this implementation, the compiler is allowed to remove the +intermediate object. Sadly, not all compilers implement the NRVO, some +even implement it in an incorrect way which makes it useless here. +Without the NRVO, the NRVO-friendly code is no worse than the original +code showed above, but there is another possible implementation, which +has some very special properties: + +``` +T operator+( T lhs, const T& rhs ) +{ + return lhs += rhs; +} +``` + +The difference to the first implementation is that `lhs` is +not taken as a constant reference used to create a copy; instead, +`lhs` is a by-value parameter, thus it is already the copy +needed. This allows another optimization (C++11 [sect]12.2/2 \[class.temporary\]) +for some cases. + +Consider `a + b + c` where the result of `a + b` is not copied when +used as `lhs` when adding `c`. This is more efficient than the original +code, but not as efficient as a compiler using the NRVO. For most people, +it is still preferable for compilers that don't implement the NRVO, but +the `operator+` now has a different function signature. Also, +the number of objects created differs for `(a + b) + c` and `a + (b + c)`. + +Most probably, this won't be a problem for you, but if your code relies on the function +signature or a strict symmetric behaviour, you should set +`BOOST_FORCE_SYMMETRIC_OPERATORS` in your user-config. This +will force the NRVO-friendly implementation to be used even for compilers +that do not implement the NRVO. + +[#sec:grpd_oprs] +[h5 Grouped Arithmetic Operators] + +The following templates provide common groups of related operations. +For example, since a type which is addable is usually also subtractable, +the [link table:additive1 `additive`] template provides the +combined operators of both. The grouped operator templates have an +additional optional template parameter `B`, which is not +shown, for the [link sec:chaining base class chaining] technique. + +[table Notation + [[Key] [Description]] + [[`T`] [primary operand type]] + [[`U`] [alternate operand type]] +] + +[table Grouped Arithmetic Operator Template Classes + [ + [Template] + + [Component Operator Templates] + ] + [ + [ + [#table:totally_ordered1] `totally_ordered` + + __totally_ordered1__`` + ] + [ + [link table:less_than_comparable1 `less_than_comparable`] + + [link table:equality_comparable1 `equality_comparable`] + ] + ] + [ + [ + [#table:totally_ordered2]`totally_ordered` + + __totally_ordered2__`` + ] + [ + [link table:less_than_comparable2 `less_than_comparable`] + + [link table:equality_comparable2 `equality_comparable`] + ] + ] + [ + [ + [#table:additive1]`additive` + + __additive1__`` + ] + [ + [link table:addable1 `addable`] + + [link table:subtractable1 `subtractable`] + ] + ] + [ + [ + [#table:additive2]`additive` + + __additive2__`` + ] + [ + [link table:addable2 `addable`] + + [link table:subtractable2 `subtractable`] + ] + ] + [ + [ + [#table:multiplicative1] `multiplicative` + + __multiplicative1__`` + ] + [ + [link table:multipliable1 `multipliable`] + + [link table:dividable1 `dividable`] + ] + ] + [ + [ + [#table:multiplicative2]`multiplicative` + + __multiplicative2__`` + ] + [ + [link table:multipliable2 `multipliable`] + + [link table:dividable2 `dividable`] + ] + ] + [ + [ + [#table:integer_multiplicative1] `integer_multiplicative` + + __integer_multiplicative1__`` + ] + [ + [link table:multiplicative1 `multiplicative`] + + [link table:modable1 `modable`] + ] + ] + [ + [ + [#table:integer_multiplicative2] `integer_multiplicative` + + __integer_multiplicative2__`` + ] + [ + [link table:multiplicative2 `multiplicative`] + + [link table:modable2 `modable`] + ] + ] + [ + [ + [#table:arithmetic1]`arithmetic` + + __arithmetic1__`` + ] + [ + [link table:additive1 `additive`] + + [link table:multiplicative1 `multiplicative`] + ] + ] + [ + [ + [#table:arithmetic2]`arithmetic` + + __arithmetic2__`` + ] + [ + [link table:additive2 `additive`] + + [link table:multiplicative2 `multiplicative`] + ] + ] + [ + [ + [#table:integer_arithmetic1] `integer_arithmetic` + + __integer_arithmetic1__`` + ] + [ + [link table:additive1 `additive`] + + [link table:integer_multiplicative1 `integer_multiplicative`] + ] + ] + [ + [ + [#table:integer_arithmetic2]`integer_arithmetic` + + __integer_arithmetic2__`` + ] + [ + [link table:additive2 `additive`] + + [link table:integer_multiplicative2 `integer_multiplicative`] + ] + ] + [ + [ + [#table:bitwise1]`bitwise` + + __bitwise1__`` + ] + [ + [link table:xorable1 `xorable`] + + [link table:andable1 `andable`] + + [link table:orable1 `orable`] + ] + ] + [ + [ + [#table:bitwise2]`bitwise` + + __bitwise2__`` + ] + [ + [link table:xorable2 `xorable`] + + [link table:andable2 `andable`] + + [link table:orable2 `orable`] + ] + ] + [ + [ + [#table:unit_steppable] `unit_steppable` + ] + [ + [link table:incrementable `incrementable`] + + [link table:decrementable `decrementable`] + ] + ] + [ + [ + [#table:shiftable1]`shiftable` + + __shiftable1__`` + ] + [ + [link table:left_shiftable1 `left_shiftable`] + + [link table:right_shiftable1 `right_shiftable`] + ] + ] + [ + [ + [#table:shiftable2]`shiftable` + + __shiftable2__`` + ] + [ + [link table:left_shiftable2 `left_shiftable`] + + [link table:right_shiftable2 `right_shiftable`] + ] + ] + [ + [ + [#table:ring_operators1] `ring_operators` + + __ring_operators1__`` + ] + [ + [link table:additive1 `additive`] + + [link table:multipliable1 `multipliable`] + ] + ] + [ + [ + [#table:ring_operators2]`ring_operators` + + __ring_operators2__`` + ] + [ + [link table:additive2 `additive`] + + [link table:subtractable2_left `subtractable2_left`] + + [link table:multipliable2 `multipliable`] + ] + ] + [ + [ + [#table:ordered_ring_operators1] `ordered_ring_operators` + + __ordered_ring_operators1__`` + ] + [ + [link table:ring_operators1 `ring_operators`] + + [link table:totally_ordered1 `totally_ordered`] + ] + ] + [ + [ + [#table:ordered_ring_operators2] `ordered_ring_operators` + + __ordered_ring_operators2__`` + ] + [ + [link table:ring_operators2 `ring_operators`] + + [link table:totally_ordered2 `totally_ordered`] + ] + ] + [ + [ + [#table:field_operators1]`field_operators` + + __field_operators1__`` + ] + [ + [link table:ring_operators1 `ring_operators`] + + [link table:dividable1 `dividable`] + ] + ] + [ + [ + [#table:field_operators2]`field_operators` + + __field_operators2__`` + ] + [ + [link table:ring_operators2 `ring_operators`] + + [link table:dividable2 `dividable`] + + [link table:dividable2_left `dividable2_left`] + ] + ] + [ + [ + [#table:ordered_field_operators1]`ordered_field_operators` + + __ordered_field_operators1__`` + ] + [ + [link table:field_operators1 `field_operators`] + + [link table:totally_ordered1 `totally_ordered`] + ] + ] + [ + [ + [#table:ordered_field_operators2]`ordered_field_operators` + + __ordered_field_operators2__`` + ] + [ + [link table:field_operators2 `field_operators`] + + [link table:totally_ordered2 `totally_ordered`] + ] + ] + [ + [ + [#table:euclidean_ring_operators1]`euclidean_ring_operators` + + __euclidean_ring_operators1__`` + ] + [ + [link table:ring_operators1 `ring_operators`] + + [link table:dividable1 `dividable`] + + [link table:modable1 `modable`] + ] + ] + [ + [ + [#table:euclidean_ring_operators2] `euclidean_ring_operators` + + __euclidean_ring_operators2__`` + ] + [ + [link table:ring_operators2 `ring_operators`] + + [link table:dividable2 `dividable`] + + [link table:dividable2_left `dividable2_left`] + + [link table:modable2 `modable`] + + [link table:modable2_left `modable2_left`] + ] + ] + [ + [ + [#table:ordered_euclidean_ring_operators1] `ordered_euclidean_ring_operators` + + __ordered_euclidean_ring_operators1__`` + ] + [ + [link table:euclidean_ring_operators1 `euclidean_ring_operators`] + + [link table:totally_ordered1 `totally_ordered`] + ] + ] + [ + [ + [#table:ordered_euclidean_ring_operators2]`ordered_euclidean_ring_operators` + + __ordered_euclidean_ring_operators2__`` + ] + [ + [link table:euclidean_ring_operators2 `euclidean_ring_operators`] + + [link table:totally_ordered2 `totally_ordered`] + ] + ] +] + +['Spelling: euclidean vs. euclidian]: Older versions of the +Boost.Operators library used "`euclidian`", but it was pointed out that +"`euclidean`" is the more common spelling. To be compatible with older +version, the library now supports both spellings. + +[#sec:ex_oprs] +[h5 Example Templates] + +The arithmetic operator class templates [link table:operators1 `operators<>`] and +[link table:operators2 `operators2<>`] are examples of non-extensible operator +grouping classes. These legacy class templates, from previous versions +of the header, cannot be used for [link sec:chaining base class chaining]. + +[table Notation + [[Key] [Description]] + [[`T`] [primary operand type]] + [[`U`] [alternate operand type]] +] + +[table Final Arithmetic Operator Template Classes + [ + [Template] + + [Component Operator Templates] + ] + [ + [ + [#table:operators1]__operators__`` + ] + [ + [link table:totally_ordered1 `totally_ordered`] + + [link table:integer_arithmetic1 `integer_arithmetic`] + + [link table:bitwise1 `bitwise`] + + [link table:unit_steppable `unit_steppable`] + ] + ] + [ + [ + [#table:operators2]__operators__`` + + __operators2__`` + ] + [ + [link table:totally_ordered2 `totally_ordered`] + + [link table:integer_arithmetic2 `integer_arithmetic`] + + [link table:bitwise2 `bitwise`] + ] + ] +] + +[#sec:a_demo] +['Arithmetic Operators Demonstration and Test Program]: The +[@../../../test/operators_test.cpp `operators_test.cpp`] +program demonstrates the use of the arithmetic operator templates, and +can also be used to verify correct operation. Check the compiler status +report for the test results with selected platforms. + +[endsect] + +[#sec:deref] +[section Dereference Operators and Iterator Helpers] + +The [link sec:iterator iterator helper] templates ease the task of +creating a custom iterator. Similar to arithmetic types, a complete +iterator has many operators that are "redundant" and can be implemented +in terms of the core set of operators. + +The [link sec:dereference dereference operators] were motivated by +the [link sec:iterator iterator helpers], but are often useful in +non-iterator contexts as well. Many of the redundant iterator operators +are also arithmetic operators, so the iterator helper classes borrow many +of the operators defined above. In fact, only two new operators need to +be defined: the pointer-to-member `operator->` and the +subscript `operator[]`. + +The requirements for the types used to instantiate the dereference +operators are specified in terms of expressions which must be valid and +their return type. The composite operator templates list their component +templates, which the instantiating type must support, and possibly other +requirements. + +[#sec:dereference] +[h5 Dereference Operators] + +All the dereference operator templates in this table accept an +optional template parameter (not shown) to be used for +[link sec:chaining base class chaining]. + +[table Notation + [[Key] [Description]] + [[`T`] [operand type]] + [[`D`] [`difference_type`]] + [[`i`] [object of type `T` (an iterator)]] + [[`P`] [`pointer` type]] + [[`R`] [`reference` type]] + [[`n`] [object of type `D` (an index)]] +] + +[table Dereference Operator Template Classes + [ + [Template] + + [Supplied Operations] + + [Requirements] + ] + [ + [ + [#table:dereferenceable]__dereferenceable__`` + ] + [ + `P operator->() const` + ] + [ + `*i`. Address of the returned value convertible to `P`. + ] + ] + [ + [ + [#table:indexable]__indexable__`` + ] + [ + `R operator[](D n) const` + ] + [ + `*(i + n)`. Return of type `R`. + ] + ] +] + +[#sec:grpd_iter_oprs] +[h5 Grouped Iterator Operators] + +There are five iterator operator class templates, each for a different +category of iterator. The following table shows the operator groups for +any category that a custom iterator could define. These class templates +have an additional optional template parameter `B`, which is +not shown, to support [link sec:chaining base class chaining]. + +[table Notation + [[Key] [Description]] + [[`T`] [operand type]] + [[`D`] [`difference_type`]] + [[`V`] [`value_type`]] + [[`P`] [`pointer` type]] + [[`R`] [`reference` type]] +] + +[table Iterator Operator Class Templates + [ + [Template] + + [Component Operator Templates] + ] + [ + [ + [#table:input_iteratable]__input_iteratable__`` + ] + [ + [link table:equality_comparable1 `equality_comparable`] + + [link table:incrementable `incrementable`] + + [link table:dereferenceable `dereferenceable`] + ] + ] + [ + [ + [#table:output_iteratable]__output_iteratable__`` + ] + [ + [link table:incrementable `incrementable`] + ] + ] + [ + [ + [#table:forward_iteratable]__forward_iteratable__`` + ] + [ + [link table:input_iteratable `input_iteratable`] + ] + ] + [ + [ + [#table:bidirectional_iteratable] __bidirectional_iteratable__`` + ] + [ + [link table:forward_iteratable `forward_iteratable`] + + [link table:decrementable `decrementable`] + ] + ] + [ + [ + [#table:random_access_iteratable] __random_access_iteratable__`` + ] + [ + [link table:bidirectional_iteratable `bidirectional_iteratable`] + + [link table:totally_ordered1 `totally_ordered`] + + [link table:additive2 `additive`] + + [link table:indexable `indexable`] + ] + ] +] + +[#sec:iterator] +[h5 Iterator Helpers] + +There are also five iterator helper class templates, each +corresponding to a different iterator category. These classes cannot be +used for [link sec:chaining base class chaining]. The following +summaries show that these class templates supply both the iterator +operators from the [link sec:grpd_iter_oprs iterator operator class +templates] and the iterator `typedef`s required by the C++ standard, +such as `iterator_category` and `value_type`. + +[table Notation + [[Key] [Description]] + [[`T`] [operand type]] + [[`D`] [`difference_type`]] + [[`V`] [`value_type`]] + [[`P`] [`pointer` type]] + [[`R`] [`reference` type]] + [[`x1`, `x2`] [objects of type `T`]] +] + +[table Helper Class Templates + [ + [Template] + + [Operations and Requirements] + ] + [ + [ + [#table:input_iterator_helper]__input_iterator_helper__`` + ] + [ + Supports the operations and has the requirements of [link table:input_iteratable `input_iteratable`] + ] + ] + [ + [ + [#table:output_iterator_helper]__output_iterator_helper__`` + ] + [ + Supports the operations and has the requirements of [link table:output_iteratable `output_iteratable`] + + See also \[[link note:1 1]\], \[[link note:2 2]\]. + ] + ] + [ + [ + [#table:forward_iterator_helper] __forward_iterator_helper__`` + ] + [ + Supports the operations and has the requirements of [link table:forward_iteratable `forward_iteratable`] + ] + ] + [ + [ + [#table:bidirectional_iterator_helper] __bidirectional_iterator_helper__`` + ] + [ + Supports the operations and has the requirements of [link table:bidirectional_iteratable `bidirectional_iteratable`] + ] + ] + [ + [ + [#table:random_access_iterator_helper]__random_access_iterator_helper__`` + ] + [ + Supports the operations and has the requirements of [link table:random_access_iteratable `random_access_iteratable`] + + To satisfy __RandomAccessIterator__, `x1 - x2` with return convertible to `D` is also required. + ] + ] +] + +[#sec:iterator_helpers_notes] + +['Iterator Helper Notes]: + +# [#note:1] Unlike other iterator helpers templates, __output_iterator_helper__ takes only one template parameter - +the type of its target class. Although to some it might seem like an unnecessary restriction, the standard requires +`difference_type` and `value_type` of any output iterator to be `void` (C++11 [sect]24.4.1 \[lib.iterator.traits\]), and +__output_iterator_helper__ template respects this requirement. Also, output iterators in the standard have void `pointer` and +`reference` types, so the __output_iterator_helper__ does the same. +# [#note:2] As self-proxying is the easiest and most common way to implement output iterators (see, +for example, insert (C++11 [sect]24.5.2 \[insert.iterators\]) and stream iterators (C++11 [sect]24.6 \[stream.iterators\]) in the standard library), +__output_iterator_helper__ supports the idiom by defining `operator*` and `operator++` member functions which +just return a non-const reference to the iterator itself. Support for self-proxying allows us, in many cases, +to reduce the task of writing an output iterator to writing just two member functions - an appropriate +constructor and a copy-assignment operator. For example, here is a possible implementation of +[@boost:/libs/iterator/doc/function_output_iterator.html `boost::function_output_iterator`] adaptor: + +``` +template +struct function_output_iterator + : boost::__output_iterator_helper__< function_output_iterator > +{ + explicit function_output_iterator(UnaryFunction const& f = UnaryFunction()) + : func(f) {} + + template + function_output_iterator& operator=(T const& value) + { + this->func(value); + return *this; + } + +private: + UnaryFunction func; +}; +``` + +Note that support for self-proxying does not prevent you from using +__output_iterator_helper__ to ease any other, different kind of +output iterator's implementation. If +__output_iterator_helper__'s target type provides its own +definition of `operator*` or/and `operator++`, then +these operators will get used and the ones supplied by +__output_iterator_helper__ will never be instantiated. + +[#sec:i_demo] +[h5 Iterator Demonstration and Test Program] + +The [@../../../test/iterators_test.cpp `iterators_test.cpp`] +program demonstrates the use of the iterator templates, and can also be +used to verify correct operation. The following is the custom iterator +defined in the test program. It demonstrates a correct (though trivial) +implementation of the core operations that must be defined in order for +the iterator helpers to "fill in" the rest of the iterator +operations. + +``` +template +struct test_iter + : public boost::__random_access_iterator_helper__< + test_iter, T, __std_ptrdiff_t__, P, R + > +{ + typedef test_iter self; + typedef R Reference; + typedef __std_ptrdiff_t__ Distance; + +public: + explicit test_iter(T* i =0); + test_iter(const self& x); + self& operator=(const self& x); + Reference operator*() const; + self& operator++(); + self& operator--(); + self& operator+=(Distance n); + self& operator-=(Distance n); + bool operator==(const self& x) const; + bool operator<(const self& x) const; + friend Distance operator-(const self& x, const self& y); +}; +``` + +Check the [@http://www.boost.org/development/testing.html compiler status report] for the +test results with selected platforms. + +[endsect] + +[#sec:old_lib_note] +[section Note for Users of Older Versions] + +The [link sec:chaining changes in the library interface and +recommended usage] were motivated by some practical issues described +below. The new version of the library is still backward-compatible with +the former one, so you are not ['forced] to change any existing code, +but the old usage is deprecated. + +Though it was arguably simpler and more intuitive than using +[link sec:chaining base class chaining], it has been discovered +that the old practice of deriving from multiple operator +templates can cause the resulting classes to be much larger than they +should be. Most modern C++ compilers significantly bloat the size of +classes derived from multiple empty base classes, even though the base +classes themselves have no state. For instance, the size of +`point` from the [link sec:example example] +above was 12-24 bytes on various compilers for the Win32 platform, +instead of the expected 8 bytes. + +Strictly speaking, it was not the library's fault [ndash] the language rules +allow the compiler to apply the [@https://en.cppreference.com/w/cpp/language/ebo empty base class optimization] +in that situation. In principle an arbitrary number of empty base classes can +be allocated at the same offset, provided that none of them have a common +ancestor (see [sect]10 \[class.derived\] paragraph 8 of the C++11 standard). + +But the language definition also does not ['require] implementations +to do the optimization, and few if any of today's compilers implement it +when multiple inheritance is involved. What's worse, it is very unlikely +that implementors will adopt it as a future enhancement to existing +compilers, because it would break binary compatibility between code +generated by two different versions of the same compiler. As Matt Austern +said, "One of the few times when you have the freedom to do this sort of +thing is when you are targeting a new architecture[hellip]". On the other hand, +many common compilers will use the empty base optimization for single +inheritance hierarchies. + +Given the importance of the issue for the users of the library (which +aims to be useful for writing light-weight classes like +`MyInt` or `point<>`), and the forces described above, we decided to change +the library interface so that the object size bloat could be eliminated even +on compilers that support only the simplest form of the empty base class +optimization. The current library interface is the result of those changes. +Though the new usage is a bit more complicated than the old one, we think +it's worth it to make the library more useful in real world. Alexy Gurtovoy +contributed the code which supports the new usage idiom while allowing the +library to remain backward-compatible. + +[endsect] + +[#sec:contributors] +[section Acknowledgments] + +* [@http://www.boost.org/people/dave_abrahams.htm Dave Abrahams]: + Started the library and contributed the arithmetic operators in + [@../../../../boost/operators.hpp `boost/operators.hpp`]. + +* [@http://www.boost.org/people/jeremy_siek.htm Jeremy Siek]: + Contributed the [link sec:deref dereference operators and iterator + helpers] in [@../../../../boost/operators.hpp boost/operators.hpp]. + Also contributed [@../../../test/iterators_test.cpp iterators_test.cpp]. + +* [@http://www.boost.org/people/aleksey_gurtovoy.htm Aleksey Gurtovoy]: + Contributed the code to support [link sec:chaining base class + chaining] while remaining backward-compatible with old versions of + the library. + +* [@http://www.boost.org/people/beman_dawes.html Beman Dawes]: + Contributed [@../../../test/operators_test.cpp `operators_test.cpp`]. + +* [@http://www.boost.org/people/daryle_walker.html Daryle Walker]: + Contributed classes for the shift operators, equivalence, partial + ordering, and arithmetic conversions. Added the grouped operator + classes. Added helper classes for input and output iterators. + +* Helmut Zeisel: Contributed the 'left' operators and added some grouped operator + classes. + +* Daniel Frey: Contributed the NRVO-friendly and symmetric implementation of + arithmetic operators. + +[endsect] + +[endsect] diff --git a/libs/utility/doc/other.qbk b/libs/utility/doc/other.qbk new file mode 100644 index 00000000..239e682d --- /dev/null +++ b/libs/utility/doc/other.qbk @@ -0,0 +1,29 @@ +[/ + Copyright (c) 2021 Alan de Freitas (alandefreitas@gmail.com) + + 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) + + Official repository: https://github.com/boostorg/utility +] + +[section:utilities More Utilities] + +Some utilities have been moved from Boost.Utilities to more appropriate Boost libraries: + +# Moved to [@boost:/libs/core/index.html Boost.Core] + # [@boost:/libs/core/doc/html/core/addressof.html addressof] + # [@boost:/libs/core/doc/html/core/checked_delete.html checked_delete] + # [@boost:/libs/core/doc/html/core/enable_if.html enable_if] + # [@boost:/libs/core/doc/html/core/noncopyable.html noncopyable] +# Moved to [@boost:/libs/type_traits/index.html Boost.TypeTraits] + # [@boost:/libs/type_traits/doc/html/boost_typetraits/reference/declval.html declval] +# Moved to [@boost:/libs/iterator/index.html Boost.Iterator] + # [@boost:/libs/iterator/doc/generator_iterator.htm generator iterator adaptors] + # [@boost:/libs/iterator/doc/html/iterator/algorithms/next_prior.html next/prior] +# Moved to [@boost:/libs/io/index.html Boost.IO] + # [@boost:/libs/io/doc/html/io.html ostream_string] +# Moved to [@boost:/libs/throw_exception/index.html Boost.ThrowException] + # [@boost:/libs/throw_exception/doc/html/throw_exception.html#using_boost_throw_exception throw_exception] + +[endsect] diff --git a/libs/utility/doc/overview.qbk b/libs/utility/doc/overview.qbk new file mode 100644 index 00000000..f790fb02 --- /dev/null +++ b/libs/utility/doc/overview.qbk @@ -0,0 +1,46 @@ +[/ + Copyright (c) 2021 Alan de Freitas (alandefreitas@gmail.com) + + 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) + + Official repository: https://github.com/boostorg/utility +] + +[section Overview] +[block''''''] + +Boost.Utility is a collection of small, useful, and general-purpose components for language support. + +Over time, + +* several components have been moved to more appropriate Boost libraries and +* many of these components had variants accepted into the C++ standard + +When the component has moved to another Boost library, Boost.Utility headers still lead to the appropriate headers +in other libraries. + +[table:id Components + [[Boost.Utility] [Moved to Boost] [C++ Standard variant]] + [[[@boost:/libs/core/doc/html/core/addressof.html `addressof`]] [[@boost:/libs/core/index.html Boost.Core]] [C++11 __std_addressof__]] + [[__base_from_member__] [] []] + [[__BOOST_BINARY__] [] [C++14 [@https://en.cppreference.com/w/cpp/language/integer_literal Binary integer literal]]] + [[__call_traits__] [] []] + [[[@boost:/libs/core/doc/html/core/checked_delete.html `checked_delete`]] [[@boost:/libs/core/index.html Boost.Core]] []] + [[__compressed_pair__] [] []] + [[[@boost:/libs/type_traits/doc/html/boost_typetraits/reference/declval.html `declval`]] [[@boost:/libs/type_traits/index.html Boost.TypeTraits]] [C++11 __std_declval__]] + [[[@boost:/libs/core/doc/html/core/enable_if.html `enable_if`]] [[@boost:/libs/core/index.html Boost.Core]] [C++11 __std_enable_if__]] + [[[@boost:/libs/iterator/doc/generator_iterator.htm generator iterator adaptors]] [[@boost:/libs/iterator/index.html Boost.Iterator]] []] + [[__in_place_factory__] [] []] + [[[@boost:/libs/iterator/index.html `iterator_adaptors`]] [[@boost:/libs/iterator/index.html Boost.Iterator]] []] + [[[@boost:/libs/iterator/doc/html/iterator/algorithms/next_prior.html `next` / `prior`]] [[@boost:/libs/iterator/index.html Boost.Iterator]] [C++11 __std_next__ / __std_prev__]] + [[[@boost:/libs/core/doc/html/core/noncopyable.html `noncopyable`]] [[@boost:/libs/core/index.html Boost.Core]] []] + [[[link sec:operators `operators`]] [] []] + [[[@boost:/libs/io/doc/html/io.html `ostream_string`]] [[@boost:/libs/io/index.html Boost.IO]] []] + [[__result_of__] [] [C++11 __std_result_of__]] + [[__string_view__] [] [C++17 __std_string_view__]] + [[[@boost:/libs/throw_exception/doc/html/throw_exception.html#using_boost_throw_exception `throw_exception`]] [[@boost:/libs/throw_exception/index.html Boost.ThrowException]] []] + [[[link sec:value_init `value_init`]] [] [C++11 [@https://en.cppreference.com/w/cpp/language/list_initialization List initialization]]] +] + +[endsect] diff --git a/libs/utility/doc/quickref.xml b/libs/utility/doc/quickref.xml new file mode 100644 index 00000000..953421f5 --- /dev/null +++ b/libs/utility/doc/quickref.xml @@ -0,0 +1,497 @@ + + + + + + + + + + + + + + + + + + + Base from Member + + + Call Traits + + + Compressed Pair + + + In-place Factory + + + + + + + + Classes + + + base_from_member + + + + + + + Type Traits + + + call_traits + + + call_traits<T&> + + + call_traits<T[N]> + + + + call_traits<const + T[N]> + + + + + + + + Classes + + + compressed_pair + + + + Functions + + + swap + + + + + + + Classes + + + in_place_factory_base + + + typed_in_place_factory_base + + + + + + + + + + + + + + + + + + + Operators + + + + + + + + + Classes (1 of 5) + + + additive1 + + + additive2 + + + arithmetic1 + + + arithmetic2 + + + bidirectional_iteratable + + + + bidirectional_iterator_helper + + + + bitwise1 + + + bitwise2 + + + decrementable + + + dereferenceable + + + equality_comparable1 + + + equality_comparable2 + + + equivalent1 + + + + + + Classes (2 of 5) + + + equivalent2 + + + euclidean_ring_operators1 + + + + euclidean_ring_operators2 + + + + field_operators1 + + + field_operators2 + + + forward_iteratable + + + forward_iterator_helper + + + incrementable + + + indexable + + + input_iteratable + + + input_iterator_helper + + + integer_arithmetic1 + + + integer_arithmetic2 + + + + + + Classes (3 of 5) + + + integer_multiplicative1 + + + integer_multiplicative2 + + + is_chained_base + + + less_than_comparable1 + + + less_than_comparable2 + + + multiplicative1 + + + multiplicative2 + + + operators + + + operators2 + + + operators<T,T> + + + + ordered_euclidean_ring_operators1 + + + + + ordered_euclidean_ring_operators2 + + + + + ordered_euclidian_ring_operators1 + + + + + + + Classes (4 of 5) + + + + ordered_euclidian_ring_operators2 + + + + ordered_field_operators1 + + + ordered_field_operators2 + + + ordered_ring_operators1 + + + ordered_ring_operators2 + + + output_iteratable + + + output_iterator_helper + + + partially_ordered1 + + + partially_ordered2 + + + random_access_iteratable + + + + random_access_iterator_helper + + + + ring_operators1 + + + ring_operators2 + + + + + + Classes (5 of 5) + + + shiftable1 + + + shiftable2 + + + totally_ordered1 + + + totally_ordered2 + + + unit_steppable + + + Type Traits + + + is_chained_base + + + + + + + + + + + + + + + + + + Result of + + + String View + + + Value Init + + + + + + + + + Type Traits + + + result_of + + + tr1_result_of + + + + + + + Aliases + + + string_view + + + u16string_ref + + + u16string_view + + + u32string_ref + + + u32string_view + + + wstring_ref + + + wstring_view + + + string_ref + + + + + + Classes + + + basic_string_ref + + + basic_string_view + + + Functions + + + hash_range + + + hash_value + + + + + + Operators + + + operator== + + + operator!= + + + operator< + + + operator<= + + + operator> + + + operator>= + + + operator<< + + + + + + + Classes + + + initialized + + + initialized_value_t + + + value_initialized + + + Functions + + + get + + + swap + + + Constants + + + initialized_value + + + + + + + diff --git a/libs/utility/doc/result_of.qbk b/libs/utility/doc/result_of.qbk new file mode 100644 index 00000000..4542c581 --- /dev/null +++ b/libs/utility/doc/result_of.qbk @@ -0,0 +1,421 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / + / 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) + /] + +[/===============] +[section Result of] +[/===============] + +[section Introduction] + +The class template __result_of__ helps determine the type of a +call expression. For example, given an lvalue `f` of type `F` +and lvalues `t1`,`t2`, ..., `tN` of types `T1`, `T2`, ..., `TN`, +respectively, the type __result_of__`::type` defines +the result type of the expression `f(t1, t2, ...,tN)`. + +This implementation permits the type `F` to be a function pointer, +function reference, member function pointer, or class type. By default, +N may be any value between 0 and 16. To change the upper limit, define +the macro `BOOST_RESULT_OF_NUM_ARGS` to the maximum value for N. Class +template __result_of__ resides in the header +[@../../../../boost/utility/result_of.hpp ``]. + +If your compiler's support for __decltype__ is adequate, __result_of__ +automatically uses it to deduce the type of the call expression, in +which case __result_of__`::type` names the type +__decltype__`(boost::declval()(boost::declval(), +boost::declval(), ..., boost::declval()))`, as in the +following example. + +``` +struct functor { + template + T operator()(T x) + { + return x; + } +}; + +typedef __boost_result_of__::type type; // type is int +``` + +You can test whether __result_of__ is using __decltype__ by checking if +the macro `BOOST_RESULT_OF_USE_DECLTYPE` is defined after +including `result_of.hpp`. You can also force __result_of__ to use +__decltype__ by defining `BOOST_RESULT_OF_USE_DECLTYPE` prior +to including `result_of.hpp`. + +If __decltype__ is not used, then automatic result type deduction of function +objects is not possible. Instead, __result_of__ uses the following protocol +to allow the programmer to specify a type. When `F` is a class type with a +member type `result_type`, `result_of::type` is +`F::result_type`. When `F` does not contain `result_type`, +`result_of::type` is +`F::result::type` when +`N > 0` or `void` when `N = 0`. + +Note that it is the responsibility of the programmer to ensure that +function objects accurately advertise their result +type via this protocol, as in the following example. + +``` +struct functor { + template struct result; + + template + struct result { + typedef T type; + }; + + template + T operator()(T x) + { + return x; + } +}; + +typedef __boost_result_of__::type type; // type is int +``` + +Since __decltype__ is a language feature standardized in C++11, if you are +writing a function object to be used with __result_of__, for maximum +portability, you might consider following the above protocol +even if your compiler has proper __decltype__ support. + +If you wish to continue to use the protocol on compilers that +support __decltype__, there are two options: + +* You can use __boost_tr1_result_of__, which is also defined in +[@../../../boost/utility/result_of.hpp ``]. + +* Alternatively, you can define the macro `BOOST_RESULT_OF_USE_TR1`, +which causes __result_of__ to use the protocol described above instead +of __decltype__. If you choose to follow the protocol, take care to +ensure that the `result_type` and `result<>` members accurately +represent the return type of `operator()` given a call expression. + +Additionally, __boost_result_of__ provides a third mode of operation, +which some users may find convenient. When +`BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK` is defined, +__boost_result_of__ behaves as follows. If the function object has a member +type `result_type` or member template `result<>`, then __boost_result_of__ +will use the TR1 protocol. + +Otherwise, __boost_result_of__ will use __decltype__. Using TR1 with +a __decltype__ fallback may workaround certain problems at the cost of portability. +For example: + +* Deficient compiler: If your code requires __boost_result_of__ to work +with incomplete return types but your compiler's __decltype__ implementation +does not support incomplete return types, then you can use the TR1 protocol +as a workaround. Support for incomplete return types was added late in the +C++11 standardization process +(see [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf N3276]) +and is not implemented by some compilers. + +* Deficient legacy code: If your existing TR1 function object advertises a different type than +the actual result type deduced by __decltype__, then using TR1 with a __decltype__ fallback +will allow you to work with both your existing TR1 function objects and new C++11 +function object. This situation could occur if your legacy function objects +misused the TR1 protocol. See the documentation on known [link sec:result_of_tr1_diff differences] +between __boost_result_of__ and TR1. + +* [#BOOST_NO_RESULT_OF] This implementation of __result_of__ requires class template +partial specialization, the ability to parse function types properly, and support +for SFINAE. If __result_of__ is not supported by your compiler, including the header +[@../../../boost/utility/result_of.hpp ``] will define +the macro `BOOST_NO_RESULT_OF`. + +For additional information about __result_of__, see the C++ Library +Technical Report, [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf N1836], +or, for motivation and design rationale, the __result_of__ +[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1454.html proposal]. + +[endsect] + +[#sec:result_of_guidelines] +[section Usage guidelines for __boost_result_of__] + +The following are general suggestions about when and how to use __boost_result_of__. + +# If you are targeting C++11 and are not concerned about portability to +non-compliant compilers or previous versions of the standard, then use +`__std_result_of__`. If `__std_result_of__` meets your needs, then +there's no reason to stop using it. + +# If you are targeting C++11 but may port your code to legacy compilers +at some time in the future, then use __boost_result_of__ with __decltype__. +When __decltype__ is used __boost_result_of__ and `__std_result_of__` are usually +interchangeable. See the documentation on known [link sec:result_of_cxx11_diff differences] +between __boost_result_of__ and C++11 __std_result_of__. + +# If compiler portability is required, use __boost_result_of__ with the TR1 protocol + +Regardless of how you configure __boost_result_of__, it is +important to bear in mind that the return type of a +function may change depending on its arguments, and +additionally, the return type of a member function may +change depending on the cv-qualification of the +object. __boost_result_of__ must be passed +the appropriately cv-qualified types in order to +deduce the corresponding return type. + +For example: + +``` +struct functor { + int& operator()(int); + int const& operator()(int) const; + + float& operator()(float&); + float const& operator()(float const&); +}; + +typedef __boost_result_of__< + functor(int) +>::type type1; // type1 is int & + +typedef __boost_result_of__< + const functor(int) +>::type type2; // type2 is int const & + +typedef __boost_result_of__< + functor(float&) +>::type type3; // type3 is float & + +typedef __boost_result_of__< + functor(float const&) +>::type type4; // type4 is float const & +``` + +[endsect] + +[#sec:result_of_tr1_protocol_guidelines] +[section Usage guidelines for the TR1 result_of protocol] + +On compliant C++11 compilers, __boost_result_of__ can +use __decltype__ to deduce the type of any +call expression, including calls to function +objects. However, on pre-C++11 compilers or on +compilers without adequate decltype support, +additional scaffolding is needed from function +objects as described above. The following are +suggestions about how to use the TR1 protocol. + +* When the return type does not depend on the +argument types or the cv-qualification of the +function object, simply +define `result_type`. There is no need +to use the `result` template unless the +return type varies. + +* Use the protocol specified type when defining +function prototypes. This can help ensure the +actual return type does not get out of sync with +the protocol specification. For example: + +``` +struct functor { + typedef int result_type; + result_type operator()(int); +}; +``` + +* Always specify the `result` specialization near the corresponding +`operator()` overload. This can make it easier to keep the specializations +in sync with the overloads. For example: + +``` +struct functor { + template struct result; + + template + struct result { + typedef int& type; + }; + result::type operator()(int); + + template + struct result { + typedef int const& type; + }; + result::type operator()(int) const; +}; +``` + +* Use type transformations to simplify +the `result` template specialization. For +example, the following uses [@../type_traits/doc/html/index.html Boost.TypeTraits] +to specialize the `result` template for +a single `operator()` that can be called on +both a const and non-const function object with +either an lvalue or rvalue argument. + +``` +struct functor { + template struct result; + + template + struct result + : boost::remove_cv< + typename boost::remove_reference::type + > + {}; + + template + T operator()(T const& x) const; +}; +``` + +[endsect] + +[#sec:result_of_tr1_diff] +[section Known differences between __boost_result_of__ and __boost_tr1_result_of__] + +When using __decltype__, __boost_result_of__ ignores the TR1 protocol and instead deduces the +return type of function objects directly via __decltype__. In most situations, users +will not notice a difference, so long as they use the protocol correctly. The following are situations in +which the type deduced by __boost_result_of__ is known to differ depending on whether +__decltype__ or the TR1 protocol is used. + +TR1 protocol misusage: When using the TR1 protocol, __boost_result_of__ cannot +detect whether the actual type of a call to a function object is the same as the +type specified by the protocol, which allows for the possibility of inadvertent +mismatches between the specified type and the actual type. When using __decltype__, +these subtle bugs may result in compilation errors. For example: + +``` +struct functor { + typedef short result_type; + int operator()(short); +}; + +#ifdef BOOST_RESULT_OF_USE_DECLTYPE + +BOOST_STATIC_ASSERT(( + boost::is_same<__boost_result_of__::type, int>::value +)); + +#else + +BOOST_STATIC_ASSERT(( + boost::is_same<__boost_result_of__::type, short>::value +)); + +#endif +``` + +Note that the user can force __boost_result_of__ to use the TR1 +protocol even on platforms that support __decltype__ by +defining `BOOST_RESULT_OF_USE_TR1`. + +Nullary function objects: When using the TR1 protocol, __boost_result_of__ +cannot always deduce the type of calls to nullary function objects, in which case the +type defaults to void. When using __decltype__, __boost_result_of__ always gives the +actual type of the call expression. For example: + +``` +struct functor { + template struct result { + typedef int type; + }; + int operator()(); +}; + +#ifdef BOOST_RESULT_OF_USE_DECLTYPE + +BOOST_STATIC_ASSERT(( + boost::is_same<__boost_result_of__::type, int>::value +)); + +#else + +BOOST_STATIC_ASSERT(( + boost::is_same<__boost_result_of__::type, void>::value +)); + +#endif +``` + +Note that there are some workarounds for the nullary function problem. +So long as the return type does not vary, `result_type` can always be used to +specify the return type regardless of arity. If the return type does vary, +then the user can specialize __boost_result_of__ itself for nullary calls. + +Non-class prvalues and cv-qualification: When using the TR1 protocol, __boost_result_of__ will +report the cv-qualified type specified by `result_type` or the `result` template regardless of +the actual cv-qualification of the call expression. When using __decltype__, __boost_result_of__ +will report the actual type of the call expression, which is not cv-qualified when the expression +is a non-class prvalue. For example: + +``` +struct functor { + template struct result; + template struct result { + typedef const T type; + }; + + const short operator()(const short); + int const & operator()(int const &); +}; + +// Non-prvalue call expressions work the same with or without decltype. + +BOOST_STATIC_ASSERT(( + boost::is_same< + __boost_result_of__::type, + int const & +::value +)); + +// Non-class prvalue call expressions are not actually cv-qualified, +// but only the decltype-based result_of reports this accurately. + +#ifdef BOOST_RESULT_OF_USE_DECLTYPE + +BOOST_STATIC_ASSERT(( + boost::is_same< + __boost_result_of__::type, + short +::value +)); + +#else + +BOOST_STATIC_ASSERT(( + boost::is_same< + __boost_result_of__::type, + const short +::value +)); + +#endif +``` + +[endsect] + +[#sec:result_of_cxx11_diff] +[section Known differences between __boost_result_of__ and C++11 result_of] + +When using __decltype__, __boost_result_of__ implements most of the C++11 __std_result_of__ +specification. One known exception is that __boost_result_of__ does not implement the +requirements regarding pointers to member data. + +[endsect] + +[/===============] +[xinclude tmp/result_of_reference.xml] +[/===============] + +[section Acknowledgments] + +Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others. + +[endsect] + +[endsect] diff --git a/libs/utility/doc/string_view.qbk b/libs/utility/doc/string_view.qbk new file mode 100644 index 00000000..be79a98f --- /dev/null +++ b/libs/utility/doc/string_view.qbk @@ -0,0 +1,209 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / + / 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) + /] + +[/===============] +[section String View] +[/===============] + +[section Introduction] + +The class __boost_string_view__ and other classes derived from __basic_string_view__ represent references to strings or substrings. When you are parsing/processing strings from some external source, frequently you want to pass a piece of text to a procedure for specialized processing. Before __std_string_view__, the canonical way to do this used to be a __std_string__, but that has certain drawbacks: + +1) If you are processing a buffer of text (say a HTTP response or the contents of a file), then you have to create the string from the text you want to pass, which involves memory allocation and copying of data. + +2) If a routine receives a constant __std_string__ and wants to pass a portion of that string to another routine, then it must create a new string of that substring. + +3) If a routine receives a constant __std_string__ and wants to return a portion of the string, then it must create a new string to return. + +__boost_string_view__ is designed to solve these efficiency problems. A __boost_string_view__ is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of __std_string__. A __boost_string_view__ is cheap to create, copy and pass by value, because it does not actually own the storage that it points to. + +A __boost_string_view__ is implemented as a small struct that contains a pointer to the start of the character `data` and a `count`. A __boost_string_view__ is cheap to create and cheap to copy. + +__boost_string_view__ acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator[]`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you do not need to change the underlying data. For example, __std_sort__ and __std_remove__ will not work. + +Besides generic container functionality, __boost_string_view__ provides a subset of the interface of __std_string__. This makes it easy to replace parameters of type `const __std_string__ &` with __boost_string_view__. Like __std_string__, __boost_string_view__ has a static member variable named `npos` to denote the result of failed searches, and to mean "the end". + +[caution Because a __boost_string_view__ does not own the data that it refers to, it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a __string_view__ refers to exists as long as the __string_view__ does.] + +[note + +Boost.Utility also includes the class __string_ref__: + +- __string_ref__ is the initial implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442: +string_ref: a non-owning reference to a string]. + +- __string_view__ is an updated implementation to reflect the Library Fundamentals TS [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html N4480: \[string.view\]]. + +Please prefer __string_view__ / __basic_string_view__ over __string_ref__ / __basic_string_ref__: + +- The __basic_string_view__ class better matches __std_basic_string_view__. + +- __basic_string_view__ has WAY more constexpr support. + +- Code that uses __basic_string_ref__ should continue to work. + +- Not much code depends on __basic_string_ref__ anymore. + + +] +[endsect] + +[/===============] +[section Examples] +[/===============] + +Integrating __string_view__ into your code is fairly simple. Wherever you pass a `const __std_string__ &` or __std_string__ as a parameter, that's a candidate for passing a __boost_string_view__. + +``` +__std_string__ extract_part ( const __std_string__ &bar ) { + return bar.substr ( 2, 3 ); +} + +if ( extract_part ( "ABCDEFG" ).front() == 'C' ) { /* do something */ } +``` + +Let's figure out what happens in this contrived example. + +* First, a temporary string is created from the string literal `"ABCDEFG"`, and it is passed (by reference) to the routine `extract_part`. +* Then a second string is created in the call `__std_string__::substr` and returned to `extract_part` (this copy may be elided by RVO). +* Then `extract_part` returns that string back to the caller (again this copy may be elided). +* The first temporary string is deallocated, and `front` is called on the second string, and then it is deallocated as well. + +Two __std_string__ s are created, and two copy operations. That is potentially four memory allocations and deallocations, and the associated copying of data. + +Now let's look at the same code with __string_view__: + +``` +__boost_string_view__ extract_part ( __boost_string_view__ bar ) { + return bar.substr ( 2, 3 ); +} + +if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ } +``` + +No memory allocations. No copying of character data. No changes to the code other than the types. There are two __string_view__ s created, and two __string_view__ s copied, but those are cheap operations. +[endsect] + +[/=================] +[section:reference Synopsis] +[/=================] + +The header file [@../../../../boost/utility/string_view.hpp ``] defines a template __boost_basic_string_view__, and four specializations __string_view__, __wstring_view__, __u16string_view__, __u32string_view__ - for `char` / `wchar_t` / `char16_t` / `char32_t`. + +`#include ` + +Construction and copying: + +``` +constexpr basic_string_view (); // Constructs an empty string_view +constexpr basic_string_view(const charT* str); // Constructs from a NULL-terminated string +constexpr basic_string_view(const charT* str, size_type len); // Constructs from a pointer, length pair +template +basic_string_view(const __std_basic_string__& str); // Constructs from a std::string +basic_string_view (const basic_string_view &rhs); +basic_string_view& operator=(const basic_string_view &rhs); +``` + +__string_view__ does not define a move constructor nor a move-assignment operator because copying a __string_view__ is just a cheap as moving one. + +Basic container-like functions: + +``` +constexpr size_type size() const ; +constexpr size_type length() const ; +constexpr size_type max_size() const ; +constexpr bool empty() const ; + +// All iterators are const_iterators +constexpr const_iterator begin() const ; +constexpr const_iterator cbegin() const ; +constexpr const_iterator end() const ; +constexpr const_iterator cend() const ; +const_reverse_iterator rbegin() const ; +const_reverse_iterator crbegin() const ; +const_reverse_iterator rend() const ; +const_reverse_iterator crend() const ; +``` + +Access to the individual elements (all of which are const): + +``` +constexpr const charT& operator[](size_type pos) const ; +const charT& at(size_t pos) const ; +constexpr const charT& front() const ; +constexpr const charT& back() const ; +constexpr const charT* data() const ; +``` + +Modifying the __string_view__ (but not the underlying data): + +``` +void clear(); +void remove_prefix(size_type n); +void remove_suffix(size_type n); +``` + +Searching: + +``` +size_type find(basic_string_view s) const ; +size_type find(charT c) const ; +size_type rfind(basic_string_view s) const ; +size_type rfind(charT c) const ; +size_type find_first_of(charT c) const ; +size_type find_last_of (charT c) const ; + +size_type find_first_of(basic_string_view s) const ; +size_type find_last_of(basic_string_view s) const ; +size_type find_first_not_of(basic_string_view s) const ; +size_type find_first_not_of(charT c) const ; +size_type find_last_not_of(basic_string_view s) const ; +size_type find_last_not_of(charT c) const ; +``` + +String-like operations: + +``` +constexpr basic_string_view substr(size_type pos, size_type n=npos) const ; // Creates a new string_view +bool starts_with(charT c) const ; +bool starts_with(basic_string_view x) const ; +bool ends_with(charT c) const ; +bool ends_with(basic_string_view x) const ; +``` +[endsect] + + +[/===============] +[section History] +[/===============] + +[h5 boost 1.71] +* Glen Fernandes updated the implementation of the stream insertion operator to +write directly to the `basic_streambuf` and refactored that functionality into +a common utility. + +[h5 boost 1.53] +* Introduced + +[endsect] + +[/===============] +[xinclude tmp/string_view_reference.xml] +[/===============] + +[/===============] +[section Acknowledgments] +[/===============] + +Author: Clow, Marshall + +Copyright 2012 Marshall Clow + +[endsect] + +[endsect] diff --git a/libs/utility/doc/utilities.qbk b/libs/utility/doc/utilities.qbk new file mode 100644 index 00000000..2cbe64ad --- /dev/null +++ b/libs/utility/doc/utilities.qbk @@ -0,0 +1,32 @@ +[/ + Copyright (c) 2021 Alan de Freitas (alandefreitas@gmail.com) + + 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) + + Official repository: https://github.com/boostorg/utility +] + +[section:utilities Utilities] + +The entire contents of Boost.Utility are in `namespace boost`. + +[warning + +Direct use of the header [@../../../../boost/utility.hpp ``] is discouraged and it will be deprecated. + +Please include the headers relative to individual components instead. + +] + +[include base_from_member.qbk] +[include BOOST_BINARY.qbk] +[include call_traits.qbk] +[include compressed_pair.qbk] +[include in_place_factory.qbk] +[include operators.qbk] +[include result_of.qbk] +[include string_view.qbk] +[include value_init.qbk] + +[endsect] diff --git a/libs/utility/doc/value_init.qbk b/libs/utility/doc/value_init.qbk new file mode 100644 index 00000000..85868506 --- /dev/null +++ b/libs/utility/doc/value_init.qbk @@ -0,0 +1,584 @@ +[/ + / Copyright (c) 2012 Marshall Clow + / Copyright (c) 2021, Alan Freitas + / + / 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) + /] + +[/===============] +[#sec:value_init] +[section Value Init] + +[/===============] + +[section Introduction] + +Constructing and initializing objects in a generic way is difficult in +C++. The problem is that there are several different rules that apply +for initialization. Depending on the type, the value of a newly constructed +object can be zero-initialized (logically 0), default-constructed (using +the default constructor), or indeterminate. When writing generic code, +this problem must be addressed. The template __value_initialized__ provides +a solution with consistent syntax for value initialization of scalar, +union and class types. Moreover, __value_initialized__ offers a workaround to various +compiler issues regarding value-initialization. + +Furthermore, a `const` object __initialized_value__ is provided, +to avoid repeating the type name when retrieving the value from a +`__value_initialized__` object. + +There are various ways to initialize a variable, in C++. The following +declarations all ['may] have a local variable initialized to its default +value: + +``` +T1 var1; +T2 var2 = 0; +T3 var3 = {}; +T4 var4 = T4(); +``` + +Unfortunately, whether or not any of those declarations correctly +initialize the variable very much depends on its type. The first +declaration is valid for any __DefaultConstructible__ type by definition. + +However, it does not always do an initialization. It correctly initializes +the variable when it's an instance of a class, and the author of the class +has provided a proper default constructor. On the other hand, the value of +`var1` is ['indeterminate] when its type is an arithmetic type, like `int`, +`float`, or `char`. + +An arithmetic variable is of course initialized properly by the second declaration, +`T2 var2 = 0`. But this initialization form will not usually work for a +class type, unless the class was especially written to support being +initialized that way. + +The third form, `T3 var3 = {}`, initializes an aggregate, typically a "C-style" +`struct` or a "C-style" array. However, at the time this library was developed, +the syntax did not allow for a class that has an explicitly declared constructor. + +The fourth form is the most generic form of them, as it can be used to initialize +arithmetic types, class types, aggregates, pointers, and other types. +The declaration, `T4 var4 = T4()`, should be read as follows: First a temporary +object is created, by `T4()`. This object is [link sec:valueinit value-initialized]. +Next the temporary object is copied to the named variable, `var4`. Afterwards, +the temporary is destroyed. While the copying and the destruction are likely to +be optimized away, C++ still requires the type `T4` to be __CopyConstructible__. +So `T4` needs to be ['both] __DefaultConstructible__ ['and] __CopyConstructible__. + +A class may not be CopyConstructible, for example because it may have a +private and undefined copy constructor, or because it may be derived from +`boost::noncopyable`. Scott Meyers \[[link sec:references 2]\] explains why a +class would be defined like that. + +There is another, less obvious disadvantage to the fourth form, `T4 var4 = T4()`: +It suffers from various [link sec:compiler_issues compiler issues], causing +a variable to be left uninitialized in some compiler specific cases. + +The template __value_initialized__ offers a generic way to initialize +an object, like `T4 var4 = T4()`, but without requiring its type +to be __CopyConstructible__. And it offers a workaround to those compiler issues +regarding value-initialization as well. It allows getting an initialized +variable of any type; it ['only] requires the type to be __DefaultConstructible__. +A properly ['value-initialized] object of type `T` is constructed by the following +declaration: + +``` +value_initialized var; +``` + +The template __initialized__ offers both value-initialization and direct-initialization. +It is especially useful as a data member type, allowing the very same object +to be either direct-initialized or value-initialized. + +The `const` object __initialized_value__ allows value-initializing a variable as follows: + +``` +T var = initialized_value; +``` + +This form of initialization is semantically equivalent to `T4 var4 = T4()`, +but robust against the aforementioned compiler issues. + +[endsect] + +[#sec:details] +[section Details] + +The C++ standard \[[link sec:references 3]\] contains the definitions +of `zero-initialization` and `default-initialization`. Informally, zero-initialization +means that the object is given the initial value `0` converted to the type and +default-initialization means that [@https://en.cppreference.com/w/cpp/named_req/PODType POD] \[[link sec:references 4]\] types are zero-initialized, +while non-POD class types are initialized with their corresponding default constructors. + +A ['declaration] can contain an ['initializer], which specifies the +object's initial value. The initializer can be just '()', which states that +the object shall be value-initialized (but see below). However, if a ['declaration] +has no ['initializer] and it is of a non-`const`, non-`static` POD type, the +initial value is indeterminate: (see [sect]8.5, \[dcl.init\], for the +accurate definitions). + +``` +int x; // no initializer. x value is indeterminate. +__std_string__ s; // no initializer, s is default-constructed. + +int y = int(); +// y is initialized using copy-initialization +// but the temporary uses an empty set of parentheses as the initializer, +// so it is default-constructed. +// A default constructed POD type is zero-initialized, +// therefore, y == 0. + +void foo ( __std_string__ ) ; +foo ( __std_string__() ) ; +// the temporary string is default constructed +// as indicated by the initializer () +``` + +[#sec:valueinit] +[h5 value-initialization] + +The first [@http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html Technical +Corrigendum for the C++ Standard] (TC1), whose draft was released to the public in +November 2001, introduced [@http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#178 Core +Issue 178], among many other issues. + +That issue introduced the new concept of `value-initialization`, and also fixed the +wording for zero-initialization. Informally, value-initialization is similar to +default-initialization with the exception that in some cases non-static data members +and base class sub-objects are also value-initialized. + +The difference is that an object that is value-initialized will not have, or at least +is less likely to have, indeterminate values for data members and base class sub-objects; +unlike the case of an object default constructed (see Core Issue 178 for a +normative description). + +In order to specify value-initialization of an object we need to use the +empty-set initializer: `()`. + +As before, a declaration with no initializer specifies default-initialization, +and a declaration with a non-empty initializer specifies copy (`=xxx`) or +direct (`xxx`) initialization. + +``` +template void eat(T); + +int x ; // indeterminate initial value. + +__std_string__ s; // default-initialized. + +eat ( int() ) ; // value-initialized + +eat ( __std_string__() ) ; // value-initialized +``` + +[#sec:valueinitsyn] +[h5 value-initialization syntax] + +Value initialization is specified using `()`. However, the empty set of +parentheses is not permitted by the syntax of initializers because it is +parsed as the declaration of a function taking no arguments: + +``` +int x() ; // declares function int(*)() +``` + +Thus, the empty `()` must be put in some other initialization context. + +One alternative is to use copy-initialization syntax: + +``` +int x = int(); +``` + +This works perfectly fine for POD types. But for non-POD class types, +copy-initialization searches for a suitable constructor, which could be, +for instance, the copy-constructor. It also searches for a suitable conversion +sequence but this does not apply in this context. + +For an arbitrary unknown type, using this syntax may not have the +value-initialization effect intended because we don't know if a copy +from a default constructed object is exactly the same as a default +constructed object, and the compiler is allowed, in +some cases, but never required to, optimize the copy away. + +One possible generic solution is to use value-initialization of a non static +data member: + +``` +template +struct W +{ + // value-initialization of 'data' here. + W() : data() {} + + T data; +}; + +W w; +// w.data is value-initialized for any type. +``` + +This is the solution as it was supplied by earlier versions of the +`__value_initialized__` template class. Unfortunately this approach +suffered from various compiler issues. + +[#sec:compiler_issues] +[h5 Compiler issues] + +Various compilers have not yet fully implemented value-initialization. +So when an object should be ['value-initialized] according to the C++ Standard, +it ['may] in practice still be left uninitialized, because of those +compiler issues. It is hard to make a general statement on what those issues +are like, because they depend on the compiler you are using, its version number, +and the type of object you would like to have value-initialized. + +All compilers we have tested so far support value-initialization for arithmetic types properly. +However, various compilers may leave some types of ['aggregates] uninitialized, when they +should be value-initialized. Value-initialization of objects of a pointer-to-member type may also +go wrong on various compilers. + +At the moment of writing, May 2010, the following reported issues regarding +value-initialization are still there in current compiler releases: + + + +* [@https://connect.microsoft.com/VisualStudio/feedback/details/100744 Microsoft Visual Studio Feedback ID 100744, Value-initialization in new-expression]: Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005. +* [@http://connect.microsoft.com/VisualStudio/feedback/details/484295 Microsoft Visual Studio Feedback ID 484295, VC++ does not value-initialize members of derived classes without user-declared constructor] Reported by Sylvester Hesp, 2009. +* [@https://connect.microsoft.com/VisualStudio/feedback/details/499606 Microsoft Visual Studio Feedback ID 499606, Presence of copy constructor breaks member class initialization] Reported by Alex Vakulenko, 2009 +* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=83751 Embarcadero/C++Builder Report 83751, Value-initialization: arrays should have each element value-initialized] Reported by Niels Dekker (LKEB), 2010. +* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=83851 Embarcadero/C++Builder Report 83851, Value-initialized temporary triggers internal backend error C1798] Reported by Niels Dekker, 2010. +* [@http://qc.embarcadero.com/wc/qcmain.aspx?d=84279 Embarcadero/C++Builder Report 84279, Internal compiler error (F1004), value-initializing member function pointer by "new T()"] Reported by Niels Dekker, 2010 +* Sun CR 6947016, Sun 5.10 may fail to value-initialize an object of a non-POD aggregate. Reported to Steve Clamage by Niels Dekker, 2010. +* IBM's XL V10.1 and V11.1 may fail to value-initialize a temporary of a non-POD aggregate. Reported to Michael Wong by Niels Dekker, 2010. +* Intel support issue 589832, Attempt to value-initialize pointer-to-member triggers internal error on Intel 11.1. Reported by John Maddock, 2010. + +Note that all known GCC issues regarding value-initialization are fixed with GCC version 4.4, including +[@http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 GCC Bug 30111]. Clang also has completely implemented +value-initialization, as far as we know, now that [@http://llvm.org/bugs/show_bug.cgi?id=7139 Clang Bug 7139] +is fixed. + +New versions of __value_initialized__ (Boost release version 1.35 or higher) offer a workaround to these +issues: __value_initialized__ may now clear its internal data, prior to constructing the object that it +contains. It will do so for those compilers that need to have such a workaround, based on the +[@boost:/libs/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_defects +compiler defect macro] `BOOST_NO_COMPLETE_VALUE_INITIALIZATION`. + +[endsect] + +[#sec:types] +[section Types and objects] + +[#sec:val_init] +[section `template class value_initialized`] + +``` +namespace boost { + +template +class __value_initialized__ +{ + + public : + + __value_initialized__() : x() {} + + operator T const &() const { return x ; } + + operator T&() { return x ; } + + T const &data() const { return x ; } + + T& data() { return x ; } + + void swap( __value_initialized__& ); + + private : + + [unspecified] x ; + +} ; + +template + +T const& get ( __value_initialized__ const& x ) +{ + return x.data(); +} + +template +T& get ( __value_initialized__& x ) +{ + return x.data(); +} + +template +void swap ( __value_initialized__& lhs, __value_initialized__& rhs ) +{ + lhs.swap(rhs); +} + +} // namespace boost +``` + +An object of this template class is a `T`-wrapper convertible to `'T&'` whose +wrapped object (data member of type `T`) is [link sec:valueinit value-initialized] upon default-initialization +of this wrapper class: + +``` +int zero = 0; +__value_initialized__ x; +assert( x == zero ) ; + +__std_string__ def; +__value_initialized__< __std_string__ > y; +assert( y == def ) ; +``` + +The purpose of this wrapper is to provide a consistent syntax for value initialization +of scalar, union and class types (POD and non-POD) since the correct syntax for value +initialization varies (see [link sec:valueinitsyn value-initialization syntax]). + +The wrapped object can be accessed either through the conversion operator +`T&`, the member function `data()`, or the non-member function `get()`: + +``` +void watch(int); + +__value_initialized__ x; + +watch(x) ; // operator T& used. +watch(x.data()); +watch( get(x) ) // function get() used +``` + +Both `const` and non-`const` objects can be wrapped. Mutable objects can be +modified directly from within the wrapper but constant objects cannot: + +When `T` is a __Swappable__ type, `__value_initialized__` +is swappable as well, by calling its `swap` member function +as well as by calling `boost::swap`. + +``` +__value_initialized__ x; +static_cast(x) = 1 ; // OK +get(x) = 1 ; // OK + +__value_initialized__ y ; +static_cast(y) = 1 ; // ERROR: cannot cast to int& +static_cast(y) = 1 ; // ERROR: cannot modify a const value +get(y) = 1 ; // ERROR: cannot modify a const value +``` + +[warning + +The __value_initialized__ implementation of Boost version 1.40.0 and older +allowed ['non-const] access to the wrapped object, from a constant wrapper, +both by its conversion operator and its `data()` member function. + +For example: + +``` +__value_initialized__ const x_c; +int& xr = x_c ; // OK, conversion to int& available even though x_c is itself const. +xr = 2 ; +``` + +The reason for this obscure behavior was that some compilers did not accept the following valid code: + +``` +struct X +{ + operator int&() ; + operator int const&() const ; + }; + X x ; + (x == 1) ; // ERROR HERE! +``` + +The current version of __value_initialized__ no longer has this obscure behavior. +As compilers nowadays widely support overloading the conversion operator by having a `const` +and a `non-const` version, we have decided to fix the issue accordingly. So the current version +supports the idea of logical constness. + +] + +[h5 Recommended practice: The non-member get() idiom] + +The obscure behavior of being able to modify a non-`const` +wrapped object from within a constant wrapper (as was supported by previous +versions of __value_initialized__) can be avoided if access to the wrapped object +is always performed with the `get()` idiom: + +``` +value_initialized x; +get(x) = 1; // OK +value_initialized cx; +get(x) = 1; // ERROR: Cannot modify a const object + +value_initialized const x_c; +get(x_c) = 1; // ERROR: Cannot modify a const object + +value_initialized const cx_c; +get(cx_c) = 1; // ERROR: Cannot modify a const object +``` + +[endsect] + +[#sec:initialized] +[section `template class initialized`] + + +``` +namespace boost { + +template +class __initialized__ +{ + + public : + + __initialized__() : x() {} + + explicit __initialized__(T const & arg) : x(arg) {} + + operator T const &() const; + + operator T&(); + + T const &data() const; + + T& data(); + + void swap( __initialized__& ); + + private : + + [unspecified] x ; + +}; + +template +T const& get ( __initialized__ const& x ); + +template +T& get ( __initialized__& x ); + +template +void swap ( __initialized__& lhs, __initialized__& rhs ); + +} // namespace boost +``` + +The template class `boost::__initialized__` supports both value-initialization +and direct-initialization, so its interface is a superset of the interface +of `__value_initialized__`: Its default-constructor value-initializes the +wrapped object just like the default-constructor of `__value_initialized__`, +but `boost::__initialized__` also offers an extra `explicit` +constructor, which direct-initializes the wrapped object by the specified value. + +`__initialized__` is especially useful when the wrapped +object must be either value-initialized or direct-initialized, depending on +runtime conditions. For example, `__initialized__` could +hold the value of a data member that may be value-initialized by some +constructors, and direct-initialized by others. + +On the other hand, if it is known beforehand that the +object must ['always] be value-initialized, `__value_initialized__` +may be preferable. And if the object must always be +direct-initialized, none of the two wrappers really needs to be used. + +[endsect] + +[#sec:initialized_value] +[section `initialized_value`] + +``` +namespace boost { +class __initialized_value_t__ +{ + public : + template operator T() const ; +}; + +__initialized_value_t__ const initialized_value = {} ; + +} // namespace boost +``` + +__initialized_value__ provides a convenient way to get +an initialized value: its conversion operator provides an appropriate +['value-initialized] object for any __CopyConstructible__ type. + +Suppose you need to have an initialized variable of type `T`. +You could do it as follows: + +``` +T var = T(); +``` + +But as mentioned before, this form suffers from various compiler issues. +The template __value_initialized__ offers a workaround: + +``` +T var = get( __value_initialized__() ); +``` + +Unfortunately both forms repeat the type name, which +is rather short now (`T`), but could of course be +more like `Namespace::Template::Type`. + +Instead, one could use __initialized_value__ as follows: + +``` +T var = __initialized_value__; +``` + +[endsect] +[endsect] + +[#sec:references] +[section References] + +# Bjarne Stroustrup, Gabriel Dos Reis, and J. Stephen Adamczyk wrote various papers, +proposing to extend the support for brace-enclosed ['initializer lists] +in C++. This [@https://en.cppreference.com/w/cpp/language/list_initialization feature] has +now been available since C++11. This would allow a variable `var` of any __DefaultConstructible__ type +`T` to be ['value-initialized] by doing `T var = {}`. The papers are listed at Bjarne's web page, +[@http://www.research.att.com/~bs/WG21.html My C++ Standards committee papers]. + +# Scott Meyers, Effective C++, Third Edition, item 6, ['Explicitly disallow the use of +compiler-generated functions you do not want], [@http://www.aristeia.com/books.html Scott Meyers: Books and CDs] + +# The C++ Standard, Second edition (2003), ISO/IEC 14882:2003 + +# POD stands for [@https://en.cppreference.com/w/cpp/named_req/PODType "Plain Old Data"] + +[endsect] + +[/===============] +[xinclude tmp/value_init_reference.xml] +[/===============] + +[#sec:acknowledgements] +[section Acknowledgements] + +__value_initialized__ was developed by Fernando Cacciola, with help and suggestions +from David Abrahams and Darin Adler. + +Special thanks to Bjorn Karlsson who carefully edited and completed this documentation. + +__value_initialized__ was reimplemented by Fernando Cacciola and Niels Dekker +for Boost release version 1.35 (2008), offering a workaround to various compiler issues. + +`boost::__initialized__` was very much inspired by feedback from Edward Diener and Jeffrey Hellrung. + +__initialized_value__ was written by Niels Dekker, and added to Boost release version 1.36 (2008). + +Developed by [@mailto:fernando_cacciola@hotmail.com Fernando Cacciola]. The latest version of +this file can be found at [@http://www.boost.org www.boost.org]. + +[endsect] + +[endsect] diff --git a/libs/utility/enable_if.html b/libs/utility/enable_if.html new file mode 100644 index 00000000..323ad968 --- /dev/null +++ b/libs/utility/enable_if.html @@ -0,0 +1,19 @@ + + + Boost.EnableIf + + + +Automatic redirection failed, please go to +../core/doc/html/core/enable_if.html +
+ + Boost.EnableIf
+
+ 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/libs/utility/identity_type/doc/Jamfile.v2 b/libs/utility/identity_type/doc/Jamfile.v2 new file mode 100644 index 00000000..07ca29ec --- /dev/null +++ b/libs/utility/identity_type/doc/Jamfile.v2 @@ -0,0 +1,44 @@ + +# Copyright (C) 2009-2012 Lorenzo Caminiti +# Distributed under the Boost Software License, Version 1.0 +# (see accompanying file LICENSE_1_0.txt or a copy at +# http://www.boost.org/LICENSE_1_0.txt) +# Home at http://www.boost.org/libs/utility/identity_type + +import quickbook ; +using boostbook ; + +doxygen reference : ../../../../boost/utility/identity_type.hpp + : "Reference" + PREDEFINED="DOXYGEN" + QUIET=YES + WARN_IF_UNDOCUMENTED=NO + HIDE_UNDOC_MEMBERS=YES + HIDE_UNDOC_CLASSES=YES + ALIASES=" Params=\"Parameters: \" Param{2}=\"\" EndParams=\"
\\1\\2
\" Returns=\"Returns:\" Note=\"Note:\" Warning=\"Warning:\" See=\"See:\" RefSect{2}=\"\\xmlonly\\2\\endxmlonly\" RefClass{1}=\"\\xmlonly\\1\\endxmlonly\" RefFunc{1}=\"\\xmlonly\\1\\endxmlonly\" RefMacro{1}=\"\\xmlonly\\1\\endxmlonly\" " + ; + +# This target must be called "index" so to generate "index.html" file. +xml index : identity_type.qbk : reference ; + +boostbook doc : index + : html + onehtml + toc.section.depth=0 + html.stylesheet=../../../../../doc/src/boostbook.css + boost.root=../../../../.. + ; + +# +# This is very imperfect - it results in both html and pdf docs being built, +# for some reason I can't get the "onehtml" format specified above to play nice +# with the usual incantations for mixed pdf/html builds. JM 06/2012. +# +boostbook pdf_doc : index + : + pdf + html:no + ; + +install pdf_doc_install : pdf_doc : . identity_type.pdf PDF ; +explicit pdf_doc_install ; diff --git a/libs/utility/identity_type/doc/html/index.html b/libs/utility/identity_type/doc/html/index.html new file mode 100644 index 00000000..13869dbd --- /dev/null +++ b/libs/utility/identity_type/doc/html/index.html @@ -0,0 +1,252 @@ +Boost.Utility/IdentityType 1.0.0

Boost.Utility/IdentityType 1.0.0

Lorenzo Caminiti

+ Distributed under the Boost Software License, Version 1.0 (see accompanying + file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt) +

+ This library allows to wrap types within round parenthesis so they can always + be passed as macro parameters. +

+ Consider the following macro which declares a variable named varn + with the specified type (see also + var_error.cpp): +

+

#define VAR(type, n) type var ## n
+
+VAR(int, 1);                    // OK.
+VAR(std::map<int, char>, 2);    // Error.
+

+

+ The first macro invocation works correctly declaring a variable named var1 of type int. + However, the second macro invocation fails generating a preprocessor error + similar to the following: +

error: macro "VAR" passed 3 arguments, but takes just 2
+

+ That is because the std::map type passed as the first macro parameter + contains a comma , not wrapped + by round parenthesis (). The preprocessor + interprets that unwrapped comma as a separation between macro parameters concluding + that a total of three (and not two) parameters are passed to the macro in the + following order: +

  1. + std::map<int +
  2. + char> +
  3. + 2 +

+ Note that, differently from the compiler, the preprocessor only recognizes + round parenthesis (). Angular + <> and squared [] parenthesis are not recognized by the preprocessor + when parsing macro parameters. +

+ In some cases, it might be possible to workaround this issue by avoiding to + pass the type expression to the macro all together. For example, in the case + above a typedef could have been + used to specify the type expression with the commas outside the macro (see + also var.cpp): +

+

typedef std::map<int, char> map_type;
+VAR(map_type, 3); // OK.
+

+

+ When this is neither possible nor desired (e.g., see the function template + f in the section below), this + library header boost/utility/identity_type.hpp + defines a macro BOOST_IDENTITY_TYPE + which can be used to workaround the issue while keeping the type expression + as one of the macro parameters (see also var.cpp). +

+

#include <boost/utility/identity_type.hpp>
+
+VAR(BOOST_IDENTITY_TYPE((std::map<int, char>)), 4); // OK.
+

+

+ The BOOST_IDENTITY_TYPE macro + expands to an expression that evaluates (at compile-time) to the specified + type. The specified type is never split into multiple macro parameters because + it is always wrapped by a set of extra round parenthesis (). + In fact, a total of two sets of round parenthesis must be used: The parenthesis + to invoke the macro BOOST_IDENTITY_TYPE(...) plus the inner parenthesis to wrap the + type passed to the macro BOOST_IDENTITY_TYPE((...)). +

+ This macro works on any C++03 + compiler (and it does not use variadic + macros). [1] The authors originally developed and tested this library using + GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled + -std=c++0x) on Cygwin + and Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7. See the library regressions + test results for more information on supported compilers and platforms. +

+ This macro must be prefixed by typename + when used within templates. For example, let's program a macro that declares + a function parameter named argn + with the specified type (see also + template.cpp): +

+

#define ARG(type, n) type arg ## n
+
+template<typename T>
+void f( // Prefix macro with `typename` in templates.
+    ARG(typename BOOST_IDENTITY_TYPE((std::map<int, T>)), 1)
+) {
+    std::cout << arg1[0] << std::endl;
+}
+

+

+

std::map<int, char> a;
+a[0] = 'a';
+
+f<char>(a); // OK...
+// f(a);    // ... but error.
+

+

+ However, note that the template parameter char + must be manually specified when invoking the function as in f<char>(a). In fact, + when the BOOST_IDENTITY_TYPE + macro is used to wrap a function template parameter, the template parameter + can no longer be automatically deduced by the compiler form the function call + as f(a) would + have done. [2] (This limitation does not apply to class templates because class + template parameters must always be explicitly specified.) In other words, without + using the BOOST_IDENTITY_TYPE + macro, C++ would normally be able to automatically deduce the function template + parameter as shown below: +

+

template<typename T>
+void g(
+    std::map<int, T> arg1
+) {
+    std::cout << arg1[0] << std::endl;
+}
+

+

+

g<char>(a); // OK...
+g(a);       // ... and also OK.
+

+

+ On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes + with one or more pure virtual functions) generates a compiler error. This can + be avoided by manipulating the type adding and removing a reference to it. +

+ Let's program a macro that performs a static assertion on a Template + Meta-Programming (TMP) meta-function (similarly to Boost.MPL BOOST_MPL_ASSERT). The BOOST_IDENTITY_TYPE macro can be used + to pass a meta-function with multiple template parameters to the assert macro + (so to handle the commas separating the template parameters). In this case, + if the meta-function is an abstract type, it needs to be manipulated adding + and removing a reference to it (see also abstract.cpp): +

+

#define TMP_ASSERT(metafunction) \
+    BOOST_STATIC_ASSERT(metafunction::value)
+
+template<typename T, bool b>
+struct abstract {
+    static const bool value = b;
+    virtual void f(T const& x) = 0;     // Pure virtual function.
+};
+
+TMP_ASSERT(
+    boost::remove_reference<            // Add and remove
+        BOOST_IDENTITY_TYPE((           // reference for
+            boost::add_reference<       // abstract type.
+                abstract<int, true>
+            >::type
+        ))
+    >::type
+);
+

+

+ The BOOST_IDENTITY_TYPE macro + can be used either when calling a user-defined macro (as shown by the examples + so far), or internally when implementing a user-defined macro (as shown below). + When BOOST_IDENTITY_TYPE is + used in the implementation of the user-defined macro, the caller of the user + macro will have to specify the extra parenthesis (see also paren.cpp): +

+

#define TMP_ASSERT_PAREN(parenthesized_metafunction) \
+    /* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \
+    BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value)
+
+#define TMP_ASSERT(metafunction) \
+    BOOST_STATIC_ASSERT(metafunction::value)
+
+// Specify only extra parenthesis `((...))`.
+TMP_ASSERT_PAREN((boost::is_const<std::map<int, char> const>));
+
+// Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro.
+TMP_ASSERT(BOOST_IDENTITY_TYPE((boost::is_const<std::map<int, char> const>)));
+

+

+ However, note that the caller will always have to specify + the extra parenthesis even when the macro parameters contain no comma: +

+

TMP_ASSERT_PAREN((boost::is_const<int const>)); // Always extra `((...))`.
+
+TMP_ASSERT(boost::is_const<int const>); // No extra `((...))` and no macro.
+

+

+ In some cases, using BOOST_IDENTITY_TYPE + in the implementation of the user-defined macro might provide the best syntax + for the caller. For example, this is the case for BOOST_MPL_ASSERT + because the majority of template meta-programming expressions contain unwrapped + commas so it is less confusing for the user to always specify the extra parenthesis + ((...)) instead of using BOOST_IDENTITY_TYPE: +

BOOST_MPL_ASSERT(( // Natural syntax.
+    boost::mpl::and_<
+          boost::is_const<T>
+        , boost::is_reference<T>
+    >
+));
+

+ However, in other situations it might be preferable to not require the extra + parenthesis in the common cases and handle commas as special cases using BOOST_IDENTITY_TYPE. For example, this + is the case for BOOST_LOCAL_FUNCTION for which always + requiring the extra parenthesis ((...)) + around the types would lead to an unnatural syntax for the local function signature: +

int BOOST_LOCAL_FUNCTION( ((int&)) x, ((int&)) y ) { // Unnatural syntax.
+    return x + y;
+} BOOST_LOCAL_FUNCTION_NAME(add)
+

+ Instead requiring the user to specify BOOST_IDENTITY_TYPE + only when needed allows for the more natural syntax BOOST_LOCAL_FUNCTION(int& + x, int& y) in the common cases when the parameter types + contain no comma (while still allowing to specify parameter types with commas + as special cases using BOOST_LOCAL_FUNCTION(BOOST_IDENTITY_TYPE((std::map<int, char>))& + x, int& y)). +

+ The implementation of this library macro is equivalent to the following: [3] +

#include <boost/type_traits/function_traits.hpp>
+
+#define BOOST_IDENTITY_TYPE(parenthesized_type) \
+    boost::function_traits<void parenthesized_type>::arg1_type
+

+ Essentially, the type is wrapped between round parenthesis (std::map<int, + char>) + so it can be passed as a single macro parameter even if it contains commas. + Then the parenthesized type is transformed into the type of a function returning + void and with the specified type + as the type of the first and only argument void + (std::map<int, char>). Finally, the type of the first argument + arg1_type is extracted at compile-time + using the function_traits meta-function + therefore obtaining the original type from the parenthesized type (effectively + stripping the extra parenthesis from around the specified type). +

Reference

Wrap type expressions with round parenthesis so they can be passed to macros even if they contain commas.

+
+BOOST_IDENTITY_TYPE(parenthesized_type)

Macro BOOST_IDENTITY_TYPE

BOOST_IDENTITY_TYPE — This macro allows to wrap the specified type expression within extra round parenthesis so the type can be passed as a single macro parameter even if it contains commas (not already wrapped within round parenthesis).

Synopsis

// In header: <boost/utility/identity_type.hpp>
+
+BOOST_IDENTITY_TYPE(parenthesized_type)

Description

Parameters:

parenthesized_typeThe type expression to be passed as macro parameter wrapped by a single set of round parenthesis (...). This type expression can contain an arbitrary number of commas.

+

This macro works on any C++03 compiler (it does not use variadic macros).

This macro must be prefixed by typename when used within templates. Note that the compiler will not be able to automatically determine function template parameters when they are wrapped with this macro (these parameters need to be explicitly specified when calling the function template).

On some compilers (like GCC), using this macro on abstract types requires to add and remove a reference to the specified type.



[1] + Using variadic macros, it would be possible to require a single set of extra + parenthesis BOOST_IDENTITY_TYPE(type) instead of two BOOST_IDENTITY_TYPE((type)) but variadic macros are not part of C++03 + (even if nowadays they are supported by most modern compilers and they are + also part of C++11). +

[2] + This is because the implementation of BOOST_IDENTITY_TYPE + wraps the specified type within a meta-function. +

[3] + There is absolutely no guarantee that the macro is actually implemented using + the code listed in this documentation. The listed code is for explanatory + purposes only. +

diff --git a/libs/utility/identity_type/doc/identity_type.qbk b/libs/utility/identity_type/doc/identity_type.qbk new file mode 100644 index 00000000..1c97616e --- /dev/null +++ b/libs/utility/identity_type/doc/identity_type.qbk @@ -0,0 +1,165 @@ + +[/ Copyright (C) 2009-2012 Lorenzo Caminiti ] +[/ Distributed under the Boost Software License, Version 1.0 ] +[/ (see accompanying file LICENSE_1_0.txt or a copy at ] +[/ http://www.boost.org/LICENSE_1_0.txt) ] +[/ Home at http://www.boost.org/libs/utility/identity_type ] + +[library Boost.Utility/IdentityType + [quickbook 1.5] + [version 1.0.0] + [copyright 2009-2012 Lorenzo Caminiti] + [purpose wraps types with round parenthesis] + [license + Distributed under the Boost Software License, Version 1.0 + (see accompanying file LICENSE_1_0.txt or a copy at + [@http://www.boost.org/LICENSE_1_0.txt]) + ] + [authors [Caminiti lorcaminiti@gmail.com, Lorenzo]] + [category Utilities] +] + +This library allows to wrap types within round parenthesis so they can always be passed as macro parameters. + +[import ../test/var_error.cpp] +[import ../test/var.cpp] +[import ../test/template.cpp] +[import ../test/abstract.cpp] +[import ../test/paren.cpp] + +[section Motivation] + +Consider the following macro which declares a variable named `var`[^['n]] with the specified [^['type]] (see also [@../../test/var_error.cpp =var_error.cpp=]): + +[var_error] + +The first macro invocation works correctly declaring a variable named `var1` of type `int`. +However, the second macro invocation fails generating a preprocessor error similar to the following: + +[pre + error: macro "VAR" passed 3 arguments, but takes just 2 +] + +That is because the `std::map` type passed as the first macro parameter contains a comma `,` not wrapped by round parenthesis `()`. +The preprocessor interprets that unwrapped comma as a separation between macro parameters concluding that a total of three (and not two) parameters are passed to the macro in the following order: + +# `std::map` +# `2` + +Note that, differently from the compiler, the preprocessor only recognizes round parenthesis `()`. +Angular `<>` and squared `[]` parenthesis are not recognized by the preprocessor when parsing macro parameters. + +[endsect] + +[section Solution] + +In some cases, it might be possible to workaround this issue by avoiding to pass the type expression to the macro all together. +For example, in the case above a `typedef` could have been used to specify the type expression with the commas outside the macro (see also [@../../test/var.cpp =var.cpp=]): + +[var_typedef] + +When this is neither possible nor desired (e.g., see the function template `f` in the section below), this library header [headerref boost/utility/identity_type.hpp] defines a macro [macroref BOOST_IDENTITY_TYPE] which can be used to workaround the issue while keeping the type expression as one of the macro parameters (see also [@../../test/var.cpp =var.cpp=]). + +[var_ok] + +The [macroref BOOST_IDENTITY_TYPE] macro expands to an expression that evaluates (at compile-time) to the specified type. +The specified type is never split into multiple macro parameters because it is always wrapped by a set of extra round parenthesis `()`. +In fact, a total of two sets of round parenthesis must be used: The parenthesis to invoke the macro `BOOST_IDENTITY_TYPE(...)` plus the inner parenthesis to wrap the type passed to the macro `BOOST_IDENTITY_TYPE((...))`. + +This macro works on any [@http://www.open-std.org/JTC1/SC22/WG21/docs/standards C++03] compiler (and it does not use [@http://en.wikipedia.org/wiki/Variadic_macro variadic macros]). +[footnote +Using variadic macros, it would be possible to require a single set of extra parenthesis `BOOST_IDENTITY_TYPE(`[^['type]]`)` instead of two `BOOST_IDENTITY_TYPE((`[^['type]]`))` but variadic macros are not part of C++03 (even if nowadays they are supported by most modern compilers and they are also part of C++11). +] +The authors originally developed and tested this library using GNU Compiler Collection (GCC) C++ 4.5.3 (with and without C++11 features enabled `-std=c++0x`) on Cygwin and Miscrosoft Visual C++ (MSVC) 8.0 on Windows 7. +See the library [@http://www.boost.org/development/tests/release/developer/utility-identity_type.html regressions test results] for more information on supported compilers and platforms. + +[endsect] + +[section Templates] + +This macro must be prefixed by `typename` when used within templates. +For example, let's program a macro that declares a function parameter named `arg`[^['n]] with the specified [^['type]] (see also [@../../test/template.cpp =template.cpp=]): + +[template_f_decl] +[template_f_call] + +However, note that the template parameter `char` must be manually specified when invoking the function as in `f(a)`. +In fact, when the [macroref BOOST_IDENTITY_TYPE] macro is used to wrap a function template parameter, the template parameter can no longer be automatically deduced by the compiler form the function call as `f(a)` would have done. +[footnote +This is because the implementation of [macroref BOOST_IDENTITY_TYPE] wraps the specified type within a meta-function. +] +(This limitation does not apply to class templates because class template parameters must always be explicitly specified.) +In other words, without using the [macroref BOOST_IDENTITY_TYPE] macro, C++ would normally be able to automatically deduce the function template parameter as shown below: + +[template_g_decl] +[template_g_call] + +[endsect] + +[section Abstract Types] + +On some compilers (e.g., GCC), using this macro on abstract types (i.e., classes with one or more pure virtual functions) generates a compiler error. +This can be avoided by manipulating the type adding and removing a reference to it. + +Let's program a macro that performs a static assertion on a [@http://en.wikipedia.org/wiki/Template_metaprogramming Template Meta-Programming] (TMP) meta-function (similarly to Boost.MPL [@http://www.boost.org/doc/libs/1_36_0/libs/mpl/doc/refmanual/assert.html `BOOST_MPL_ASSERT`]). +The [macroref BOOST_IDENTITY_TYPE] macro can be used to pass a meta-function with multiple template parameters to the assert macro (so to handle the commas separating the template parameters). +In this case, if the meta-function is an abstract type, it needs to be manipulated adding and removing a reference to it (see also [@../../test/abstract.cpp =abstract.cpp=]): + +[abstract] + +[endsect] + +[section Annex: Usage] + +The [macroref BOOST_IDENTITY_TYPE] macro can be used either when calling a user-defined macro (as shown by the examples so far), or internally when implementing a user-defined macro (as shown below). +When [macroref BOOST_IDENTITY_TYPE] is used in the implementation of the user-defined macro, the caller of the user macro will have to specify the extra parenthesis (see also [@../../test/paren.cpp =paren.cpp=]): + +[paren] + +However, note that the caller will /always/ have to specify the extra parenthesis even when the macro parameters contain no comma: + +[paren_always] + +In some cases, using [macroref BOOST_IDENTITY_TYPE] in the implementation of the user-defined macro might provide the best syntax for the caller. +For example, this is the case for `BOOST_MPL_ASSERT` because the majority of template meta-programming expressions contain unwrapped commas so it is less confusing for the user to always specify the extra parenthesis `((...))` instead of using [macroref BOOST_IDENTITY_TYPE]: + + BOOST_MPL_ASSERT(( // Natural syntax. + boost::mpl::and_< + boost::is_const + , boost::is_reference + > + )); + +However, in other situations it might be preferable to not require the extra parenthesis in the common cases and handle commas as special cases using [macroref BOOST_IDENTITY_TYPE]. +For example, this is the case for [@http://www.boost.org/libs/local_function `BOOST_LOCAL_FUNCTION`] for which always requiring the extra parenthesis `((...))` around the types would lead to an unnatural syntax for the local function signature: + + int BOOST_LOCAL_FUNCTION( ((int&)) x, ((int&)) y ) { // Unnatural syntax. + return x + y; + } BOOST_LOCAL_FUNCTION_NAME(add) + +Instead requiring the user to specify [macroref BOOST_IDENTITY_TYPE] only when needed allows for the more natural syntax `BOOST_LOCAL_FUNCTION(int& x, int& y)` in the common cases when the parameter types contain no comma (while still allowing to specify parameter types with commas as special cases using `BOOST_LOCAL_FUNCTION(BOOST_IDENTITY_TYPE((std::map))& x, int& y)`). + +[endsect] + +[section Annex: Implementation] + +The implementation of this library macro is equivalent to the following: +[footnote +There is absolutely no guarantee that the macro is actually implemented using the code listed in this documentation. +The listed code is for explanatory purposes only. +] + + #include + + #define BOOST_IDENTITY_TYPE(parenthesized_type) \ + boost::function_traits::arg1_type + +Essentially, the type is wrapped between round parenthesis `(std::map)` so it can be passed as a single macro parameter even if it contains commas. +Then the parenthesized type is transformed into the type of a function returning `void` and with the specified type as the type of the first and only argument `void (std::map)`. +Finally, the type of the first argument `arg1_type` is extracted at compile-time using the `function_traits` meta-function therefore obtaining the original type from the parenthesized type (effectively stripping the extra parenthesis from around the specified type). + +[endsect] + +[xinclude reference.xml] + diff --git a/libs/utility/identity_type/index.html b/libs/utility/identity_type/index.html new file mode 100644 index 00000000..f4bdcb10 --- /dev/null +++ b/libs/utility/identity_type/index.html @@ -0,0 +1,15 @@ + + + + + + + Automatic redirection failed, click this + link  
+

Copyright © Lorenzo Caminiti, 2009-2012

+

Distributed under the Boost Software License, Version 1.0 (see + accompanying file + LICENSE_1_0.txt or a copy at + www.boost.org/LICENSE_1_0.txt)

+ + diff --git a/libs/utility/identity_type/test/Jamfile.v2 b/libs/utility/identity_type/test/Jamfile.v2 new file mode 100644 index 00000000..5cb50366 --- /dev/null +++ b/libs/utility/identity_type/test/Jamfile.v2 @@ -0,0 +1,16 @@ + +# Copyright (C) 2009-2012 Lorenzo Caminiti +# Distributed under the Boost Software License, Version 1.0 +# (see accompanying file LICENSE_1_0.txt or a copy at +# http://www.boost.org/LICENSE_1_0.txt) +# Home at http://www.boost.org/libs/utility/identity_type + +import testing ; + +compile-fail var_error.cpp ; +run var.cpp ; +run template.cpp ; +run abstract.cpp ; +run noncopyable.cpp ; +run paren.cpp ; + diff --git a/libs/utility/identity_type/test/abstract.cpp b/libs/utility/identity_type/test/abstract.cpp new file mode 100644 index 00000000..39b10c35 --- /dev/null +++ b/libs/utility/identity_type/test/abstract.cpp @@ -0,0 +1,35 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include +#include +#include +#include + +//[abstract +#define TMP_ASSERT(metafunction) \ + BOOST_STATIC_ASSERT(metafunction::value) + +template +struct abstract { + static const bool value = b; + virtual void f(T const& x) = 0; // Pure virtual function. +}; + +TMP_ASSERT( + boost::remove_reference< // Add and remove + BOOST_IDENTITY_TYPE(( // reference for + boost::add_reference< // abstract type. + abstract + >::type + )) + >::type +); +//] + +int main() { return 0; } + diff --git a/libs/utility/identity_type/test/noncopyable.cpp b/libs/utility/identity_type/test/noncopyable.cpp new file mode 100644 index 00000000..2819e685 --- /dev/null +++ b/libs/utility/identity_type/test/noncopyable.cpp @@ -0,0 +1,25 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include +#include +#include + +//[noncopyable +#define TMP_ASSERT(metafunction) \ + BOOST_STATIC_ASSERT(metafunction::value) + +template +struct noncopyable : boost::noncopyable { + static const T value = init; +}; + +TMP_ASSERT(BOOST_IDENTITY_TYPE((noncopyable))); +//] + +int main() { return 0; } + diff --git a/libs/utility/identity_type/test/paren.cpp b/libs/utility/identity_type/test/paren.cpp new file mode 100644 index 00000000..51b355fe --- /dev/null +++ b/libs/utility/identity_type/test/paren.cpp @@ -0,0 +1,35 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include +#include +#include +#include + +//[paren +#define TMP_ASSERT_PAREN(parenthesized_metafunction) \ + /* use `BOOST_IDENTITY_TYPE` in macro definition instead of invocation */ \ + BOOST_STATIC_ASSERT(BOOST_IDENTITY_TYPE(parenthesized_metafunction)::value) + +#define TMP_ASSERT(metafunction) \ + BOOST_STATIC_ASSERT(metafunction::value) + +// Specify only extra parenthesis `((...))`. +TMP_ASSERT_PAREN((boost::is_const const>)); + +// Specify both the extra parenthesis `((...))` and `BOOST_IDENTITY_TYPE` macro. +TMP_ASSERT(BOOST_IDENTITY_TYPE((boost::is_const const>))); +//] + +//[paren_always +TMP_ASSERT_PAREN((boost::is_const)); // Always extra `((...))`. + +TMP_ASSERT(boost::is_const); // No extra `((...))` and no macro. +//] + +int main() { return 0; } + diff --git a/libs/utility/identity_type/test/template.cpp b/libs/utility/identity_type/test/template.cpp new file mode 100644 index 00000000..dfc10979 --- /dev/null +++ b/libs/utility/identity_type/test/template.cpp @@ -0,0 +1,48 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include +#include +#include + +//[template_f_decl +#define ARG(type, n) type arg ## n + +template +void f( // Prefix macro with `typename` in templates. + ARG(typename BOOST_IDENTITY_TYPE((std::map)), 1) +) { + std::cout << arg1[0] << std::endl; +} +//] + +//[template_g_decl +template +void g( + std::map arg1 +) { + std::cout << arg1[0] << std::endl; +} +//] + +int main() { + //[template_f_call + std::map a; + a[0] = 'a'; + + f(a); // OK... + // f(a); // ... but error. + //] + + //[template_g_call + g(a); // OK... + g(a); // ... and also OK. + //] + + return 0; +} + diff --git a/libs/utility/identity_type/test/var.cpp b/libs/utility/identity_type/test/var.cpp new file mode 100644 index 00000000..9ed165d7 --- /dev/null +++ b/libs/utility/identity_type/test/var.cpp @@ -0,0 +1,26 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include + +#define VAR(type, n) type var ## n + +VAR(int, 1); // OK. + +//[var_typedef +typedef std::map map_type; +VAR(map_type, 3); // OK. +//] + +//[var_ok +#include + +VAR(BOOST_IDENTITY_TYPE((std::map)), 4); // OK. +//] + +int main() { return 0; } + diff --git a/libs/utility/identity_type/test/var_error.cpp b/libs/utility/identity_type/test/var_error.cpp new file mode 100644 index 00000000..efb9743f --- /dev/null +++ b/libs/utility/identity_type/test/var_error.cpp @@ -0,0 +1,18 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +#include + +//[var_error +#define VAR(type, n) type var ## n + +VAR(int, 1); // OK. +VAR(std::map, 2); // Error. +//] + +int main() { return 0; } + diff --git a/libs/utility/in_place_factories.html b/libs/utility/in_place_factories.html new file mode 100644 index 00000000..ec8ed820 --- /dev/null +++ b/libs/utility/in_place_factories.html @@ -0,0 +1,19 @@ + + + Boost.InPlaceFactory + + + +Automatic redirection failed, please go to +./doc/html/utility/utilities/in_place_factory.html +
+ + Boost.InPlaceFactory
+
+ 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/libs/utility/include/boost/call_traits.hpp b/libs/utility/include/boost/call_traits.hpp new file mode 100644 index 00000000..2c1328e9 --- /dev/null +++ b/libs/utility/include/boost/call_traits.hpp @@ -0,0 +1,20 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/utility for most recent version including documentation. + +// See boost/detail/call_traits.hpp +// for full copyright notices. + +#ifndef BOOST_CALL_TRAITS_HPP +#define BOOST_CALL_TRAITS_HPP + +#ifndef BOOST_CONFIG_HPP +#include +#endif + +#include + +#endif // BOOST_CALL_TRAITS_HPP diff --git a/libs/utility/include/boost/compressed_pair.hpp b/libs/utility/include/boost/compressed_pair.hpp new file mode 100644 index 00000000..a7be0f2b --- /dev/null +++ b/libs/utility/include/boost/compressed_pair.hpp @@ -0,0 +1,20 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/utility for most recent version including documentation. + +// See boost/detail/compressed_pair.hpp +// for full copyright notices. + +#ifndef BOOST_COMPRESSED_PAIR_HPP +#define BOOST_COMPRESSED_PAIR_HPP + +#ifndef BOOST_CONFIG_HPP +#include +#endif + +#include + +#endif // BOOST_COMPRESSED_PAIR_HPP diff --git a/libs/utility/include/boost/detail/call_traits.hpp b/libs/utility/include/boost/detail/call_traits.hpp new file mode 100644 index 00000000..feca93da --- /dev/null +++ b/libs/utility/include/boost/detail/call_traits.hpp @@ -0,0 +1,172 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/utility for most recent version including documentation. + +// call_traits: defines typedefs for function usage +// (see libs/utility/call_traits.htm) + +/* Release notes: + 23rd July 2000: + Fixed array specialization. (JM) + Added Borland specific fixes for reference types + (issue raised by Steve Cleary). +*/ + +#ifndef BOOST_DETAIL_CALL_TRAITS_HPP +#define BOOST_DETAIL_CALL_TRAITS_HPP + +#ifndef BOOST_CONFIG_HPP +#include +#endif +#include + +#include +#include +#include +#include + +namespace boost{ + +namespace detail{ + +template +struct ct_imp2 +{ + typedef const T& param_type; +}; + +template +struct ct_imp2 +{ + typedef const T param_type; +}; + +template +struct ct_imp +{ + typedef const T& param_type; +}; + +template +struct ct_imp +{ + typedef typename ct_imp2::param_type param_type; +}; + +template +struct ct_imp +{ + typedef typename ct_imp2::param_type param_type; +}; + +template +struct ct_imp +{ + typedef const T param_type; +}; + +} + +template +struct call_traits +{ +public: + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + // + // C++ Builder workaround: we should be able to define a compile time + // constant and pass that as a single template parameter to ct_imp, + // however compiler bugs prevent this - instead pass three bool's to + // ct_imp and add an extra partial specialisation + // of ct_imp to handle the logic. (JM) + typedef typename boost::detail::ct_imp< + T, + ::boost::is_pointer::value, + ::boost::is_arithmetic::value, + ::boost::is_enum::value + >::param_type param_type; +}; + +template +struct call_traits +{ + typedef T& value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T& param_type; // hh removed const +}; + +#if BOOST_WORKAROUND( BOOST_BORLANDC, < 0x5A0 ) +// these are illegal specialisations; cv-qualifies applied to +// references have no effect according to [8.3.2p1], +// C++ Builder requires them though as it treats cv-qualified +// references as distinct types... +template +struct call_traits +{ + typedef T& value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T& param_type; // hh removed const +}; +template +struct call_traits +{ + typedef T& value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T& param_type; // hh removed const +}; +template +struct call_traits +{ + typedef T& value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T& param_type; // hh removed const +}; + +template +struct call_traits< T * > +{ + typedef T * value_type; + typedef T * & reference; + typedef T * const & const_reference; + typedef T * const param_type; // hh removed const +}; +#endif +#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS) +template +struct call_traits +{ +private: + typedef T array_type[N]; +public: + // degrades array to pointer: + typedef const T* value_type; + typedef array_type& reference; + typedef const array_type& const_reference; + typedef const T* const param_type; +}; + +template +struct call_traits +{ +private: + typedef const T array_type[N]; +public: + // degrades array to pointer: + typedef const T* value_type; + typedef array_type& reference; + typedef const array_type& const_reference; + typedef const T* const param_type; +}; +#endif + +} + +#endif // BOOST_DETAIL_CALL_TRAITS_HPP diff --git a/libs/utility/include/boost/detail/compressed_pair.hpp b/libs/utility/include/boost/detail/compressed_pair.hpp new file mode 100644 index 00000000..28de0bfc --- /dev/null +++ b/libs/utility/include/boost/detail/compressed_pair.hpp @@ -0,0 +1,456 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/utility for most recent version including documentation. + +// compressed_pair: pair that "compresses" empty members +// (see libs/utility/doc/html/compressed_pair.html) +// +// JM changes 25 Jan 2004: +// For the case where T1 == T2 and both are empty, then first() and second() +// should return different objects. +// JM changes 25 Jan 2000: +// Removed default arguments from compressed_pair_switch to get +// C++ Builder 4 to accept them +// rewriten swap to get gcc and C++ builder to compile. +// added partial specialisations for case T1 == T2 to avoid duplicate constructor defs. + +#ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP +#define BOOST_DETAIL_COMPRESSED_PAIR_HPP + +#include + +#include +#include +#include +#include +#include + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable:4512) +#endif +namespace boost +{ + +template +class compressed_pair; + + +// compressed_pair + +namespace details +{ + template::value> + struct compressed_pair_empty + : ::boost::false_type { }; + + template + struct compressed_pair_empty + : ::boost::is_empty { }; + + // JM altered 26 Jan 2000: + template + struct compressed_pair_switch; + + template + struct compressed_pair_switch + {static const int value = 0;}; + + template + struct compressed_pair_switch + {static const int value = 3;}; + + template + struct compressed_pair_switch + {static const int value = 1;}; + + template + struct compressed_pair_switch + {static const int value = 2;}; + + template + struct compressed_pair_switch + {static const int value = 4;}; + + template + struct compressed_pair_switch + {static const int value = 5;}; + + template class compressed_pair_imp; + +#ifdef __GNUC__ + // workaround for GCC (JM): + using std::swap; +#endif + // + // can't call unqualified swap from within classname::swap + // as Koenig lookup rules will find only the classname::swap + // member function not the global declaration, so use cp_swap + // as a forwarding function (JM): + template + inline void cp_swap(T& t1, T& t2) + { +#ifndef __GNUC__ + using std::swap; +#endif + swap(t1, t2); + } + + // 0 derive from neither + + template + class compressed_pair_imp + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_(x), second_(y) {} + + compressed_pair_imp(first_param_type x) + : first_(x) {} + + compressed_pair_imp(second_param_type y) + : second_(y) {} + + first_reference first() {return first_;} + first_const_reference first() const {return first_;} + + second_reference second() {return second_;} + second_const_reference second() const {return second_;} + + void swap(::boost::compressed_pair& y) + { + cp_swap(first_, y.first()); + cp_swap(second_, y.second()); + } + private: + first_type first_; + second_type second_; + }; + + // 1 derive from T1 + + template + class compressed_pair_imp + : protected ::boost::remove_cv::type + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_type(x), second_(y) {} + + compressed_pair_imp(first_param_type x) + : first_type(x) {} + + compressed_pair_imp(second_param_type y) + : second_(y) {} + + first_reference first() {return *this;} + first_const_reference first() const {return *this;} + + second_reference second() {return second_;} + second_const_reference second() const {return second_;} + + void swap(::boost::compressed_pair& y) + { + // no need to swap empty base class: + cp_swap(second_, y.second()); + } + private: + second_type second_; + }; + + // 2 derive from T2 + + template + class compressed_pair_imp + : protected ::boost::remove_cv::type + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : second_type(y), first_(x) {} + + compressed_pair_imp(first_param_type x) + : first_(x) {} + + compressed_pair_imp(second_param_type y) + : second_type(y) {} + + first_reference first() {return first_;} + first_const_reference first() const {return first_;} + + second_reference second() {return *this;} + second_const_reference second() const {return *this;} + + void swap(::boost::compressed_pair& y) + { + // no need to swap empty base class: + cp_swap(first_, y.first()); + } + + private: + first_type first_; + }; + + // 3 derive from T1 and T2 + + template + class compressed_pair_imp + : protected ::boost::remove_cv::type, + protected ::boost::remove_cv::type + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_type(x), second_type(y) {} + + compressed_pair_imp(first_param_type x) + : first_type(x) {} + + compressed_pair_imp(second_param_type y) + : second_type(y) {} + + first_reference first() {return *this;} + first_const_reference first() const {return *this;} + + second_reference second() {return *this;} + second_const_reference second() const {return *this;} + // + // no need to swap empty bases: + void swap(::boost::compressed_pair&) {} + }; + + // JM + // 4 T1 == T2, T1 and T2 both empty + // Originally this did not store an instance of T2 at all + // but that led to problems beause it meant &x.first() == &x.second() + // which is not true for any other kind of pair, so now we store an instance + // of T2 just in case the user is relying on first() and second() returning + // different objects (albeit both empty). + template + class compressed_pair_imp + : protected ::boost::remove_cv::type + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_type(x), m_second(y) {} + + compressed_pair_imp(first_param_type x) + : first_type(x), m_second(x) {} + + first_reference first() {return *this;} + first_const_reference first() const {return *this;} + + second_reference second() {return m_second;} + second_const_reference second() const {return m_second;} + + void swap(::boost::compressed_pair&) {} + private: + T2 m_second; + }; + + // 5 T1 == T2 and are not empty: //JM + + template + class compressed_pair_imp + { + public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_imp() {} + + compressed_pair_imp(first_param_type x, second_param_type y) + : first_(x), second_(y) {} + + compressed_pair_imp(first_param_type x) + : first_(x), second_(x) {} + + first_reference first() {return first_;} + first_const_reference first() const {return first_;} + + second_reference second() {return second_;} + second_const_reference second() const {return second_;} + + void swap(::boost::compressed_pair& y) + { + cp_swap(first_, y.first()); + cp_swap(second_, y.second()); + } + private: + first_type first_; + second_type second_; + }; + +} // details + +template +class compressed_pair +#ifndef BOOST_UTILITY_DOCS + : private ::boost::details::compressed_pair_imp::type, typename remove_cv::type>::value, + ::boost::details::compressed_pair_empty::value, + ::boost::details::compressed_pair_empty::value>::value> +#endif // BOOST_UTILITY_DOCS +{ +private: + typedef details::compressed_pair_imp::type, typename remove_cv::type>::value, + ::boost::details::compressed_pair_empty::value, + ::boost::details::compressed_pair_empty::value>::value> base; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair() : base() {} + compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} + explicit compressed_pair(first_param_type x) : base(x) {} + explicit compressed_pair(second_param_type y) : base(y) {} + + first_reference first() {return base::first();} + first_const_reference first() const {return base::first();} + + second_reference second() {return base::second();} + second_const_reference second() const {return base::second();} + + void swap(compressed_pair& y) { base::swap(y); } +}; + +// JM +// Partial specialisation for case where T1 == T2: +// +template +class compressed_pair +#ifndef BOOST_UTILITY_DOCS + : private details::compressed_pair_imp::type, typename remove_cv::type>::value, + ::boost::details::compressed_pair_empty::value, + ::boost::details::compressed_pair_empty::value>::value> +#endif // BOOST_UTILITY_DOCS +{ +private: + typedef details::compressed_pair_imp::type, typename remove_cv::type>::value, + ::boost::details::compressed_pair_empty::value, + ::boost::details::compressed_pair_empty::value>::value> base; +public: + typedef T first_type; + typedef T second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair() : base() {} + compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} +#if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) + explicit +#endif + compressed_pair(first_param_type x) : base(x) {} + + first_reference first() {return base::first();} + first_const_reference first() const {return base::first();} + + second_reference second() {return base::second();} + second_const_reference second() const {return base::second();} + + void swap(::boost::compressed_pair& y) { base::swap(y); } +}; + +template +inline +void +swap(compressed_pair& x, compressed_pair& y) +{ + x.swap(y); +} + +} // boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP + diff --git a/libs/utility/include/boost/detail/ob_compressed_pair.hpp b/libs/utility/include/boost/detail/ob_compressed_pair.hpp new file mode 100644 index 00000000..4621be35 --- /dev/null +++ b/libs/utility/include/boost/detail/ob_compressed_pair.hpp @@ -0,0 +1,498 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Use, modification and distribution are subject to 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). +// +// See http://www.boost.org/libs/utility for most recent version including documentation. +// see libs/utility/compressed_pair.hpp +// +/* Release notes: + 20 Jan 2001: + Fixed obvious bugs (David Abrahams) + 07 Oct 2000: + Added better single argument constructor support. + 03 Oct 2000: + Added VC6 support (JM). + 23rd July 2000: + Additional comments added. (JM) + Jan 2000: + Original version: this version crippled for use with crippled compilers + - John Maddock Jan 2000. +*/ + +#ifndef BOOST_UTILITY_DOCS +#ifndef BOOST_OB_COMPRESSED_PAIR_HPP +#define BOOST_OB_COMPRESSED_PAIR_HPP + + +#include +#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP +#include +#endif +#ifndef BOOST_SAME_TRAITS_HPP +#include +#endif +#ifndef BOOST_CALL_TRAITS_HPP +#include +#endif + +namespace boost +{ +#ifdef BOOST_MSVC6_MEMBER_TEMPLATES +// +// use member templates to emulate +// partial specialisation. Note that due to +// problems with overload resolution with VC6 +// each of the compressed_pair versions that follow +// have one template single-argument constructor +// in place of two specific constructors: +// + +template +class compressed_pair; + +namespace detail{ + +template +struct best_conversion_traits +{ + typedef char one; + typedef char (&two)[2]; + static A a; + static one test(T1); + static two test(T2); + + enum { value = sizeof(test(a)) }; +}; + +template +struct init_one; + +template <> +struct init_one<1> +{ + template + static void init(const A& a, T1* p1, T2*) + { + *p1 = a; + } +}; + +template <> +struct init_one<2> +{ + template + static void init(const A& a, T1*, T2* p2) + { + *p2 = a; + } +}; + + +// T1 != T2, both non-empty +template +class compressed_pair_0 +{ +private: + T1 _first; + T2 _second; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_0() : _first(), _second() {} + compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {} + template + explicit compressed_pair_0(const A& val) + { + init_one::value>::init(val, &_first, &_second); + } + compressed_pair_0(const ::boost::compressed_pair& x) + : _first(x.first()), _second(x.second()) {} + +#if 0 + compressed_pair_0& operator=(const compressed_pair_0& x) { + cout << "assigning compressed pair 0" << endl; + _first = x._first; + _second = x._second; + cout << "finished assigning compressed pair 0" << endl; + return *this; + } +#endif + + first_reference first() { return _first; } + first_const_reference first() const { return _first; } + + second_reference second() { return _second; } + second_const_reference second() const { return _second; } + + void swap(compressed_pair_0& y) + { + using std::swap; + swap(_first, y._first); + swap(_second, y._second); + } +}; + +// T1 != T2, T2 empty +template +class compressed_pair_1 : T2 +{ +private: + T1 _first; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_1() : T2(), _first() {} + compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {} + + template + explicit compressed_pair_1(const A& val) + { + init_one::value>::init(val, &_first, static_cast(this)); + } + + compressed_pair_1(const ::boost::compressed_pair& x) + : T2(x.second()), _first(x.first()) {} + + first_reference first() { return _first; } + first_const_reference first() const { return _first; } + + second_reference second() { return *this; } + second_const_reference second() const { return *this; } + + void swap(compressed_pair_1& y) + { + // no need to swap empty base class: + using std::swap; + swap(_first, y._first); + } +}; + +// T1 != T2, T1 empty +template +class compressed_pair_2 : T1 +{ +private: + T2 _second; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_2() : T1(), _second() {} + compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {} + template + explicit compressed_pair_2(const A& val) + { + init_one::value>::init(val, static_cast(this), &_second); + } + compressed_pair_2(const ::boost::compressed_pair& x) + : T1(x.first()), _second(x.second()) {} + +#if 0 + compressed_pair_2& operator=(const compressed_pair_2& x) { + cout << "assigning compressed pair 2" << endl; + T1::operator=(x); + _second = x._second; + cout << "finished assigning compressed pair 2" << endl; + return *this; + } +#endif + first_reference first() { return *this; } + first_const_reference first() const { return *this; } + + second_reference second() { return _second; } + second_const_reference second() const { return _second; } + + void swap(compressed_pair_2& y) + { + // no need to swap empty base class: + using std::swap; + swap(_second, y._second); + } +}; + +// T1 != T2, both empty +template +class compressed_pair_3 : T1, T2 +{ +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_3() : T1(), T2() {} + compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {} + template + explicit compressed_pair_3(const A& val) + { + init_one::value>::init(val, static_cast(this), static_cast(this)); + } + compressed_pair_3(const ::boost::compressed_pair& x) + : T1(x.first()), T2(x.second()) {} + + first_reference first() { return *this; } + first_const_reference first() const { return *this; } + + second_reference second() { return *this; } + second_const_reference second() const { return *this; } + + void swap(compressed_pair_3& y) + { + // no need to swap empty base classes: + } +}; + +// T1 == T2, and empty +template +class compressed_pair_4 : T1 +{ +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_4() : T1() {} + compressed_pair_4(first_param_type x, second_param_type y) : T1(x), m_second(y) {} + // only one single argument constructor since T1 == T2 + explicit compressed_pair_4(first_param_type x) : T1(x), m_second(x) {} + compressed_pair_4(const ::boost::compressed_pair& x) + : T1(x.first()), m_second(x.second()) {} + + first_reference first() { return *this; } + first_const_reference first() const { return *this; } + + second_reference second() { return m_second; } + second_const_reference second() const { return m_second; } + + void swap(compressed_pair_4& y) + { + // no need to swap empty base classes: + } +private: + T2 m_second; +}; + +// T1 == T2, not empty +template +class compressed_pair_5 +{ +private: + T1 _first; + T2 _second; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair_5() : _first(), _second() {} + compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {} + // only one single argument constructor since T1 == T2 + explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {} + compressed_pair_5(const ::boost::compressed_pair& c) + : _first(c.first()), _second(c.second()) {} + + first_reference first() { return _first; } + first_const_reference first() const { return _first; } + + second_reference second() { return _second; } + second_const_reference second() const { return _second; } + + void swap(compressed_pair_5& y) + { + using std::swap; + swap(_first, y._first); + swap(_second, y._second); + } +}; + +template +struct compressed_pair_chooser +{ + template + struct rebind + { + typedef compressed_pair_0 type; + }; +}; + +template <> +struct compressed_pair_chooser +{ + template + struct rebind + { + typedef compressed_pair_1 type; + }; +}; + +template <> +struct compressed_pair_chooser +{ + template + struct rebind + { + typedef compressed_pair_2 type; + }; +}; + +template <> +struct compressed_pair_chooser +{ + template + struct rebind + { + typedef compressed_pair_3 type; + }; +}; + +template <> +struct compressed_pair_chooser +{ + template + struct rebind + { + typedef compressed_pair_4 type; + }; +}; + +template <> +struct compressed_pair_chooser +{ + template + struct rebind + { + typedef compressed_pair_5 type; + }; +}; + +template +struct compressed_pair_traits +{ +private: + typedef compressed_pair_chooser::value, is_empty::value, is_same::value> chooser; + typedef typename chooser::template rebind bound_type; +public: + typedef typename bound_type::type type; +}; + +} // namespace detail + +template +class compressed_pair : public detail::compressed_pair_traits::type +{ +private: + typedef typename detail::compressed_pair_traits::type base_type; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair() : base_type() {} + compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {} + template + explicit compressed_pair(const A& x) : base_type(x){} + + first_reference first() { return base_type::first(); } + first_const_reference first() const { return base_type::first(); } + + second_reference second() { return base_type::second(); } + second_const_reference second() const { return base_type::second(); } +}; + +template +inline void swap(compressed_pair& x, compressed_pair& y) +{ + x.swap(y); +} + +#else +// no partial specialisation, no member templates: + +template +class compressed_pair +{ +private: + T1 _first; + T2 _second; +public: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + typedef typename call_traits::reference first_reference; + typedef typename call_traits::reference second_reference; + typedef typename call_traits::const_reference first_const_reference; + typedef typename call_traits::const_reference second_const_reference; + + compressed_pair() : _first(), _second() {} + compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {} + explicit compressed_pair(first_param_type x) : _first(x), _second() {} + // can't define this in case T1 == T2: + // explicit compressed_pair(second_param_type y) : _first(), _second(y) {} + + first_reference first() { return _first; } + first_const_reference first() const { return _first; } + + second_reference second() { return _second; } + second_const_reference second() const { return _second; } + + void swap(compressed_pair& y) + { + using std::swap; + swap(_first, y._first); + swap(_second, y._second); + } +}; + +template +inline void swap(compressed_pair& x, compressed_pair& y) +{ + x.swap(y); +} + +#endif + +} // boost + +#endif // BOOST_OB_COMPRESSED_PAIR_HPP +#endif // BOOST_UTILITY_DOCS diff --git a/libs/utility/include/boost/operators.hpp b/libs/utility/include/boost/operators.hpp new file mode 100644 index 00000000..be56a2f8 --- /dev/null +++ b/libs/utility/include/boost/operators.hpp @@ -0,0 +1,920 @@ +// Boost operators.hpp header file ----------------------------------------// + +// (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001. +// (C) Copyright Daniel Frey 2002-2017. +// 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) + +// See http://www.boost.org/libs/utility/operators.htm for documentation. + +// Revision History +// 23 Nov 17 Protect dereferenceable<> from overloaded operator&. +// 15 Oct 17 Adapted to C++17, replace std::iterator<> with manual +// implementation. +// 22 Feb 16 Added ADL protection, preserve old work-arounds in +// operators_v1.hpp and clean up this file. (Daniel Frey) +// 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++ +// (Matthew Bradbury, fixes #4432) +// 07 Aug 08 Added "euclidean" spelling. (Daniel Frey) +// 03 Apr 08 Make sure "convertible to bool" is sufficient +// for T::operator<, etc. (Daniel Frey) +// 24 May 07 Changed empty_base to depend on T, see +// http://svn.boost.org/trac/boost/ticket/979 +// 21 Oct 02 Modified implementation of operators to allow compilers with a +// correct named return value optimization (NRVO) to produce optimal +// code. (Daniel Frey) +// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel) +// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker) +// 27 Aug 01 'left' form for non commutative operators added; +// additional classes for groups of related operators added; +// workaround for empty base class optimization +// bug of GCC 3.0 (Helmut Zeisel) +// 25 Jun 01 output_iterator_helper changes: removed default template +// parameters, added support for self-proxying, additional +// documentation and tests (Aleksey Gurtovoy) +// 29 May 01 Added operator classes for << and >>. Added input and output +// iterator helper classes. Added classes to connect equality and +// relational operators. Added classes for groups of related +// operators. Reimplemented example operator and iterator helper +// classes in terms of the new groups. (Daryle Walker, with help +// from Alexy Gurtovoy) +// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly +// supplied arguments from actually being used (Dave Abrahams) +// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and +// refactoring of compiler workarounds, additional documentation +// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from +// Dave Abrahams) +// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and +// Jeremy Siek (Dave Abrahams) +// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5 +// (Mark Rodgers) +// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy) +// 10 Jun 00 Support for the base class chaining technique was added +// (Aleksey Gurtovoy). See documentation and the comments below +// for the details. +// 12 Dec 99 Initial version with iterator operators (Jeremy Siek) +// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary +// specializations of dividable, subtractable, modable (Ed Brey) +// 17 Nov 99 Add comments (Beman Dawes) +// Remove unnecessary specialization of operators<> (Ed Brey) +// 15 Nov 99 Fix less_than_comparable second operand type for first two +// operators.(Beman Dawes) +// 12 Nov 99 Add operators templates (Ed Brey) +// 11 Nov 99 Add single template parameter version for compilers without +// partial specialization (Beman Dawes) +// 10 Nov 99 Initial version + +// 10 Jun 00: +// An additional optional template parameter was added to most of +// operator templates to support the base class chaining technique (see +// documentation for the details). Unfortunately, a straightforward +// implementation of this change would have broken compatibility with the +// previous version of the library by making it impossible to use the same +// template name (e.g. 'addable') for both the 1- and 2-argument versions of +// an operator template. This implementation solves the backward-compatibility +// issue at the cost of some simplicity. +// +// One of the complications is an existence of special auxiliary class template +// 'is_chained_base<>' (see 'operators_detail' namespace below), which is used +// to determine whether its template parameter is a library's operator template +// or not. You have to specialize 'is_chained_base<>' for each new +// operator template you add to the library. +// +// However, most of the non-trivial implementation details are hidden behind +// several local macros defined below, and as soon as you understand them, +// you understand the whole library implementation. + +#ifndef BOOST_OPERATORS_HPP +#define BOOST_OPERATORS_HPP + +// If old work-arounds are needed, refer to the preserved version without +// ADL protection. +#if defined(BOOST_NO_OPERATORS_IN_NAMESPACE) || defined(BOOST_USE_OPERATORS_V1) +#include "operators_v1.hpp" +#else + +#include +#include + +#include +#include +#include + +#if defined(__sgi) && !defined(__GNUC__) +# pragma set woff 1234 +#endif + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1600) +# pragma warning( disable : 4284 ) // complaint about return type of +#endif // operator-> not begin a UDT + +// Define BOOST_OPERATORS_CONSTEXPR to be like BOOST_CONSTEXPR but empty under MSVC < v19.22 +#if BOOST_WORKAROUND(BOOST_MSVC, < 1922) +#define BOOST_OPERATORS_CONSTEXPR +#elif defined __sun +#define BOOST_OPERATORS_CONSTEXPR +#else +#define BOOST_OPERATORS_CONSTEXPR BOOST_CONSTEXPR +#endif + +// In this section we supply the xxxx1 and xxxx2 forms of the operator +// templates, which are explicitly targeted at the 1-type-argument and +// 2-type-argument operator forms, respectively. + +namespace boost +{ +namespace operators_impl +{ +namespace operators_detail +{ + +template class empty_base {}; + +} // namespace operators_detail + +// Basic operator classes (contributed by Dave Abrahams) ------------------// + +// Note that friend functions defined in a class are implicitly inline. +// See the C++ std, 11.4 [class.friend] paragraph 5 + +template > +struct less_than_comparable2 : B +{ + friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const U& y) { return !static_cast(x > y); } + friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const U& y) { return !static_cast(x < y); } + friend BOOST_OPERATORS_CONSTEXPR bool operator>(const U& x, const T& y) { return y < x; } + friend BOOST_OPERATORS_CONSTEXPR bool operator<(const U& x, const T& y) { return y > x; } + friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const U& x, const T& y) { return !static_cast(y < x); } + friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const U& x, const T& y) { return !static_cast(y > x); } +}; + +template > +struct less_than_comparable1 : B +{ + friend BOOST_OPERATORS_CONSTEXPR bool operator>(const T& x, const T& y) { return y < x; } + friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const T& y) { return !static_cast(y < x); } + friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const T& y) { return !static_cast(x < y); } +}; + +template > +struct equality_comparable2 : B +{ + friend BOOST_OPERATORS_CONSTEXPR bool operator==(const U& y, const T& x) { return x == y; } + friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const U& y, const T& x) { return !static_cast(x == y); } + friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const T& y, const U& x) { return !static_cast(y == x); } +}; + +template > +struct equality_comparable1 : B +{ + friend BOOST_OPERATORS_CONSTEXPR bool operator!=(const T& x, const T& y) { return !static_cast(x == y); } +}; + +// A macro which produces "name_2left" from "name". +#define BOOST_OPERATOR2_LEFT(name) name##2##_##left + +// NRVO-friendly implementation (contributed by Daniel Frey) ---------------// + +#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) + +// This is the optimal implementation for ISO/ANSI C++, +// but it requires the compiler to implement the NRVO. +// If the compiler has no NRVO, this is the best symmetric +// implementation available. + +#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ +template > \ +struct NAME##2 : B \ +{ \ + friend T operator OP( const T& lhs, const U& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ + friend T operator OP( const U& lhs, const T& rhs ) \ + { T nrv( rhs ); nrv OP##= lhs; return nrv; } \ +}; \ + \ +template > \ +struct NAME##1 : B \ +{ \ + friend T operator OP( const T& lhs, const T& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ +}; + +#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ +template > \ +struct NAME##2 : B \ +{ \ + friend T operator OP( const T& lhs, const U& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ +}; \ + \ +template > \ +struct BOOST_OPERATOR2_LEFT(NAME) : B \ +{ \ + friend T operator OP( const U& lhs, const T& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ +}; \ + \ +template > \ +struct NAME##1 : B \ +{ \ + friend T operator OP( const T& lhs, const T& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ +}; + +#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) + +// For compilers without NRVO the following code is optimal, but not +// symmetric! Note that the implementation of +// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide +// optimization opportunities to the compiler :) + +#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ +template > \ +struct NAME##2 : B \ +{ \ + friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ + friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \ +}; \ + \ +template > \ +struct NAME##1 : B \ +{ \ + friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ +}; + +#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ +template > \ +struct NAME##2 : B \ +{ \ + friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ +}; \ + \ +template > \ +struct BOOST_OPERATOR2_LEFT(NAME) : B \ +{ \ + friend T operator OP( const U& lhs, const T& rhs ) \ + { return T( lhs ) OP##= rhs; } \ +}; \ + \ +template > \ +struct NAME##1 : B \ +{ \ + friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ +}; + +#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) + +BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * ) +BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + ) +BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - ) +BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / ) +BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % ) +BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ ) +BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & ) +BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | ) + +#undef BOOST_BINARY_OPERATOR_COMMUTATIVE +#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE +#undef BOOST_OPERATOR2_LEFT + +// incrementable and decrementable contributed by Jeremy Siek + +template > +struct incrementable : B +{ + friend T operator++(T& x, int) + { + incrementable_type nrv(x); + ++x; + return nrv; + } +private: // The use of this typedef works around a Borland bug + typedef T incrementable_type; +}; + +template > +struct decrementable : B +{ + friend T operator--(T& x, int) + { + decrementable_type nrv(x); + --x; + return nrv; + } +private: // The use of this typedef works around a Borland bug + typedef T decrementable_type; +}; + +// Iterator operator classes (contributed by Jeremy Siek) ------------------// + +template > +struct dereferenceable : B +{ + P operator->() const + { + return ::boost::addressof(*static_cast(*this)); + } +}; + +template > +struct indexable : B +{ + R operator[](I n) const + { + return *(static_cast(*this) + n); + } +}; + +// More operator classes (contributed by Daryle Walker) --------------------// +// (NRVO-friendly implementation contributed by Daniel Frey) ---------------// + +#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) + +#define BOOST_BINARY_OPERATOR( NAME, OP ) \ +template > \ +struct NAME##2 : B \ +{ \ + friend T operator OP( const T& lhs, const U& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ +}; \ + \ +template > \ +struct NAME##1 : B \ +{ \ + friend T operator OP( const T& lhs, const T& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ +}; + +#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) + +#define BOOST_BINARY_OPERATOR( NAME, OP ) \ +template > \ +struct NAME##2 : B \ +{ \ + friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ +}; \ + \ +template > \ +struct NAME##1 : B \ +{ \ + friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ +}; + +#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) + +BOOST_BINARY_OPERATOR( left_shiftable, << ) +BOOST_BINARY_OPERATOR( right_shiftable, >> ) + +#undef BOOST_BINARY_OPERATOR + +template > +struct equivalent2 : B +{ + friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T& x, const U& y) + { + return !static_cast(x < y) && !static_cast(x > y); + } +}; + +template > +struct equivalent1 : B +{ + friend BOOST_OPERATORS_CONSTEXPR bool operator==(const T&x, const T&y) + { + return !static_cast(x < y) && !static_cast(y < x); + } +}; + +template > +struct partially_ordered2 : B +{ + friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const U& y) + { return static_cast(x < y) || static_cast(x == y); } + friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const U& y) + { return static_cast(x > y) || static_cast(x == y); } + friend BOOST_OPERATORS_CONSTEXPR bool operator>(const U& x, const T& y) + { return y < x; } + friend BOOST_OPERATORS_CONSTEXPR bool operator<(const U& x, const T& y) + { return y > x; } + friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const U& x, const T& y) + { return static_cast(y > x) || static_cast(y == x); } + friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const U& x, const T& y) + { return static_cast(y < x) || static_cast(y == x); } +}; + +template > +struct partially_ordered1 : B +{ + friend BOOST_OPERATORS_CONSTEXPR bool operator>(const T& x, const T& y) + { return y < x; } + friend BOOST_OPERATORS_CONSTEXPR bool operator<=(const T& x, const T& y) + { return static_cast(x < y) || static_cast(x == y); } + friend BOOST_OPERATORS_CONSTEXPR bool operator>=(const T& x, const T& y) + { return static_cast(y < x) || static_cast(x == y); } +}; + +// Combined operator classes (contributed by Daryle Walker) ----------------// + +template > +struct totally_ordered2 + : less_than_comparable2 > {}; + +template > +struct totally_ordered1 + : less_than_comparable1 > {}; + +template > +struct additive2 + : addable2 > {}; + +template > +struct additive1 + : addable1 > {}; + +template > +struct multiplicative2 + : multipliable2 > {}; + +template > +struct multiplicative1 + : multipliable1 > {}; + +template > +struct integer_multiplicative2 + : multiplicative2 > {}; + +template > +struct integer_multiplicative1 + : multiplicative1 > {}; + +template > +struct arithmetic2 + : additive2 > {}; + +template > +struct arithmetic1 + : additive1 > {}; + +template > +struct integer_arithmetic2 + : additive2 > {}; + +template > +struct integer_arithmetic1 + : additive1 > {}; + +template > +struct bitwise2 + : xorable2 > > {}; + +template > +struct bitwise1 + : xorable1 > > {}; + +template > +struct unit_steppable + : incrementable > {}; + +template > +struct shiftable2 + : left_shiftable2 > {}; + +template > +struct shiftable1 + : left_shiftable1 > {}; + +template > +struct ring_operators2 + : additive2 > > {}; + +template > +struct ring_operators1 + : additive1 > {}; + +template > +struct ordered_ring_operators2 + : ring_operators2 > {}; + +template > +struct ordered_ring_operators1 + : ring_operators1 > {}; + +template > +struct field_operators2 + : ring_operators2 > > {}; + +template > +struct field_operators1 + : ring_operators1 > {}; + +template > +struct ordered_field_operators2 + : field_operators2 > {}; + +template > +struct ordered_field_operators1 + : field_operators1 > {}; + +template > +struct euclidian_ring_operators2 + : ring_operators2 > > > > {}; + +template > +struct euclidian_ring_operators1 + : ring_operators1 > > {}; + +template > +struct ordered_euclidian_ring_operators2 + : totally_ordered2 > {}; + +template > +struct ordered_euclidian_ring_operators1 + : totally_ordered1 > {}; + +template > +struct euclidean_ring_operators2 + : ring_operators2 > > > > {}; + +template > +struct euclidean_ring_operators1 + : ring_operators1 > > {}; + +template > +struct ordered_euclidean_ring_operators2 + : totally_ordered2 > {}; + +template > +struct ordered_euclidean_ring_operators1 + : totally_ordered1 > {}; + +template > +struct input_iteratable + : equality_comparable1 > > {}; + +template > +struct output_iteratable + : incrementable {}; + +template > +struct forward_iteratable + : input_iteratable {}; + +template > +struct bidirectional_iteratable + : forward_iteratable > {}; + +// To avoid repeated derivation from equality_comparable, +// which is an indirect base class of bidirectional_iterable, +// random_access_iteratable must not be derived from totally_ordered1 +// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001) +template > +struct random_access_iteratable + : bidirectional_iteratable > > > {}; + + +// +// Here's where we put it all together, defining the xxxx forms of the templates. +// We also define specializations of is_chained_base<> for +// the xxxx, xxxx1, and xxxx2 templates. +// + +namespace operators_detail +{ + +// A type parameter is used instead of a plain bool because Borland's compiler +// didn't cope well with the more obvious non-type template parameter. +struct true_t {}; +struct false_t {}; + +} // namespace operators_detail + +// is_chained_base<> - a traits class used to distinguish whether an operator +// template argument is being used for base class chaining, or is specifying a +// 2nd argument type. + +// Unspecialized version assumes that most types are not being used for base +// class chaining. We specialize for the operator templates defined in this +// library. +template struct is_chained_base { + typedef operators_detail::false_t value; +}; + +// Provide a specialization of 'is_chained_base<>' +// for a 4-type-argument operator template. +# define BOOST_OPERATOR_TEMPLATE4(template_name4) \ + template \ + struct is_chained_base< template_name4 > { \ + typedef operators_detail::true_t value; \ + }; + +// Provide a specialization of 'is_chained_base<>' +// for a 3-type-argument operator template. +# define BOOST_OPERATOR_TEMPLATE3(template_name3) \ + template \ + struct is_chained_base< template_name3 > { \ + typedef operators_detail::true_t value; \ + }; + +// Provide a specialization of 'is_chained_base<>' +// for a 2-type-argument operator template. +# define BOOST_OPERATOR_TEMPLATE2(template_name2) \ + template \ + struct is_chained_base< template_name2 > { \ + typedef operators_detail::true_t value; \ + }; + +// Provide a specialization of 'is_chained_base<>' +// for a 1-type-argument operator template. +# define BOOST_OPERATOR_TEMPLATE1(template_name1) \ + template \ + struct is_chained_base< template_name1 > { \ + typedef operators_detail::true_t value; \ + }; + +// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it +// can be used for specifying both 1-argument and 2-argument forms. Requires the +// existence of two previously defined class templates named '1' +// and '2' which must implement the corresponding 1- and 2- +// argument forms. +// +// The template type parameter O == is_chained_base::value is used to +// distinguish whether the 2nd argument to is being used for +// base class chaining from another boost operator template or is describing a +// 2nd operand type. O == true_t only when U is actually an another operator +// template from the library. Partial specialization is used to select an +// implementation in terms of either '1' or '2'. +// + +# define BOOST_OPERATOR_TEMPLATE(template_name) \ +template \ + ,class O = typename is_chained_base::value \ + > \ +struct template_name; \ + \ +template \ +struct template_name \ + : template_name##2 {}; \ + \ +template \ +struct template_name, operators_detail::true_t> \ + : template_name##1 {}; \ + \ +template \ +struct template_name \ + : template_name##1 {}; \ + \ +template \ +struct is_chained_base< template_name > { \ + typedef operators_detail::true_t value; \ +}; \ + \ +BOOST_OPERATOR_TEMPLATE2(template_name##2) \ +BOOST_OPERATOR_TEMPLATE1(template_name##1) + +BOOST_OPERATOR_TEMPLATE(less_than_comparable) +BOOST_OPERATOR_TEMPLATE(equality_comparable) +BOOST_OPERATOR_TEMPLATE(multipliable) +BOOST_OPERATOR_TEMPLATE(addable) +BOOST_OPERATOR_TEMPLATE(subtractable) +BOOST_OPERATOR_TEMPLATE2(subtractable2_left) +BOOST_OPERATOR_TEMPLATE(dividable) +BOOST_OPERATOR_TEMPLATE2(dividable2_left) +BOOST_OPERATOR_TEMPLATE(modable) +BOOST_OPERATOR_TEMPLATE2(modable2_left) +BOOST_OPERATOR_TEMPLATE(xorable) +BOOST_OPERATOR_TEMPLATE(andable) +BOOST_OPERATOR_TEMPLATE(orable) + +BOOST_OPERATOR_TEMPLATE1(incrementable) +BOOST_OPERATOR_TEMPLATE1(decrementable) + +BOOST_OPERATOR_TEMPLATE2(dereferenceable) +BOOST_OPERATOR_TEMPLATE3(indexable) + +BOOST_OPERATOR_TEMPLATE(left_shiftable) +BOOST_OPERATOR_TEMPLATE(right_shiftable) +BOOST_OPERATOR_TEMPLATE(equivalent) +BOOST_OPERATOR_TEMPLATE(partially_ordered) + +BOOST_OPERATOR_TEMPLATE(totally_ordered) +BOOST_OPERATOR_TEMPLATE(additive) +BOOST_OPERATOR_TEMPLATE(multiplicative) +BOOST_OPERATOR_TEMPLATE(integer_multiplicative) +BOOST_OPERATOR_TEMPLATE(arithmetic) +BOOST_OPERATOR_TEMPLATE(integer_arithmetic) +BOOST_OPERATOR_TEMPLATE(bitwise) +BOOST_OPERATOR_TEMPLATE1(unit_steppable) +BOOST_OPERATOR_TEMPLATE(shiftable) +BOOST_OPERATOR_TEMPLATE(ring_operators) +BOOST_OPERATOR_TEMPLATE(ordered_ring_operators) +BOOST_OPERATOR_TEMPLATE(field_operators) +BOOST_OPERATOR_TEMPLATE(ordered_field_operators) +BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators) +BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators) +BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators) +BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators) +BOOST_OPERATOR_TEMPLATE2(input_iteratable) +BOOST_OPERATOR_TEMPLATE1(output_iteratable) +BOOST_OPERATOR_TEMPLATE2(forward_iteratable) +BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable) +BOOST_OPERATOR_TEMPLATE4(random_access_iteratable) + +#undef BOOST_OPERATOR_TEMPLATE +#undef BOOST_OPERATOR_TEMPLATE4 +#undef BOOST_OPERATOR_TEMPLATE3 +#undef BOOST_OPERATOR_TEMPLATE2 +#undef BOOST_OPERATOR_TEMPLATE1 + +template +struct operators2 + : totally_ordered2 > > {}; + +template +struct operators : operators2 {}; + +template struct operators + : totally_ordered > > > {}; + +// Iterator helper classes (contributed by Jeremy Siek) -------------------// +// (Input and output iterator helpers contributed by Daryle Walker) -------// +// (Changed to use combined operator classes by Daryle Walker) ------------// +// (Adapted to C++17 by Daniel Frey) --------------------------------------// +template +struct iterator_helper +{ + typedef Category iterator_category; + typedef T value_type; + typedef Distance difference_type; + typedef Pointer pointer; + typedef Reference reference; +}; + +template +struct input_iterator_helper + : input_iteratable > {}; + +template +struct output_iterator_helper + : output_iteratable > +{ + T& operator*() { return static_cast(*this); } + T& operator++() { return static_cast(*this); } +}; + +template +struct forward_iterator_helper + : forward_iteratable > {}; + +template +struct bidirectional_iterator_helper + : bidirectional_iteratable > {}; + +template +struct random_access_iterator_helper + : random_access_iteratable > +{ + friend D requires_difference_operator(const T& x, const T& y) { + return x - y; + } +}; // random_access_iterator_helper + +} // namespace operators_impl +using namespace operators_impl; + +} // namespace boost + +#if defined(__sgi) && !defined(__GNUC__) +#pragma reset woff 1234 +#endif + +#endif // BOOST_NO_OPERATORS_IN_NAMESPACE +#endif // BOOST_OPERATORS_HPP diff --git a/libs/utility/include/boost/operators_v1.hpp b/libs/utility/include/boost/operators_v1.hpp new file mode 100644 index 00000000..e1c53e87 --- /dev/null +++ b/libs/utility/include/boost/operators_v1.hpp @@ -0,0 +1,951 @@ +// Boost operators.hpp header file ----------------------------------------// + +// (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001. +// 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) + +// See http://www.boost.org/libs/utility/operators.htm for documentation. + +// Revision History +// 22 Feb 16 Preserve old work-arounds. (Daniel Frey) +// 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++ +// (Matthew Bradbury, fixes #4432) +// 07 Aug 08 Added "euclidean" spelling. (Daniel Frey) +// 03 Apr 08 Make sure "convertible to bool" is sufficient +// for T::operator<, etc. (Daniel Frey) +// 24 May 07 Changed empty_base to depend on T, see +// http://svn.boost.org/trac/boost/ticket/979 +// 21 Oct 02 Modified implementation of operators to allow compilers with a +// correct named return value optimization (NRVO) to produce optimal +// code. (Daniel Frey) +// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel) +// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker) +// 27 Aug 01 'left' form for non commutative operators added; +// additional classes for groups of related operators added; +// workaround for empty base class optimization +// bug of GCC 3.0 (Helmut Zeisel) +// 25 Jun 01 output_iterator_helper changes: removed default template +// parameters, added support for self-proxying, additional +// documentation and tests (Aleksey Gurtovoy) +// 29 May 01 Added operator classes for << and >>. Added input and output +// iterator helper classes. Added classes to connect equality and +// relational operators. Added classes for groups of related +// operators. Reimplemented example operator and iterator helper +// classes in terms of the new groups. (Daryle Walker, with help +// from Alexy Gurtovoy) +// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly +// supplied arguments from actually being used (Dave Abrahams) +// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and +// refactoring of compiler workarounds, additional documentation +// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from +// Dave Abrahams) +// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and +// Jeremy Siek (Dave Abrahams) +// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5 +// (Mark Rodgers) +// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy) +// 10 Jun 00 Support for the base class chaining technique was added +// (Aleksey Gurtovoy). See documentation and the comments below +// for the details. +// 12 Dec 99 Initial version with iterator operators (Jeremy Siek) +// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary +// specializations of dividable, subtractable, modable (Ed Brey) +// 17 Nov 99 Add comments (Beman Dawes) +// Remove unnecessary specialization of operators<> (Ed Brey) +// 15 Nov 99 Fix less_than_comparable second operand type for first two +// operators.(Beman Dawes) +// 12 Nov 99 Add operators templates (Ed Brey) +// 11 Nov 99 Add single template parameter version for compilers without +// partial specialization (Beman Dawes) +// 10 Nov 99 Initial version + +// 10 Jun 00: +// An additional optional template parameter was added to most of +// operator templates to support the base class chaining technique (see +// documentation for the details). Unfortunately, a straightforward +// implementation of this change would have broken compatibility with the +// previous version of the library by making it impossible to use the same +// template name (e.g. 'addable') for both the 1- and 2-argument versions of +// an operator template. This implementation solves the backward-compatibility +// issue at the cost of some simplicity. +// +// One of the complications is an existence of special auxiliary class template +// 'is_chained_base<>' (see 'detail' namespace below), which is used +// to determine whether its template parameter is a library's operator template +// or not. You have to specialize 'is_chained_base<>' for each new +// operator template you add to the library. +// +// However, most of the non-trivial implementation details are hidden behind +// several local macros defined below, and as soon as you understand them, +// you understand the whole library implementation. + +#ifndef BOOST_OPERATORS_V1_HPP +#define BOOST_OPERATORS_V1_HPP + +#include +#include + +#include +#include + +#if defined(__sgi) && !defined(__GNUC__) +# pragma set woff 1234 +#endif + +#if BOOST_WORKAROUND(BOOST_MSVC, < 1600) +# pragma warning( disable : 4284 ) // complaint about return type of +#endif // operator-> not begin a UDT + +namespace boost { +namespace detail { + +template class empty_base {}; + +} // namespace detail +} // namespace boost + +// In this section we supply the xxxx1 and xxxx2 forms of the operator +// templates, which are explicitly targeted at the 1-type-argument and +// 2-type-argument operator forms, respectively. Some compilers get confused +// when inline friend functions are overloaded in namespaces other than the +// global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of +// these templates must go in the global namespace. + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE +namespace boost +{ +#endif + +// Basic operator classes (contributed by Dave Abrahams) ------------------// + +// Note that friend functions defined in a class are implicitly inline. +// See the C++ std, 11.4 [class.friend] paragraph 5 + +template > +struct less_than_comparable2 : B +{ + friend bool operator<=(const T& x, const U& y) { return !static_cast(x > y); } + friend bool operator>=(const T& x, const U& y) { return !static_cast(x < y); } + friend bool operator>(const U& x, const T& y) { return y < x; } + friend bool operator<(const U& x, const T& y) { return y > x; } + friend bool operator<=(const U& x, const T& y) { return !static_cast(y < x); } + friend bool operator>=(const U& x, const T& y) { return !static_cast(y > x); } +}; + +template > +struct less_than_comparable1 : B +{ + friend bool operator>(const T& x, const T& y) { return y < x; } + friend bool operator<=(const T& x, const T& y) { return !static_cast(y < x); } + friend bool operator>=(const T& x, const T& y) { return !static_cast(x < y); } +}; + +template > +struct equality_comparable2 : B +{ + friend bool operator==(const U& y, const T& x) { return x == y; } + friend bool operator!=(const U& y, const T& x) { return !static_cast(x == y); } + friend bool operator!=(const T& y, const U& x) { return !static_cast(y == x); } +}; + +template > +struct equality_comparable1 : B +{ + friend bool operator!=(const T& x, const T& y) { return !static_cast(x == y); } +}; + +// A macro which produces "name_2left" from "name". +#define BOOST_OPERATOR2_LEFT(name) name##2##_##left + +// NRVO-friendly implementation (contributed by Daniel Frey) ---------------// + +#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) + +// This is the optimal implementation for ISO/ANSI C++, +// but it requires the compiler to implement the NRVO. +// If the compiler has no NRVO, this is the best symmetric +// implementation available. + +#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ +template > \ +struct NAME##2 : B \ +{ \ + friend T operator OP( const T& lhs, const U& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ + friend T operator OP( const U& lhs, const T& rhs ) \ + { T nrv( rhs ); nrv OP##= lhs; return nrv; } \ +}; \ + \ +template > \ +struct NAME##1 : B \ +{ \ + friend T operator OP( const T& lhs, const T& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ +}; + +#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ +template > \ +struct NAME##2 : B \ +{ \ + friend T operator OP( const T& lhs, const U& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ +}; \ + \ +template > \ +struct BOOST_OPERATOR2_LEFT(NAME) : B \ +{ \ + friend T operator OP( const U& lhs, const T& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ +}; \ + \ +template > \ +struct NAME##1 : B \ +{ \ + friend T operator OP( const T& lhs, const T& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ +}; + +#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) + +// For compilers without NRVO the following code is optimal, but not +// symmetric! Note that the implementation of +// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide +// optimization opportunities to the compiler :) + +#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \ +template > \ +struct NAME##2 : B \ +{ \ + friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ + friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \ +}; \ + \ +template > \ +struct NAME##1 : B \ +{ \ + friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ +}; + +#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \ +template > \ +struct NAME##2 : B \ +{ \ + friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ +}; \ + \ +template > \ +struct BOOST_OPERATOR2_LEFT(NAME) : B \ +{ \ + friend T operator OP( const U& lhs, const T& rhs ) \ + { return T( lhs ) OP##= rhs; } \ +}; \ + \ +template > \ +struct NAME##1 : B \ +{ \ + friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ +}; + +#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) + +BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * ) +BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + ) +BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - ) +BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / ) +BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % ) +BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ ) +BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & ) +BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | ) + +#undef BOOST_BINARY_OPERATOR_COMMUTATIVE +#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE +#undef BOOST_OPERATOR2_LEFT + +// incrementable and decrementable contributed by Jeremy Siek + +template > +struct incrementable : B +{ + friend T operator++(T& x, int) + { + incrementable_type nrv(x); + ++x; + return nrv; + } +private: // The use of this typedef works around a Borland bug + typedef T incrementable_type; +}; + +template > +struct decrementable : B +{ + friend T operator--(T& x, int) + { + decrementable_type nrv(x); + --x; + return nrv; + } +private: // The use of this typedef works around a Borland bug + typedef T decrementable_type; +}; + +// Iterator operator classes (contributed by Jeremy Siek) ------------------// + +template > +struct dereferenceable : B +{ + P operator->() const + { + return &*static_cast(*this); + } +}; + +template > +struct indexable : B +{ + R operator[](I n) const + { + return *(static_cast(*this) + n); + } +}; + +// More operator classes (contributed by Daryle Walker) --------------------// +// (NRVO-friendly implementation contributed by Daniel Frey) ---------------// + +#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) + +#define BOOST_BINARY_OPERATOR( NAME, OP ) \ +template > \ +struct NAME##2 : B \ +{ \ + friend T operator OP( const T& lhs, const U& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ +}; \ + \ +template > \ +struct NAME##1 : B \ +{ \ + friend T operator OP( const T& lhs, const T& rhs ) \ + { T nrv( lhs ); nrv OP##= rhs; return nrv; } \ +}; + +#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) + +#define BOOST_BINARY_OPERATOR( NAME, OP ) \ +template > \ +struct NAME##2 : B \ +{ \ + friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \ +}; \ + \ +template > \ +struct NAME##1 : B \ +{ \ + friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \ +}; + +#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS) + +BOOST_BINARY_OPERATOR( left_shiftable, << ) +BOOST_BINARY_OPERATOR( right_shiftable, >> ) + +#undef BOOST_BINARY_OPERATOR + +template > +struct equivalent2 : B +{ + friend bool operator==(const T& x, const U& y) + { + return !static_cast(x < y) && !static_cast(x > y); + } +}; + +template > +struct equivalent1 : B +{ + friend bool operator==(const T&x, const T&y) + { + return !static_cast(x < y) && !static_cast(y < x); + } +}; + +template > +struct partially_ordered2 : B +{ + friend bool operator<=(const T& x, const U& y) + { return static_cast(x < y) || static_cast(x == y); } + friend bool operator>=(const T& x, const U& y) + { return static_cast(x > y) || static_cast(x == y); } + friend bool operator>(const U& x, const T& y) + { return y < x; } + friend bool operator<(const U& x, const T& y) + { return y > x; } + friend bool operator<=(const U& x, const T& y) + { return static_cast(y > x) || static_cast(y == x); } + friend bool operator>=(const U& x, const T& y) + { return static_cast(y < x) || static_cast(y == x); } +}; + +template > +struct partially_ordered1 : B +{ + friend bool operator>(const T& x, const T& y) + { return y < x; } + friend bool operator<=(const T& x, const T& y) + { return static_cast(x < y) || static_cast(x == y); } + friend bool operator>=(const T& x, const T& y) + { return static_cast(y < x) || static_cast(x == y); } +}; + +// Combined operator classes (contributed by Daryle Walker) ----------------// + +template > +struct totally_ordered2 + : less_than_comparable2 > {}; + +template > +struct totally_ordered1 + : less_than_comparable1 > {}; + +template > +struct additive2 + : addable2 > {}; + +template > +struct additive1 + : addable1 > {}; + +template > +struct multiplicative2 + : multipliable2 > {}; + +template > +struct multiplicative1 + : multipliable1 > {}; + +template > +struct integer_multiplicative2 + : multiplicative2 > {}; + +template > +struct integer_multiplicative1 + : multiplicative1 > {}; + +template > +struct arithmetic2 + : additive2 > {}; + +template > +struct arithmetic1 + : additive1 > {}; + +template > +struct integer_arithmetic2 + : additive2 > {}; + +template > +struct integer_arithmetic1 + : additive1 > {}; + +template > +struct bitwise2 + : xorable2 > > {}; + +template > +struct bitwise1 + : xorable1 > > {}; + +template > +struct unit_steppable + : incrementable > {}; + +template > +struct shiftable2 + : left_shiftable2 > {}; + +template > +struct shiftable1 + : left_shiftable1 > {}; + +template > +struct ring_operators2 + : additive2 > > {}; + +template > +struct ring_operators1 + : additive1 > {}; + +template > +struct ordered_ring_operators2 + : ring_operators2 > {}; + +template > +struct ordered_ring_operators1 + : ring_operators1 > {}; + +template > +struct field_operators2 + : ring_operators2 > > {}; + +template > +struct field_operators1 + : ring_operators1 > {}; + +template > +struct ordered_field_operators2 + : field_operators2 > {}; + +template > +struct ordered_field_operators1 + : field_operators1 > {}; + +template > +struct euclidian_ring_operators2 + : ring_operators2 > > > > {}; + +template > +struct euclidian_ring_operators1 + : ring_operators1 > > {}; + +template > +struct ordered_euclidian_ring_operators2 + : totally_ordered2 > {}; + +template > +struct ordered_euclidian_ring_operators1 + : totally_ordered1 > {}; + +template > +struct euclidean_ring_operators2 + : ring_operators2 > > > > {}; + +template > +struct euclidean_ring_operators1 + : ring_operators1 > > {}; + +template > +struct ordered_euclidean_ring_operators2 + : totally_ordered2 > {}; + +template > +struct ordered_euclidean_ring_operators1 + : totally_ordered1 > {}; + +template > +struct input_iteratable + : equality_comparable1 > > {}; + +template > +struct output_iteratable + : incrementable {}; + +template > +struct forward_iteratable + : input_iteratable {}; + +template > +struct bidirectional_iteratable + : forward_iteratable > {}; + +// To avoid repeated derivation from equality_comparable, +// which is an indirect base class of bidirectional_iterable, +// random_access_iteratable must not be derived from totally_ordered1 +// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001) +template > +struct random_access_iteratable + : bidirectional_iteratable > > > {}; + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE +} // namespace boost +#endif // BOOST_NO_OPERATORS_IN_NAMESPACE + + +// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 - +// +// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an +// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used +// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for +// two-argument forms. Note that these macros expect to be invoked from within +// boost. + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + + // The template is already in boost so we have nothing to do. +# define BOOST_IMPORT_TEMPLATE4(template_name) +# define BOOST_IMPORT_TEMPLATE3(template_name) +# define BOOST_IMPORT_TEMPLATE2(template_name) +# define BOOST_IMPORT_TEMPLATE1(template_name) + +#else // BOOST_NO_OPERATORS_IN_NAMESPACE + +# ifndef BOOST_NO_USING_TEMPLATE + + // Bring the names in with a using-declaration + // to avoid stressing the compiler. +# define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name; +# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name; +# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name; +# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name; + +# else + + // Otherwise, because a Borland C++ 5.5 bug prevents a using declaration + // from working, we are forced to use inheritance for that compiler. +# define BOOST_IMPORT_TEMPLATE4(template_name) \ + template > \ + struct template_name : ::template_name {}; + +# define BOOST_IMPORT_TEMPLATE3(template_name) \ + template > \ + struct template_name : ::template_name {}; + +# define BOOST_IMPORT_TEMPLATE2(template_name) \ + template > \ + struct template_name : ::template_name {}; + +# define BOOST_IMPORT_TEMPLATE1(template_name) \ + template > \ + struct template_name : ::template_name {}; + +# endif // BOOST_NO_USING_TEMPLATE + +#endif // BOOST_NO_OPERATORS_IN_NAMESPACE + +// +// Here's where we put it all together, defining the xxxx forms of the templates +// in namespace boost. We also define specializations of is_chained_base<> for +// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as +// necessary. +// + +// is_chained_base<> - a traits class used to distinguish whether an operator +// template argument is being used for base class chaining, or is specifying a +// 2nd argument type. + +namespace boost { +// A type parameter is used instead of a plain bool because Borland's compiler +// didn't cope well with the more obvious non-type template parameter. +namespace detail { + struct true_t {}; + struct false_t {}; +} // namespace detail + +// Unspecialized version assumes that most types are not being used for base +// class chaining. We specialize for the operator templates defined in this +// library. +template struct is_chained_base { + typedef ::boost::detail::false_t value; +}; + +} // namespace boost + +// Import a 4-type-argument operator template into boost (if necessary) and +// provide a specialization of 'is_chained_base<>' for it. +# define BOOST_OPERATOR_TEMPLATE4(template_name4) \ + BOOST_IMPORT_TEMPLATE4(template_name4) \ + template \ + struct is_chained_base< ::boost::template_name4 > { \ + typedef ::boost::detail::true_t value; \ + }; + +// Import a 3-type-argument operator template into boost (if necessary) and +// provide a specialization of 'is_chained_base<>' for it. +# define BOOST_OPERATOR_TEMPLATE3(template_name3) \ + BOOST_IMPORT_TEMPLATE3(template_name3) \ + template \ + struct is_chained_base< ::boost::template_name3 > { \ + typedef ::boost::detail::true_t value; \ + }; + +// Import a 2-type-argument operator template into boost (if necessary) and +// provide a specialization of 'is_chained_base<>' for it. +# define BOOST_OPERATOR_TEMPLATE2(template_name2) \ + BOOST_IMPORT_TEMPLATE2(template_name2) \ + template \ + struct is_chained_base< ::boost::template_name2 > { \ + typedef ::boost::detail::true_t value; \ + }; + +// Import a 1-type-argument operator template into boost (if necessary) and +// provide a specialization of 'is_chained_base<>' for it. +# define BOOST_OPERATOR_TEMPLATE1(template_name1) \ + BOOST_IMPORT_TEMPLATE1(template_name1) \ + template \ + struct is_chained_base< ::boost::template_name1 > { \ + typedef ::boost::detail::true_t value; \ + }; + +// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it +// can be used for specifying both 1-argument and 2-argument forms. Requires the +// existence of two previously defined class templates named '1' +// and '2' which must implement the corresponding 1- and 2- +// argument forms. +// +// The template type parameter O == is_chained_base::value is used to +// distinguish whether the 2nd argument to is being used for +// base class chaining from another boost operator template or is describing a +// 2nd operand type. O == true_t only when U is actually an another operator +// template from the library. Partial specialization is used to select an +// implementation in terms of either '1' or '2'. +// + +# define BOOST_OPERATOR_TEMPLATE(template_name) \ +template \ + ,class O = typename is_chained_base::value \ + > \ +struct template_name : template_name##2 {}; \ + \ +template \ +struct template_name \ + : template_name##1 {}; \ + \ +template \ +struct template_name \ + : template_name##1 {}; \ + \ +template \ +struct is_chained_base< ::boost::template_name > { \ + typedef ::boost::detail::true_t value; \ +}; \ + \ +BOOST_OPERATOR_TEMPLATE2(template_name##2) \ +BOOST_OPERATOR_TEMPLATE1(template_name##1) + + + +namespace boost { + +BOOST_OPERATOR_TEMPLATE(less_than_comparable) +BOOST_OPERATOR_TEMPLATE(equality_comparable) +BOOST_OPERATOR_TEMPLATE(multipliable) +BOOST_OPERATOR_TEMPLATE(addable) +BOOST_OPERATOR_TEMPLATE(subtractable) +BOOST_OPERATOR_TEMPLATE2(subtractable2_left) +BOOST_OPERATOR_TEMPLATE(dividable) +BOOST_OPERATOR_TEMPLATE2(dividable2_left) +BOOST_OPERATOR_TEMPLATE(modable) +BOOST_OPERATOR_TEMPLATE2(modable2_left) +BOOST_OPERATOR_TEMPLATE(xorable) +BOOST_OPERATOR_TEMPLATE(andable) +BOOST_OPERATOR_TEMPLATE(orable) + +BOOST_OPERATOR_TEMPLATE1(incrementable) +BOOST_OPERATOR_TEMPLATE1(decrementable) + +BOOST_OPERATOR_TEMPLATE2(dereferenceable) +BOOST_OPERATOR_TEMPLATE3(indexable) + +BOOST_OPERATOR_TEMPLATE(left_shiftable) +BOOST_OPERATOR_TEMPLATE(right_shiftable) +BOOST_OPERATOR_TEMPLATE(equivalent) +BOOST_OPERATOR_TEMPLATE(partially_ordered) + +BOOST_OPERATOR_TEMPLATE(totally_ordered) +BOOST_OPERATOR_TEMPLATE(additive) +BOOST_OPERATOR_TEMPLATE(multiplicative) +BOOST_OPERATOR_TEMPLATE(integer_multiplicative) +BOOST_OPERATOR_TEMPLATE(arithmetic) +BOOST_OPERATOR_TEMPLATE(integer_arithmetic) +BOOST_OPERATOR_TEMPLATE(bitwise) +BOOST_OPERATOR_TEMPLATE1(unit_steppable) +BOOST_OPERATOR_TEMPLATE(shiftable) +BOOST_OPERATOR_TEMPLATE(ring_operators) +BOOST_OPERATOR_TEMPLATE(ordered_ring_operators) +BOOST_OPERATOR_TEMPLATE(field_operators) +BOOST_OPERATOR_TEMPLATE(ordered_field_operators) +BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators) +BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators) +BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators) +BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators) +BOOST_OPERATOR_TEMPLATE2(input_iteratable) +BOOST_OPERATOR_TEMPLATE1(output_iteratable) +BOOST_OPERATOR_TEMPLATE2(forward_iteratable) +BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable) +BOOST_OPERATOR_TEMPLATE4(random_access_iteratable) + +#undef BOOST_OPERATOR_TEMPLATE +#undef BOOST_OPERATOR_TEMPLATE4 +#undef BOOST_OPERATOR_TEMPLATE3 +#undef BOOST_OPERATOR_TEMPLATE2 +#undef BOOST_OPERATOR_TEMPLATE1 +#undef BOOST_IMPORT_TEMPLATE1 +#undef BOOST_IMPORT_TEMPLATE2 +#undef BOOST_IMPORT_TEMPLATE3 +#undef BOOST_IMPORT_TEMPLATE4 + +// The following 'operators' classes can only be used portably if the derived class +// declares ALL of the required member operators. +template +struct operators2 + : totally_ordered2 > > {}; + +template +struct operators : operators2 {}; + +template struct operators + : totally_ordered > > > {}; + +// Iterator helper classes (contributed by Jeremy Siek) -------------------// +// (Input and output iterator helpers contributed by Daryle Walker) -------// +// (Changed to use combined operator classes by Daryle Walker) ------------// +template +struct input_iterator_helper + : input_iteratable > {}; + +template +struct output_iterator_helper + : output_iteratable > +{ + T& operator*() { return static_cast(*this); } + T& operator++() { return static_cast(*this); } +}; + +template +struct forward_iterator_helper + : forward_iteratable > {}; + +template +struct bidirectional_iterator_helper + : bidirectional_iteratable > {}; + +template +struct random_access_iterator_helper + : random_access_iteratable > +{ + friend D requires_difference_operator(const T& x, const T& y) { + return x - y; + } +}; // random_access_iterator_helper + +} // namespace boost + +#if defined(__sgi) && !defined(__GNUC__) +#pragma reset woff 1234 +#endif + +#endif // BOOST_OPERATORS_V1_HPP diff --git a/libs/utility/include/boost/utility.hpp b/libs/utility/include/boost/utility.hpp new file mode 100644 index 00000000..5ac9ecbd --- /dev/null +++ b/libs/utility/include/boost/utility.hpp @@ -0,0 +1,24 @@ +// Boost utility.hpp header file -------------------------------------------// + +// Copyright 1999-2003 Aleksey Gurtovoy. Use, modification, and distribution are +// subject to the Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or a copy at .) + +// See for the library's home page. + +#ifndef BOOST_UTILITY_HPP +#define BOOST_UTILITY_HPP + +// Use of this header is discouraged and it will be deprecated. +// Please include one or more of the headers below instead. + +#include +#include +#include + +#include +#include +#include +#include + +#endif // BOOST_UTILITY_HPP diff --git a/libs/utility/include/boost/utility/base_from_member.hpp b/libs/utility/include/boost/utility/base_from_member.hpp new file mode 100644 index 00000000..614fad7d --- /dev/null +++ b/libs/utility/include/boost/utility/base_from_member.hpp @@ -0,0 +1,173 @@ +// boost utility/base_from_member.hpp header file --------------------------// + +// Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and +// distribution are subject to the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or a copy at +// .) + +// See for the library's home page. + +#ifndef BOOST_UTILITY_BASE_FROM_MEMBER_HPP +#define BOOST_UTILITY_BASE_FROM_MEMBER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// Base-from-member arity configuration macro ------------------------------// + +// The following macro determines how many arguments will be in the largest +// constructor template of base_from_member. Constructor templates will be +// generated from one argument to this maximum. Code from other files can read +// this number if they need to always match the exact maximum base_from_member +// uses. The maximum constructor length can be changed by overriding the +// #defined constant. Make sure to apply the override, if any, for all source +// files during project compiling for consistency. + +// Contributed by Jonathan Turkanis + +#ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY +#define BOOST_BASE_FROM_MEMBER_MAX_ARITY 10 +#endif + + +// An iteration of a constructor template for base_from_member -------------// + +// A macro that should expand to: +// template < typename T1, ..., typename Tn > +// base_from_member( T1 x1, ..., Tn xn ) +// : member( x1, ..., xn ) +// {} +// This macro should only persist within this file. + +#ifndef BOOST_UTILITY_DOCS +#define BOOST_PRIVATE_CTR_DEF( z, n, data ) \ + template < BOOST_PP_ENUM_PARAMS(n, typename T) > \ + base_from_member( BOOST_PP_ENUM_BINARY_PARAMS(n, T, x) ) \ + : member( BOOST_PP_ENUM_PARAMS(n, x) ) \ + {} \ + /**/ +#endif // BOOST_UTILITY_DOCS + +namespace boost +{ + +namespace detail +{ + +// Type-unmarking class template -------------------------------------------// + +// Type-trait to get the raw type, i.e. the type without top-level reference nor +// cv-qualification, from a type expression. Mainly for function arguments, any +// reference part is stripped first. + +// Contributed by Daryle Walker + +template < typename T > +struct remove_cv_ref +{ + typedef typename ::boost::remove_cv::type>::type type; + +}; // boost::detail::remove_cv_ref + +// Unmarked-type comparison class template ---------------------------------// + +// Type-trait to check if two type expressions have the same raw type. + +// Contributed by Daryle Walker, based on a work-around by Luc Danton + +template < typename T, typename U > +struct is_related + : public ::boost::is_same< + typename ::boost::detail::remove_cv_ref::type, + typename ::boost::detail::remove_cv_ref::type > +{}; + +// Enable-if-on-unidentical-unmarked-type class template -------------------// + +// Enable-if on the first two type expressions NOT having the same raw type. + +// Contributed by Daryle Walker, based on a work-around by Luc Danton + +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES +template +struct enable_if_unrelated + : public ::boost::enable_if_c +{}; + +template +struct enable_if_unrelated + : public ::boost::disable_if< ::boost::detail::is_related > +{}; +#endif + +} // namespace boost::detail + + +// Base-from-member class template -----------------------------------------// + +// Helper to initialize a base object so a derived class can use this +// object in the initialization of another base class. Used by +// Dietmar Kuehl from ideas by Ron Klatcho to solve the problem of a +// base class needing to be initialized by a member. + +// Contributed by Daryle Walker + +template < typename MemberType, int UniqueID = 0 > +class base_from_member +{ +protected: + MemberType member; + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ + !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && \ + !(defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 4)) + template ::type> + explicit BOOST_CONSTEXPR base_from_member( T&& ...x ) + BOOST_NOEXCEPT_IF( BOOST_NOEXCEPT_EXPR(::new ((void*) 0) MemberType( + static_cast(x)... )) ) // no std::is_nothrow_constructible... + : member( static_cast(x)... ) // ...nor std::forward needed + {} +#else + base_from_member() + : member() + {} + + template < typename T0 > explicit base_from_member( T0 x0 ) : member( x0 ) {} + BOOST_PP_REPEAT_FROM_TO( 2, BOOST_PP_INC(BOOST_BASE_FROM_MEMBER_MAX_ARITY), + BOOST_PRIVATE_CTR_DEF, _ ) +#endif + +}; // boost::base_from_member + +template < typename MemberType, int UniqueID > +class base_from_member +{ +protected: + MemberType& member; + + explicit BOOST_CONSTEXPR base_from_member( MemberType& x ) + BOOST_NOEXCEPT + : member( x ) + {} + +}; // boost::base_from_member + +} // namespace boost + + +// Undo any private macros +#undef BOOST_PRIVATE_CTR_DEF + + +#endif // BOOST_UTILITY_BASE_FROM_MEMBER_HPP diff --git a/libs/utility/include/boost/utility/binary.hpp b/libs/utility/include/boost/utility/binary.hpp new file mode 100644 index 00000000..2c3189a6 --- /dev/null +++ b/libs/utility/include/boost/utility/binary.hpp @@ -0,0 +1,709 @@ +/*============================================================================= + Copyright (c) 2005 Matthew Calabrese + + Use, modification and distribution is subject to 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) +==============================================================================*/ + +#ifndef BOOST_UTILITY_BINARY_HPP +#define BOOST_UTILITY_BINARY_HPP + +/*============================================================================= + + Binary Literal Utility + ______________________ + + + The following code works by converting the input bit pattern into a + Boost.Preprocessor sequence, then converting groupings of 3 bits each into + the corresponding octal digit, and finally concatenating all of the digits + together along with a leading zero. This yields a standard octal literal + with the desired value as specified in bits. + +==============================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BOOST_BINARY( bit_groupings ) \ + BOOST_BINARY_LITERAL_D( BOOST_PP_DEDUCE_D(), bit_groupings ) + +#define BOOST_BINARY_U( bit_groupings ) \ + BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, U ) + +#define BOOST_BINARY_L( bit_groupings ) \ + BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, L ) + +#define BOOST_BINARY_UL( bit_groupings ) \ + BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, UL ) + +#define BOOST_BINARY_LU( bit_groupings ) \ + BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, LU ) + +#define BOOST_BINARY_LL( bit_groupings ) \ + BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, LL ) + +#define BOOST_BINARY_ULL( bit_groupings ) \ + BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, ULL ) + +#define BOOST_BINARY_LLU( bit_groupings ) \ + BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, LLU ) + +#define BOOST_SUFFIXED_BINARY_LITERAL( bit_groupings, suffix ) \ + BOOST_SUFFIXED_BINARY_LITERAL_D( BOOST_PP_DEDUCE_D(), bit_groupings, suffix ) + +#define BOOST_SUFFIXED_BINARY_LITERAL_D( d, bit_groupings, suffix ) \ + BOOST_PP_CAT( BOOST_BINARY_LITERAL_D( d, bit_groupings ), suffix ) + +#define BOOST_BINARY_LITERAL_D( d, bit_groupings ) \ + BOOST_PP_SEQ_CAT \ + ( (0) BOOST_DETAIL_CREATE_BINARY_LITERAL_OCTAL_SEQUENCE( d, bit_groupings ) \ + ) + +#ifndef BOOST_UTILITY_DOCS +#define BOOST_DETAIL_CREATE_BINARY_LITERAL_OCTAL_SEQUENCE( d, bit_groupings ) \ + BOOST_PP_SEQ_TRANSFORM \ + ( BOOST_DETAIL_TRIPLE_TO_OCTAL_OPERATION \ + , BOOST_PP_NIL \ + , BOOST_PP_IDENTITY( BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_TRIPLE_SEQUENCE )()\ + ( BOOST_DETAIL_COMPLETE_TRIPLE_SEQUENCE \ + ( \ + d \ + , BOOST_DETAIL_CREATE_BINARY_LITERAL_BIT_SEQUENCE( d, bit_groupings ) \ + ) \ + ) \ + ) + +#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_TRIPLE_SEQUENCE( bit_sequence ) \ + BOOST_PP_CAT \ + ( BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_1 bit_sequence \ + , END_BIT \ + ) + +#define BOOST_DETAIL_BITS_PER_OCTIT 3 + +#define BOOST_DETAIL_COMPLETE_TRIPLE_SEQUENCE( d, incomplete_nibble_sequence ) \ + BOOST_PP_CAT \ + ( BOOST_DETAIL_CREATE_TRIPLE_COMPLETION_SEQUENCE_ \ + , BOOST_PP_MOD_D( d \ + , BOOST_PP_SEQ_SIZE( incomplete_nibble_sequence ) \ + , BOOST_DETAIL_BITS_PER_OCTIT \ + ) \ + ) \ + incomplete_nibble_sequence + +#define BOOST_DETAIL_FIXED_COMPL( bit ) \ + BOOST_PP_CAT( BOOST_DETAIL_FIXED_COMPL_, bit ) + +#define BOOST_DETAIL_FIXED_COMPL_0 1 + +#define BOOST_DETAIL_FIXED_COMPL_1 0 + +#define BOOST_DETAIL_CREATE_BINARY_LITERAL_BIT_SEQUENCE( d, bit_groupings ) \ + BOOST_PP_EMPTY \ + BOOST_PP_CAT( BOOST_PP_WHILE_, d ) \ + ( BOOST_DETAIL_BINARY_LITERAL_PREDICATE \ + , BOOST_DETAIL_BINARY_LITERAL_OPERATION \ + , bit_groupings () \ + ) + +#define BOOST_DETAIL_BINARY_LITERAL_PREDICATE( d, state ) \ + BOOST_DETAIL_FIXED_COMPL( BOOST_DETAIL_IS_NULLARY_ARGS( state ) ) + +#define BOOST_DETAIL_BINARY_LITERAL_OPERATION( d, state ) \ + BOOST_DETAIL_SPLIT_AND_SWAP \ + ( BOOST_PP_CAT( BOOST_DETAIL_BINARY_LITERAL_ELEMENT_, state ) ) + +#define BOOST_DETAIL_TRIPLE_TO_OCTAL_OPERATION( s, dummy_param, tuple ) \ + BOOST_DETAIL_TERNARY_TRIPLE_TO_OCTAL tuple + +#define BOOST_DETAIL_TERNARY_TRIPLE_TO_OCTAL( bit2, bit1, bit0 ) \ + BOOST_DETAIL_TRIPLE_TO_OCTAL_ ## bit2 ## bit1 ## bit0 + +#define BOOST_DETAIL_CREATE_TRIPLE_COMPLETION_SEQUENCE_1 (0)(0) +#define BOOST_DETAIL_CREATE_TRIPLE_COMPLETION_SEQUENCE_2 (0) +#define BOOST_DETAIL_CREATE_TRIPLE_COMPLETION_SEQUENCE_0 + +#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_1END_BIT + +#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_1( bit ) \ + ( ( bit, BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_2 + +#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_2( bit ) \ + bit, BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_3 + +#define BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_3( bit ) \ + bit ) ) BOOST_DETAIL_CONVERT_BIT_SEQUENCE_TO_PARENTHETIC_TUPLE_1 + +#define BOOST_DETAIL_SPLIT_AND_SWAP( params ) \ + BOOST_PP_IDENTITY( BOOST_DETAIL_SPLIT_AND_SWAP_PARAMS )()( params ) + +#define BOOST_DETAIL_SPLIT_AND_SWAP_PARAMS( first_param, second_param ) \ + second_param first_param + +#define BOOST_DETAIL_LEFT_OF_COMMA( params ) \ + BOOST_PP_IDENTITY( BOOST_DETAIL_FIRST_MACRO_PARAM )()( params ) + +#define BOOST_DETAIL_FIRST_MACRO_PARAM( first_param, second_param ) \ + first_param + +/* Begin derived concepts from Chaos by Paul Mensonides */ + +#define BOOST_DETAIL_IS_NULLARY_ARGS( param ) \ + BOOST_DETAIL_LEFT_OF_COMMA \ + ( BOOST_PP_CAT( BOOST_DETAIL_IS_NULLARY_ARGS_R_ \ + , BOOST_DETAIL_IS_NULLARY_ARGS_C param \ + ) \ + ) + +#define BOOST_DETAIL_IS_NULLARY_ARGS_C() \ + 1 + +#define BOOST_DETAIL_IS_NULLARY_ARGS_R_1 \ + 1, BOOST_PP_NIL + +#define BOOST_DETAIL_IS_NULLARY_ARGS_R_BOOST_DETAIL_IS_NULLARY_ARGS_C \ + 0, BOOST_PP_NIL + +/* End derived concepts from Chaos by Paul Mensonides */ + +#define BOOST_DETAIL_TRIPLE_TO_OCTAL_000 0 +#define BOOST_DETAIL_TRIPLE_TO_OCTAL_001 1 +#define BOOST_DETAIL_TRIPLE_TO_OCTAL_010 2 +#define BOOST_DETAIL_TRIPLE_TO_OCTAL_011 3 +#define BOOST_DETAIL_TRIPLE_TO_OCTAL_100 4 +#define BOOST_DETAIL_TRIPLE_TO_OCTAL_101 5 +#define BOOST_DETAIL_TRIPLE_TO_OCTAL_110 6 +#define BOOST_DETAIL_TRIPLE_TO_OCTAL_111 7 + +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0 (0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1 (1), + +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00 (0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01 (0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10 (1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11 (1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00 (0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01 (0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10 (1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11 (1)(1), + +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000 (0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001 (0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010 (0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011 (0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100 (1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101 (1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110 (1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111 (1)(1)(1), + +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000 (0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001 (0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010 (0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011 (0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100 (0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101 (0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110 (0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111 (0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000 (1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001 (1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010 (1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011 (1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100 (1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101 (1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110 (1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111 (1)(1)(1)(1), + +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000 (0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001 (0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010 (0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011 (0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100 (0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101 (0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110 (0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111 (0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000 (0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001 (0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010 (0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011 (0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100 (0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101 (0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110 (0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111 (0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000 (1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001 (1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010 (1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011 (1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100 (1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101 (1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110 (1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111 (1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000 (1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001 (1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010 (1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011 (1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100 (1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101 (1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110 (1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111 (1)(1)(1)(1)(1), + +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000000 (0)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000001 (0)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000010 (0)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000011 (0)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000100 (0)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000101 (0)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000110 (0)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_000111 (0)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001000 (0)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001001 (0)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001010 (0)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001011 (0)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001100 (0)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001101 (0)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001110 (0)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_001111 (0)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010000 (0)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010001 (0)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010010 (0)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010011 (0)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010100 (0)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010101 (0)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010110 (0)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_010111 (0)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011000 (0)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011001 (0)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011010 (0)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011011 (0)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011100 (0)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011101 (0)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011110 (0)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_011111 (0)(1)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100000 (1)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100001 (1)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100010 (1)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100011 (1)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100100 (1)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100101 (1)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100110 (1)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_100111 (1)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101000 (1)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101001 (1)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101010 (1)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101011 (1)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101100 (1)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101101 (1)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101110 (1)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_101111 (1)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110000 (1)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110001 (1)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110010 (1)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110011 (1)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110100 (1)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110101 (1)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110110 (1)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_110111 (1)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111000 (1)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111001 (1)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111010 (1)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111011 (1)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111100 (1)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111101 (1)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111110 (1)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_111111 (1)(1)(1)(1)(1)(1), + +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000000 (0)(0)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000001 (0)(0)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000010 (0)(0)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000011 (0)(0)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000100 (0)(0)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000101 (0)(0)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000110 (0)(0)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0000111 (0)(0)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001000 (0)(0)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001001 (0)(0)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001010 (0)(0)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001011 (0)(0)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001100 (0)(0)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001101 (0)(0)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001110 (0)(0)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0001111 (0)(0)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010000 (0)(0)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010001 (0)(0)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010010 (0)(0)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010011 (0)(0)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010100 (0)(0)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010101 (0)(0)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010110 (0)(0)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0010111 (0)(0)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011000 (0)(0)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011001 (0)(0)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011010 (0)(0)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011011 (0)(0)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011100 (0)(0)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011101 (0)(0)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011110 (0)(0)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0011111 (0)(0)(1)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100000 (0)(1)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100001 (0)(1)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100010 (0)(1)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100011 (0)(1)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100100 (0)(1)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100101 (0)(1)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100110 (0)(1)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0100111 (0)(1)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101000 (0)(1)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101001 (0)(1)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101010 (0)(1)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101011 (0)(1)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101100 (0)(1)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101101 (0)(1)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101110 (0)(1)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0101111 (0)(1)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110000 (0)(1)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110001 (0)(1)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110010 (0)(1)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110011 (0)(1)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110100 (0)(1)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110101 (0)(1)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110110 (0)(1)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0110111 (0)(1)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111000 (0)(1)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111001 (0)(1)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111010 (0)(1)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111011 (0)(1)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111100 (0)(1)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111101 (0)(1)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111110 (0)(1)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_0111111 (0)(1)(1)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000000 (1)(0)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000001 (1)(0)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000010 (1)(0)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000011 (1)(0)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000100 (1)(0)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000101 (1)(0)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000110 (1)(0)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1000111 (1)(0)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001000 (1)(0)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001001 (1)(0)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001010 (1)(0)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001011 (1)(0)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001100 (1)(0)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001101 (1)(0)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001110 (1)(0)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1001111 (1)(0)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010000 (1)(0)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010001 (1)(0)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010010 (1)(0)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010011 (1)(0)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010100 (1)(0)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010101 (1)(0)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010110 (1)(0)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1010111 (1)(0)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011000 (1)(0)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011001 (1)(0)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011010 (1)(0)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011011 (1)(0)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011100 (1)(0)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011101 (1)(0)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011110 (1)(0)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1011111 (1)(0)(1)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100000 (1)(1)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100001 (1)(1)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100010 (1)(1)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100011 (1)(1)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100100 (1)(1)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100101 (1)(1)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100110 (1)(1)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1100111 (1)(1)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101000 (1)(1)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101001 (1)(1)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101010 (1)(1)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101011 (1)(1)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101100 (1)(1)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101101 (1)(1)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101110 (1)(1)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1101111 (1)(1)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110000 (1)(1)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110001 (1)(1)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110010 (1)(1)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110011 (1)(1)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110100 (1)(1)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110101 (1)(1)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110110 (1)(1)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1110111 (1)(1)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111000 (1)(1)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111001 (1)(1)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111010 (1)(1)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111011 (1)(1)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111100 (1)(1)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111101 (1)(1)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111110 (1)(1)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_1111111 (1)(1)(1)(1)(1)(1)(1), + +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000000 (0)(0)(0)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000001 (0)(0)(0)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000010 (0)(0)(0)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000011 (0)(0)(0)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000100 (0)(0)(0)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000101 (0)(0)(0)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000110 (0)(0)(0)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00000111 (0)(0)(0)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001000 (0)(0)(0)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001001 (0)(0)(0)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001010 (0)(0)(0)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001011 (0)(0)(0)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001100 (0)(0)(0)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001101 (0)(0)(0)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001110 (0)(0)(0)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00001111 (0)(0)(0)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010000 (0)(0)(0)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010001 (0)(0)(0)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010010 (0)(0)(0)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010011 (0)(0)(0)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010100 (0)(0)(0)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010101 (0)(0)(0)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010110 (0)(0)(0)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00010111 (0)(0)(0)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011000 (0)(0)(0)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011001 (0)(0)(0)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011010 (0)(0)(0)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011011 (0)(0)(0)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011100 (0)(0)(0)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011101 (0)(0)(0)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011110 (0)(0)(0)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00011111 (0)(0)(0)(1)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100000 (0)(0)(1)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100001 (0)(0)(1)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100010 (0)(0)(1)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100011 (0)(0)(1)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100100 (0)(0)(1)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100101 (0)(0)(1)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100110 (0)(0)(1)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00100111 (0)(0)(1)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101000 (0)(0)(1)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101001 (0)(0)(1)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101010 (0)(0)(1)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101011 (0)(0)(1)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101100 (0)(0)(1)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101101 (0)(0)(1)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101110 (0)(0)(1)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00101111 (0)(0)(1)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110000 (0)(0)(1)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110001 (0)(0)(1)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110010 (0)(0)(1)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110011 (0)(0)(1)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110100 (0)(0)(1)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110101 (0)(0)(1)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110110 (0)(0)(1)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00110111 (0)(0)(1)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111000 (0)(0)(1)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111001 (0)(0)(1)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111010 (0)(0)(1)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111011 (0)(0)(1)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111100 (0)(0)(1)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111101 (0)(0)(1)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111110 (0)(0)(1)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_00111111 (0)(0)(1)(1)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000000 (0)(1)(0)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000001 (0)(1)(0)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000010 (0)(1)(0)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000011 (0)(1)(0)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000100 (0)(1)(0)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000101 (0)(1)(0)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000110 (0)(1)(0)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01000111 (0)(1)(0)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001000 (0)(1)(0)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001001 (0)(1)(0)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001010 (0)(1)(0)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001011 (0)(1)(0)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001100 (0)(1)(0)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001101 (0)(1)(0)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001110 (0)(1)(0)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01001111 (0)(1)(0)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010000 (0)(1)(0)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010001 (0)(1)(0)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010010 (0)(1)(0)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010011 (0)(1)(0)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010100 (0)(1)(0)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010101 (0)(1)(0)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010110 (0)(1)(0)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01010111 (0)(1)(0)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011000 (0)(1)(0)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011001 (0)(1)(0)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011010 (0)(1)(0)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011011 (0)(1)(0)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011100 (0)(1)(0)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011101 (0)(1)(0)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011110 (0)(1)(0)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01011111 (0)(1)(0)(1)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100000 (0)(1)(1)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100001 (0)(1)(1)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100010 (0)(1)(1)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100011 (0)(1)(1)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100100 (0)(1)(1)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100101 (0)(1)(1)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100110 (0)(1)(1)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01100111 (0)(1)(1)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101000 (0)(1)(1)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101001 (0)(1)(1)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101010 (0)(1)(1)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101011 (0)(1)(1)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101100 (0)(1)(1)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101101 (0)(1)(1)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101110 (0)(1)(1)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01101111 (0)(1)(1)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110000 (0)(1)(1)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110001 (0)(1)(1)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110010 (0)(1)(1)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110011 (0)(1)(1)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110100 (0)(1)(1)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110101 (0)(1)(1)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110110 (0)(1)(1)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01110111 (0)(1)(1)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111000 (0)(1)(1)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111001 (0)(1)(1)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111010 (0)(1)(1)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111011 (0)(1)(1)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111100 (0)(1)(1)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111101 (0)(1)(1)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111110 (0)(1)(1)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_01111111 (0)(1)(1)(1)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000000 (1)(0)(0)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000001 (1)(0)(0)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000010 (1)(0)(0)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000011 (1)(0)(0)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000100 (1)(0)(0)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000101 (1)(0)(0)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000110 (1)(0)(0)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10000111 (1)(0)(0)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001000 (1)(0)(0)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001001 (1)(0)(0)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001010 (1)(0)(0)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001011 (1)(0)(0)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001100 (1)(0)(0)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001101 (1)(0)(0)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001110 (1)(0)(0)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10001111 (1)(0)(0)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010000 (1)(0)(0)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010001 (1)(0)(0)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010010 (1)(0)(0)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010011 (1)(0)(0)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010100 (1)(0)(0)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010101 (1)(0)(0)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010110 (1)(0)(0)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10010111 (1)(0)(0)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011000 (1)(0)(0)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011001 (1)(0)(0)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011010 (1)(0)(0)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011011 (1)(0)(0)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011100 (1)(0)(0)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011101 (1)(0)(0)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011110 (1)(0)(0)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10011111 (1)(0)(0)(1)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100000 (1)(0)(1)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100001 (1)(0)(1)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100010 (1)(0)(1)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100011 (1)(0)(1)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100100 (1)(0)(1)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100101 (1)(0)(1)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100110 (1)(0)(1)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10100111 (1)(0)(1)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101000 (1)(0)(1)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101001 (1)(0)(1)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101010 (1)(0)(1)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101011 (1)(0)(1)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101100 (1)(0)(1)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101101 (1)(0)(1)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101110 (1)(0)(1)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10101111 (1)(0)(1)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110000 (1)(0)(1)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110001 (1)(0)(1)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110010 (1)(0)(1)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110011 (1)(0)(1)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110100 (1)(0)(1)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110101 (1)(0)(1)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110110 (1)(0)(1)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10110111 (1)(0)(1)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111000 (1)(0)(1)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111001 (1)(0)(1)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111010 (1)(0)(1)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111011 (1)(0)(1)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111100 (1)(0)(1)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111101 (1)(0)(1)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111110 (1)(0)(1)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_10111111 (1)(0)(1)(1)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000000 (1)(1)(0)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000001 (1)(1)(0)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000010 (1)(1)(0)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000011 (1)(1)(0)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000100 (1)(1)(0)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000101 (1)(1)(0)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000110 (1)(1)(0)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11000111 (1)(1)(0)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001000 (1)(1)(0)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001001 (1)(1)(0)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001010 (1)(1)(0)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001011 (1)(1)(0)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001100 (1)(1)(0)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001101 (1)(1)(0)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001110 (1)(1)(0)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11001111 (1)(1)(0)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010000 (1)(1)(0)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010001 (1)(1)(0)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010010 (1)(1)(0)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010011 (1)(1)(0)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010100 (1)(1)(0)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010101 (1)(1)(0)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010110 (1)(1)(0)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11010111 (1)(1)(0)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011000 (1)(1)(0)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011001 (1)(1)(0)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011010 (1)(1)(0)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011011 (1)(1)(0)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011100 (1)(1)(0)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011101 (1)(1)(0)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011110 (1)(1)(0)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11011111 (1)(1)(0)(1)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100000 (1)(1)(1)(0)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100001 (1)(1)(1)(0)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100010 (1)(1)(1)(0)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100011 (1)(1)(1)(0)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100100 (1)(1)(1)(0)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100101 (1)(1)(1)(0)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100110 (1)(1)(1)(0)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11100111 (1)(1)(1)(0)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101000 (1)(1)(1)(0)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101001 (1)(1)(1)(0)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101010 (1)(1)(1)(0)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101011 (1)(1)(1)(0)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101100 (1)(1)(1)(0)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101101 (1)(1)(1)(0)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101110 (1)(1)(1)(0)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11101111 (1)(1)(1)(0)(1)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110000 (1)(1)(1)(1)(0)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110001 (1)(1)(1)(1)(0)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110010 (1)(1)(1)(1)(0)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110011 (1)(1)(1)(1)(0)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110100 (1)(1)(1)(1)(0)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110101 (1)(1)(1)(1)(0)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110110 (1)(1)(1)(1)(0)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11110111 (1)(1)(1)(1)(0)(1)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111000 (1)(1)(1)(1)(1)(0)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111001 (1)(1)(1)(1)(1)(0)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111010 (1)(1)(1)(1)(1)(0)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111011 (1)(1)(1)(1)(1)(0)(1)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111100 (1)(1)(1)(1)(1)(1)(0)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111101 (1)(1)(1)(1)(1)(1)(0)(1), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111110 (1)(1)(1)(1)(1)(1)(1)(0), +#define BOOST_DETAIL_BINARY_LITERAL_ELEMENT_11111111 (1)(1)(1)(1)(1)(1)(1)(1), +#endif // BOOST_UTILITY_DOCS +#endif diff --git a/libs/utility/include/boost/utility/compare_pointees.hpp b/libs/utility/include/boost/utility/compare_pointees.hpp new file mode 100644 index 00000000..5ab21cde --- /dev/null +++ b/libs/utility/include/boost/utility/compare_pointees.hpp @@ -0,0 +1,76 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#ifndef BOOST_UTILITY_COMPARE_POINTEES_25AGO2003_HPP +#define BOOST_UTILITY_COMPARE_POINTEES_25AGO2003_HPP + +#include + +namespace boost { + +// template bool equal_pointees(OP const& x, OP const& y); +// template struct equal_pointees_t; +// +// Being OP a model of OptionalPointee (either a pointer or an optional): +// +// If both x and y have valid pointees, returns the result of (*x == *y) +// If only one has a valid pointee, returns false. +// If none have valid pointees, returns true. +// No-throw +template +inline +bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y ) +{ + return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ; +} + +template +struct equal_pointees_t +{ + typedef bool result_type; + typedef OptionalPointee first_argument_type; + typedef OptionalPointee second_argument_type; + + bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const + { return equal_pointees(x,y) ; } +} ; + +// template bool less_pointees(OP const& x, OP const& y); +// template struct less_pointees_t; +// +// Being OP a model of OptionalPointee (either a pointer or an optional): +// +// If y has not a valid pointee, returns false. +// ElseIf x has not a valid pointee, returns true. +// ElseIf both x and y have valid pointees, returns the result of (*x < *y) +// No-throw +template +inline +bool less_pointees ( OptionalPointee const& x, OptionalPointee const& y ) +{ + return !y ? false : ( !x ? true : (*x) < (*y) ) ; +} + +template +struct less_pointees_t +{ + typedef bool result_type; + typedef OptionalPointee first_argument_type; + typedef OptionalPointee second_argument_type; + + bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const + { return less_pointees(x,y) ; } +} ; + +} // namespace boost + +#endif + diff --git a/libs/utility/include/boost/utility/detail/in_place_factory_prefix.hpp b/libs/utility/include/boost/utility/detail/in_place_factory_prefix.hpp new file mode 100644 index 00000000..afd76b5a --- /dev/null +++ b/libs/utility/include/boost/utility/detail/in_place_factory_prefix.hpp @@ -0,0 +1,36 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2007, Tobias Schwinger. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#ifndef BOOST_UTILITY_DETAIL_INPLACE_FACTORY_PREFIX_04APR2007_HPP +#define BOOST_UTILITY_DETAIL_INPLACE_FACTORY_PREFIX_04APR2007_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT(z,n,_) BOOST_PP_CAT(m_a,n) BOOST_PP_LPAREN() BOOST_PP_CAT(a,n) BOOST_PP_RPAREN() +#define BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL(z,n,_) BOOST_PP_CAT(A,n) const& BOOST_PP_CAT(m_a,n); + +#define BOOST_MAX_INPLACE_FACTORY_ARITY 10 + +#undef BOOST_UTILITY_DETAIL_INPLACE_FACTORY_SUFFIX_04APR2007_HPP + +#endif + diff --git a/libs/utility/include/boost/utility/detail/in_place_factory_suffix.hpp b/libs/utility/include/boost/utility/detail/in_place_factory_suffix.hpp new file mode 100644 index 00000000..58f48c70 --- /dev/null +++ b/libs/utility/include/boost/utility/detail/in_place_factory_suffix.hpp @@ -0,0 +1,23 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2007, Tobias Schwinger. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#ifndef BOOST_UTILITY_DETAIL_INPLACE_FACTORY_SUFFIX_04APR2007_HPP +#define BOOST_UTILITY_DETAIL_INPLACE_FACTORY_SUFFIX_04APR2007_HPP + +#undef BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT +#undef BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL +#undef BOOST_MAX_INPLACE_FACTORY_ARITY + +#undef BOOST_UTILITY_DETAIL_INPLACE_FACTORY_PREFIX_04APR2007_HPP + +#endif + diff --git a/libs/utility/include/boost/utility/detail/minstd_rand.hpp b/libs/utility/include/boost/utility/detail/minstd_rand.hpp new file mode 100644 index 00000000..95efb21a --- /dev/null +++ b/libs/utility/include/boost/utility/detail/minstd_rand.hpp @@ -0,0 +1,58 @@ +#ifndef BOOST_UTILITY_DETAIL_MINSTD_RAND_HPP_INCLUDED +#define BOOST_UTILITY_DETAIL_MINSTD_RAND_HPP_INCLUDED + +// Copyright 2017 Peter Dimov +// +// 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 +// +// An implementation of minstd_rand that does not require +// the Random library + +#include + +namespace boost +{ +namespace detail +{ + +class minstd_rand +{ +private: + + boost::uint_least32_t x_; + + enum { a = 48271, m = 2147483647 }; + +public: + + minstd_rand(): x_( 1 ) + { + } + + explicit minstd_rand( boost::uint_least32_t x ): x_( x % m ) + { + if( x_ == 0 ) + { + x_ = 1; + } + } + + boost::uint_least32_t operator()() + { + boost::uint_least64_t y = x_; + + y = ( a * y ) % m; + + x_ = static_cast( y ); + + return x_; + } +}; + +} // namespace detail +} // namespace boost + +#endif // #ifndef BOOST_UTILITY_DETAIL_MINSTD_RAND_HPP_INCLUDED diff --git a/libs/utility/include/boost/utility/detail/result_of_iterate.hpp b/libs/utility/include/boost/utility/detail/result_of_iterate.hpp new file mode 100644 index 00000000..2ea59446 --- /dev/null +++ b/libs/utility/include/boost/utility/detail/result_of_iterate.hpp @@ -0,0 +1,218 @@ +// Boost result_of library + +// Copyright Douglas Gregor 2004. Use, modification and +// distribution is subject to 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) + +// Copyright Daniel Walker, Eric Niebler, Michel Morin 2008-2012. +// Use, modification and distribution is subject to 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) + +// For more information, see http://www.boost.org/libs/utility +#if !defined(BOOST_PP_IS_ITERATING) +# error Boost result_of - do not include this file! +#endif + +// CWPro8 requires an argument in a function type specialization +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3002)) && BOOST_PP_ITERATION() == 0 +# define BOOST_RESULT_OF_ARGS void +#else +# define BOOST_RESULT_OF_ARGS BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T) +#endif + +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) +template +struct tr1_result_of + : conditional< + is_pointer::value || is_member_function_pointer::value + , boost::detail::tr1_result_of_impl< + typename remove_cv::type, + typename remove_cv::type(BOOST_RESULT_OF_ARGS), + (boost::detail::result_of_has_result_type::value)> + , boost::detail::tr1_result_of_impl< + F, + F(BOOST_RESULT_OF_ARGS), + (boost::detail::result_of_has_result_type::value)> >::type { }; +#endif + +#ifdef BOOST_RESULT_OF_USE_DECLTYPE +template +struct result_of + : detail::cpp0x_result_of { }; +#endif // BOOST_RESULT_OF_USE_DECLTYPE + +#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK +template +struct result_of + : conditional::value || detail::result_of_has_result::value, + tr1_result_of, + detail::cpp0x_result_of >::type { }; +#endif // BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK + +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) + +namespace detail { + +template +struct cpp0x_result_of + : conditional< + is_member_function_pointer::value + , detail::tr1_result_of_impl< + typename remove_cv::type, + typename remove_cv::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false + > + , detail::cpp0x_result_of_impl< + F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)) + > + >::type +{}; + +#ifdef BOOST_NO_SFINAE_EXPR + +template +struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION()); + +template +struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION()) { + R operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T)) const; + typedef result_of_private_type const &(*pfn_t)(...); + operator pfn_t() const volatile; +}; + +template +struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION()) + : BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION()) +{}; + +template +struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION()) + : BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION()) +{}; + +template +struct BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION()) + : conditional< + is_class::type>::value, + result_of_wrap_callable_class, + type_identity::type>::type> > + >::type +{}; + +template +struct BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) { + typedef typename BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())::type wrapper_t; + static const bool value = ( + sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type( + (boost::declval()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT)), result_of_weird_type()) + )) + ); + typedef integral_constant type; +}; + +template +struct cpp0x_result_of_impl + : lazy_enable_if< + BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) + , cpp0x_result_of_impl + > +{}; + +template +struct cpp0x_result_of_impl +{ + typedef decltype( + boost::declval()( + BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) + ) + ) type; +}; + +#else // BOOST_NO_SFINAE_EXPR + +template +struct cpp0x_result_of_impl()( + BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) + ) + )>::type> { + typedef decltype( + boost::declval()( + BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) + ) + ) type; +}; + +#endif // BOOST_NO_SFINAE_EXPR + +} // namespace detail + +#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) + +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) +template +struct result_of + : tr1_result_of { }; +#endif + +#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) + +#undef BOOST_RESULT_OF_ARGS + +#if BOOST_PP_ITERATION() >= 1 + +namespace detail { + +template +struct tr1_result_of_impl +{ + typedef R type; +}; + +template +struct tr1_result_of_impl +{ + typedef R type; +}; + +#if !BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) +template +struct tr1_result_of_impl +{ + typedef R type; +}; + +template +struct tr1_result_of_impl +{ + typedef R type; +}; + +template +struct tr1_result_of_impl +{ + typedef R type; +}; + +template +struct tr1_result_of_impl +{ + typedef R type; +}; +#endif + +} +#endif diff --git a/libs/utility/include/boost/utility/detail/result_of_variadic.hpp b/libs/utility/include/boost/utility/detail/result_of_variadic.hpp new file mode 100644 index 00000000..f6929f8a --- /dev/null +++ b/libs/utility/include/boost/utility/detail/result_of_variadic.hpp @@ -0,0 +1,190 @@ +// Boost result_of library + +// Copyright Douglas Gregor 2004. Use, modification and +// distribution is subject to 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) + +// Copyright Daniel Walker, Eric Niebler, Michel Morin 2008-2012. +// Use, modification and distribution is subject to 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) + +// For more information, see http://www.boost.org/libs/utility + +#ifndef BOOST_RESULT_OF_HPP +# error Boost result_of - do not include this file! +#endif + +template +struct tr1_result_of + : conditional< + is_pointer::value || is_member_function_pointer::value + , boost::detail::tr1_result_of_impl< + typename remove_cv::type, + typename remove_cv::type(Args...), + (boost::detail::result_of_has_result_type::value)> + , boost::detail::tr1_result_of_impl< + F, + F(Args...), + (boost::detail::result_of_has_result_type::value)> >::type { }; + +#ifdef BOOST_RESULT_OF_USE_DECLTYPE +template +struct result_of + : detail::cpp0x_result_of { }; +#endif // BOOST_RESULT_OF_USE_DECLTYPE + +#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK +template +struct result_of + : conditional::value || detail::result_of_has_result::value, + tr1_result_of, + detail::cpp0x_result_of >::type { }; +#endif // BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK + +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) + +namespace detail { + +template +struct cpp0x_result_of + : conditional< + is_member_function_pointer::value + , detail::tr1_result_of_impl< + typename remove_cv::type, + typename remove_cv::type(Args...), false + > + , detail::cpp0x_result_of_impl< + F(Args...) + > + >::type +{}; + +#ifdef BOOST_NO_SFINAE_EXPR + +template +struct result_of_callable_fun_2; + +template +struct result_of_callable_fun_2 { + R operator()(Args...) const; + typedef result_of_private_type const &(*pfn_t)(...); + operator pfn_t() const volatile; +}; + +template +struct result_of_callable_fun + : result_of_callable_fun_2 +{}; + +template +struct result_of_callable_fun + : result_of_callable_fun_2 +{}; + +template +struct result_of_select_call_wrapper_type + : conditional< + is_class::type>::value, + result_of_wrap_callable_class, + type_identity::type>::type> > + >::type +{}; + +template +struct result_of_is_callable { + typedef typename result_of_select_call_wrapper_type::type wrapper_t; + static const bool value = ( + sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type( + (boost::declval()(boost::declval()...), result_of_weird_type()) + )) + ); + typedef integral_constant type; +}; + +template +struct cpp0x_result_of_impl + : lazy_enable_if< + result_of_is_callable + , cpp0x_result_of_impl + > +{}; + +template +struct cpp0x_result_of_impl +{ + typedef decltype( + boost::declval()( + boost::declval()... + ) + ) type; +}; + +#else // BOOST_NO_SFINAE_EXPR + +template +struct cpp0x_result_of_impl()( + boost::declval()... + ) + )>::type> { + typedef decltype( + boost::declval()( + boost::declval()... + ) + ) type; +}; + +#endif // BOOST_NO_SFINAE_EXPR + +} // namespace detail + +#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) + +template +struct result_of + : tr1_result_of { }; + +#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) + +namespace detail { + +template +struct tr1_result_of_impl +{ + typedef R type; +}; + +template +struct tr1_result_of_impl +{ + typedef R type; +}; + +template +struct tr1_result_of_impl +{ + typedef R type; +}; + +template +struct tr1_result_of_impl +{ + typedef R type; +}; + +template +struct tr1_result_of_impl +{ + typedef R type; +}; + +template +struct tr1_result_of_impl +{ + typedef R type; +}; + +} diff --git a/libs/utility/include/boost/utility/identity_type.hpp b/libs/utility/include/boost/utility/identity_type.hpp new file mode 100644 index 00000000..4a1f6c4d --- /dev/null +++ b/libs/utility/include/boost/utility/identity_type.hpp @@ -0,0 +1,46 @@ + +// Copyright (C) 2009-2012 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 +// (see accompanying file LICENSE_1_0.txt or a copy at +// http://www.boost.org/LICENSE_1_0.txt) +// Home at http://www.boost.org/libs/utility/identity_type + +/** @file +Wrap type expressions with round parenthesis so they can be passed to macros +even if they contain commas. +*/ + +#ifndef BOOST_IDENTITY_TYPE_HPP_ +#define BOOST_IDENTITY_TYPE_HPP_ + +#include + +/** +@brief This macro allows to wrap the specified type expression within extra +round parenthesis so the type can be passed as a single macro parameter even if +it contains commas (not already wrapped within round parenthesis). + +@Params +@Param{parenthesized_type, +The type expression to be passed as macro parameter wrapped by a single set +of round parenthesis (...). +This type expression can contain an arbitrary number of commas. +} +@EndParams + +This macro works on any C++03 compiler (it does not use variadic macros). + +This macro must be prefixed by typename when used within templates. +Note that the compiler will not be able to automatically determine function +template parameters when they are wrapped with this macro (these parameters +need to be explicitly specified when calling the function template). + +On some compilers (like GCC), using this macro on abstract types requires to +add and remove a reference to the specified type. +*/ +#define BOOST_IDENTITY_TYPE(parenthesized_type) \ + /* must NOT prefix this with `::` to work with parenthesized syntax */ \ + boost::function_traits< void parenthesized_type >::arg1_type + +#endif // #include guard + diff --git a/libs/utility/include/boost/utility/in_place_factory.hpp b/libs/utility/include/boost/utility/in_place_factory.hpp new file mode 100644 index 00000000..d18a4c54 --- /dev/null +++ b/libs/utility/include/boost/utility/in_place_factory.hpp @@ -0,0 +1,92 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2007, Tobias Schwinger. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#ifndef BOOST_UTILITY_INPLACE_FACTORY_04APR2007_HPP +#ifndef BOOST_PP_IS_ITERATING + +#include + +namespace boost { + +class in_place_factory_base {} ; + +#ifndef BOOST_UTILITY_DOCS +#define BOOST_PP_ITERATION_LIMITS (0, BOOST_MAX_INPLACE_FACTORY_ARITY) +#define BOOST_PP_FILENAME_1 +#endif // BOOST_UTILITY_DOCS + +#include BOOST_PP_ITERATE() + +} // namespace boost + +#include + +#ifndef BOOST_UTILITY_DOCS +#define BOOST_UTILITY_INPLACE_FACTORY_04APR2007_HPP +#endif + +#else +#define N BOOST_PP_ITERATION() + +#if N +template< BOOST_PP_ENUM_PARAMS(N, class A) > +#endif +class BOOST_PP_CAT(in_place_factory,N) + : + public in_place_factory_base +{ +public: + + explicit BOOST_PP_CAT(in_place_factory,N) + ( BOOST_PP_ENUM_BINARY_PARAMS(N,A,const& a) ) +#if N > 0 + : BOOST_PP_ENUM(N, BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT, _) +#endif + {} + + template + void* apply(void* address) const + { + return new(address) T( BOOST_PP_ENUM_PARAMS(N, m_a) ); + } + + template + void* apply(void* address, std::size_t n) const + { + for(char* next = address = this->BOOST_NESTED_TEMPLATE apply(address); + !! --n;) + this->BOOST_NESTED_TEMPLATE apply(next = next+sizeof(T)); + return address; + } + + BOOST_PP_REPEAT(N, BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL, _) +}; + +#if N > 0 +template< BOOST_PP_ENUM_PARAMS(N, class A) > +inline BOOST_PP_CAT(in_place_factory,N)< BOOST_PP_ENUM_PARAMS(N, A) > +in_place( BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& a) ) +{ + return BOOST_PP_CAT(in_place_factory,N)< BOOST_PP_ENUM_PARAMS(N, A) > + ( BOOST_PP_ENUM_PARAMS(N, a) ); +} +#else +inline in_place_factory0 in_place() +{ + return in_place_factory0(); +} +#endif + +#undef N +#endif +#endif + diff --git a/libs/utility/include/boost/utility/result_of.hpp b/libs/utility/include/boost/utility/result_of.hpp new file mode 100644 index 00000000..bd926899 --- /dev/null +++ b/libs/utility/include/boost/utility/result_of.hpp @@ -0,0 +1,256 @@ +// Boost result_of library + +// Copyright Douglas Gregor 2004. Use, modification and +// distribution is subject to 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) + +// For more information, see http://www.boost.org/libs/utility +#ifndef BOOST_RESULT_OF_HPP +#define BOOST_RESULT_OF_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES +# undef BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES +# define BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES +#endif +#ifdef BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES +# include +# include +# include +# include +# include +# include +# include +#endif + +#ifndef BOOST_UTILITY_DOCS +#ifndef BOOST_RESULT_OF_NUM_ARGS +# define BOOST_RESULT_OF_NUM_ARGS 16 +#endif +#endif // BOOST_UTILITY_DOCS + +// Use the decltype-based version of result_of by default if the compiler +// supports N3276 . +// The user can force the choice by defining BOOST_RESULT_OF_USE_DECLTYPE, +// BOOST_RESULT_OF_USE_TR1, or BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK but not more than one! +#if (defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1)) || \ + (defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)) || \ + (defined(BOOST_RESULT_OF_USE_TR1) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)) +# error More than one of BOOST_RESULT_OF_USE_DECLTYPE, BOOST_RESULT_OF_USE_TR1 and \ + BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK cannot be defined at the same time. +#endif + +#ifndef BOOST_UTILITY_DOCS +#ifndef BOOST_RESULT_OF_USE_TR1 +# ifndef BOOST_RESULT_OF_USE_DECLTYPE +# ifndef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK +# ifndef BOOST_NO_CXX11_DECLTYPE_N3276 // this implies !defined(BOOST_NO_CXX11_DECLTYPE) +# define BOOST_RESULT_OF_USE_DECLTYPE +# else +# define BOOST_RESULT_OF_USE_TR1 +# endif +# endif +# endif +#endif +#endif // BOOST_UTILITY_DOCS + +namespace boost { + +template struct result_of; +template struct tr1_result_of; // a TR1-style implementation of result_of + +#if !defined(BOOST_NO_SFINAE) +namespace detail { + +typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1 +typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2 + +template struct result_of_has_type {}; + +template struct result_of_has_result_type_impl +{ + template static result_of_yes_type f( result_of_has_type* ); + template static result_of_no_type f( ... ); + + typedef boost::integral_constant(0)) == sizeof(result_of_yes_type)> type; +}; + +template struct result_of_has_result_type: result_of_has_result_type_impl::type +{ +}; + +// Work around a nvcc bug by only defining has_result when it's needed. +#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK + +template class C> struct result_of_has_template {}; + +template struct result_of_has_result_impl +{ + template static result_of_yes_type f( result_of_has_template* ); + template static result_of_no_type f( ... ); + + typedef boost::integral_constant(0)) == sizeof(result_of_yes_type)> type; +}; + +template struct result_of_has_result: result_of_has_result_impl::type +{ +}; + +#endif + +template struct tr1_result_of_impl; + +template struct cpp0x_result_of; + +#ifdef BOOST_NO_SFINAE_EXPR + +// There doesn't seem to be any other way to turn this off such that the presence of +// the user-defined operator,() below doesn't cause spurious warning all over the place, +// so unconditionally and globally turn it off. (https://svn.boost.org/trac10/ticket/7663) +#ifdef BOOST_MSVC +# pragma warning(disable: 4913) // user defined binary operator ',' exists but no overload could convert all operands, default built-in binary operator ',' used +#endif + +struct result_of_private_type {}; + +struct result_of_weird_type { + friend result_of_private_type operator,(result_of_private_type, result_of_weird_type); +}; + +template +result_of_no_type result_of_is_private_type(T const &); +result_of_yes_type result_of_is_private_type(result_of_private_type); + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable: 4512) // assignment operator could not be generated. +#endif +template +struct result_of_callable_class : C { + result_of_callable_class(); + typedef result_of_private_type const &(*pfn_t)(...); + operator pfn_t() const volatile; +}; +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +template +struct result_of_wrap_callable_class { + typedef result_of_callable_class type; +}; + +template +struct result_of_wrap_callable_class { + typedef result_of_callable_class const type; +}; + +template +struct result_of_wrap_callable_class { + typedef result_of_callable_class volatile type; +}; + +template +struct result_of_wrap_callable_class { + typedef result_of_callable_class const volatile type; +}; + +template +struct result_of_wrap_callable_class { + typedef typename result_of_wrap_callable_class::type &type; +}; + +template struct cpp0x_result_of_impl; + +#else // BOOST_NO_SFINAE_EXPR + +template +struct result_of_always_void +{ + typedef void type; +}; + +template struct cpp0x_result_of_impl {}; + +#endif // BOOST_NO_SFINAE_EXPR + +template +struct result_of_void_impl +{ + typedef void type; +}; + +template +struct result_of_void_impl +{ + typedef R type; +}; + +template +struct result_of_void_impl +{ + typedef R type; +}; + +// Determine the return type of a function pointer or pointer to member. +template +struct result_of_pointer + : tr1_result_of_impl::type, FArgs, false> { }; + +template +struct tr1_result_of_impl +{ + typedef typename F::result_type type; +}; + +template +struct is_function_with_no_args : false_type {}; + +template +struct is_function_with_no_args : true_type {}; + +template +struct result_of_nested_result : F::template result +{}; + +template +struct tr1_result_of_impl + : conditional::value, + result_of_void_impl, + result_of_nested_result >::type +{}; + +} // end namespace detail + +#ifndef BOOST_RESULT_OF_NO_VARIADIC_TEMPLATES +# include +#else +# define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_RESULT_OF_NUM_ARGS,)) +# include BOOST_PP_ITERATE() +#endif + +#if 0 +// inform dependency trackers, as they can't see through macro includes +#include +#endif + +#else +# define BOOST_NO_RESULT_OF 1 +#endif + +} + +#endif // BOOST_RESULT_OF_HPP diff --git a/libs/utility/include/boost/utility/string_ref.hpp b/libs/utility/include/boost/utility/string_ref.hpp new file mode 100644 index 00000000..6e9f7bbe --- /dev/null +++ b/libs/utility/include/boost/utility/string_ref.hpp @@ -0,0 +1,520 @@ +/* + Copyright (c) Marshall Clow 2012-2015. + Copyright (c) Glen Joseph Fernandes 2019 (glenjofe@gmail.com) + + 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) + + For more information, see http://www.boost.org + + Based on the StringRef implementation in LLVM (http://llvm.org) and + N3422 by Jeffrey Yasskin + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html + +*/ + +#ifndef BOOST_STRING_REF_HPP +#define BOOST_STRING_REF_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406) +// GCC 4.6 cannot handle a defaulted function with noexcept specifier +#define BOOST_STRING_REF_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS +#endif + +namespace boost { + + namespace detail { + // A helper functor because sometimes we don't have lambdas + template + class string_ref_traits_eq { + public: + string_ref_traits_eq ( charT ch ) : ch_(ch) {} + bool operator () ( charT val ) const { return traits::eq ( ch_, val ); } + charT ch_; + }; + } + + template + class basic_string_ref { + public: + // types + typedef charT value_type; + typedef const charT* pointer; + typedef const charT& reference; + typedef const charT& const_reference; + typedef pointer const_iterator; // impl-defined + typedef const_iterator iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef const_reverse_iterator reverse_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1); + + // construct/copy + BOOST_CONSTEXPR basic_string_ref () BOOST_NOEXCEPT + : ptr_(NULL), len_(0) {} + + // by defaulting these functions, basic_string_ref becomes + // trivially copy/move constructible. + BOOST_CONSTEXPR basic_string_ref (const basic_string_ref &rhs) BOOST_NOEXCEPT +#ifndef BOOST_STRING_REF_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS + = default; +#else + : ptr_(rhs.ptr_), len_(rhs.len_) {} +#endif + + basic_string_ref& operator=(const basic_string_ref &rhs) BOOST_NOEXCEPT +#ifndef BOOST_STRING_REF_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS + = default; +#else + { + ptr_ = rhs.ptr_; + len_ = rhs.len_; + return *this; + } +#endif + + basic_string_ref(const charT* str) BOOST_NOEXCEPT + : ptr_(str), len_(traits::length(str)) {} + + template + basic_string_ref(const std::basic_string& str) + : ptr_(str.data()), len_(str.length()) {} + +// #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) +// // Constructing a string_ref from a temporary string is a bad idea +// template +// basic_string_ref( std::basic_string&&) +// = delete; +// #endif + + BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len) BOOST_NOEXCEPT + : ptr_(str), len_(len) {} + +#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS + template + explicit operator std::basic_string() const { + return std::basic_string ( begin(), end()); + } +#endif + + std::basic_string to_string () const { + return std::basic_string ( begin(), end()); + } + + // iterators + BOOST_CONSTEXPR const_iterator begin() const { return ptr_; } + BOOST_CONSTEXPR const_iterator cbegin() const { return ptr_; } + BOOST_CONSTEXPR const_iterator end() const { return ptr_ + len_; } + BOOST_CONSTEXPR const_iterator cend() const { return ptr_ + len_; } + const_reverse_iterator rbegin() const { return const_reverse_iterator (end()); } + const_reverse_iterator crbegin() const { return const_reverse_iterator (end()); } + const_reverse_iterator rend() const { return const_reverse_iterator (begin()); } + const_reverse_iterator crend() const { return const_reverse_iterator (begin()); } + + // capacity + BOOST_CONSTEXPR size_type size() const { return len_; } + BOOST_CONSTEXPR size_type length() const { return len_; } + BOOST_CONSTEXPR size_type max_size() const { return ~static_cast(0) / (sizeof(value_type) * 2u); } + BOOST_CONSTEXPR bool empty() const { return len_ == 0; } + + // element access + BOOST_CONSTEXPR const charT& operator[](size_type pos) const { return ptr_[pos]; } + + const charT& at(size_type pos) const { + if ( pos >= len_ ) + BOOST_THROW_EXCEPTION( std::out_of_range ( "boost::string_ref::at" ) ); + return ptr_[pos]; + } + + BOOST_CONSTEXPR const charT& front() const { return ptr_[0]; } + BOOST_CONSTEXPR const charT& back() const { return ptr_[len_-1]; } + BOOST_CONSTEXPR const charT* data() const { return ptr_; } + + // modifiers + void clear() { len_ = 0; } + void remove_prefix(size_type n) { + if ( n > len_ ) + n = len_; + ptr_ += n; + len_ -= n; + } + + void remove_suffix(size_type n) { + if ( n > len_ ) + n = len_; + len_ -= n; + } + + + // basic_string_ref string operations + basic_string_ref substr() const { + return basic_string_ref(data(), size()); + } + + basic_string_ref substr(size_type pos, size_type n=npos) const { + if ( pos > size()) + BOOST_THROW_EXCEPTION( std::out_of_range ( "string_ref::substr" ) ); + return basic_string_ref(data() + pos, (std::min)(size() - pos, n)); + } + + int compare(basic_string_ref x) const { + const int cmp = traits::compare ( ptr_, x.ptr_, (std::min)(len_, x.len_)); + return cmp != 0 ? cmp : ( len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1 ); + } + + bool starts_with(charT c) const { return !empty() && traits::eq ( c, front()); } + bool starts_with(basic_string_ref x) const { + return len_ >= x.len_ && traits::compare ( ptr_, x.ptr_, x.len_ ) == 0; + } + + bool ends_with(charT c) const { return !empty() && traits::eq ( c, back()); } + bool ends_with(basic_string_ref x) const { + return len_ >= x.len_ && traits::compare ( ptr_ + len_ - x.len_, x.ptr_, x.len_ ) == 0; + } + + size_type find(basic_string_ref s) const { + if (s.empty()) return 0; + const_iterator iter = std::search ( this->cbegin (), this->cend (), + s.cbegin (), s.cend (), traits::eq ); + return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); + } + + size_type find(charT c) const { + const_iterator iter = std::find_if ( this->cbegin (), this->cend (), + detail::string_ref_traits_eq ( c )); + return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); + } + + size_type rfind(basic_string_ref s) const { + if (s.empty()) return 0; + const_reverse_iterator iter = std::search ( this->crbegin (), this->crend (), + s.crbegin (), s.crend (), traits::eq ); + return iter == this->crend () ? npos : (std::distance(iter, this->crend()) - s.size()); + } + + size_type rfind(charT c) const { + const_reverse_iterator iter = std::find_if ( this->crbegin (), this->crend (), + detail::string_ref_traits_eq ( c )); + return iter == this->crend () ? npos : (this->size() - 1 - std::distance(this->crbegin(), iter)); + } + + size_type find_first_of(charT c) const { return find (c); } + size_type find_last_of (charT c) const { return rfind (c); } + + size_type find_first_of(basic_string_ref s) const { + const_iterator iter = std::find_first_of + ( this->cbegin (), this->cend (), s.cbegin (), s.cend (), traits::eq ); + return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); + } + + size_type find_last_of(basic_string_ref s) const { + const_reverse_iterator iter = std::find_first_of + ( this->crbegin (), this->crend (), s.cbegin (), s.cend (), traits::eq ); + return iter == this->crend () ? npos : (this->size() - 1 - std::distance(this->crbegin(), iter)); + } + + size_type find_first_not_of(basic_string_ref s) const { + const_iterator iter = find_not_of ( this->cbegin (), this->cend (), s ); + return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); + } + + size_type find_first_not_of(charT c) const { + for ( const_iterator iter = this->cbegin (); iter != this->cend (); ++iter ) + if ( !traits::eq ( c, *iter )) + return std::distance ( this->cbegin (), iter ); + return npos; + } + + size_type find_last_not_of(basic_string_ref s) const { + const_reverse_iterator iter = find_not_of ( this->crbegin (), this->crend (), s ); + return iter == this->crend () ? npos : (this->size() - 1 - std::distance(this->crbegin(), iter)); + } + + size_type find_last_not_of(charT c) const { + for ( const_reverse_iterator iter = this->crbegin (); iter != this->crend (); ++iter ) + if ( !traits::eq ( c, *iter )) + return this->size() - 1 - std::distance(this->crbegin(), iter); + return npos; + } + + private: + + template + Iterator find_not_of ( Iterator first, Iterator last, basic_string_ref s ) const { + for ( ; first != last ; ++first ) + if ( 0 == traits::find ( s.ptr_, s.len_, *first )) + return first; + return last; + } + + + + const charT *ptr_; + std::size_t len_; + }; + + +// Comparison operators +// Equality + template + inline bool operator==(basic_string_ref x, basic_string_ref y) { + if ( x.size () != y.size ()) return false; + return x.compare(y) == 0; + } + + template + inline bool operator==(basic_string_ref x, const std::basic_string & y) { + return x == basic_string_ref(y); + } + + template + inline bool operator==(const std::basic_string & x, basic_string_ref y) { + return basic_string_ref(x) == y; + } + + template + inline bool operator==(basic_string_ref x, const charT * y) { + return x == basic_string_ref(y); + } + + template + inline bool operator==(const charT * x, basic_string_ref y) { + return basic_string_ref(x) == y; + } + +// Inequality + template + inline bool operator!=(basic_string_ref x, basic_string_ref y) { + if ( x.size () != y.size ()) return true; + return x.compare(y) != 0; + } + + template + inline bool operator!=(basic_string_ref x, const std::basic_string & y) { + return x != basic_string_ref(y); + } + + template + inline bool operator!=(const std::basic_string & x, basic_string_ref y) { + return basic_string_ref(x) != y; + } + + template + inline bool operator!=(basic_string_ref x, const charT * y) { + return x != basic_string_ref(y); + } + + template + inline bool operator!=(const charT * x, basic_string_ref y) { + return basic_string_ref(x) != y; + } + +// Less than + template + inline bool operator<(basic_string_ref x, basic_string_ref y) { + return x.compare(y) < 0; + } + + template + inline bool operator<(basic_string_ref x, const std::basic_string & y) { + return x < basic_string_ref(y); + } + + template + inline bool operator<(const std::basic_string & x, basic_string_ref y) { + return basic_string_ref(x) < y; + } + + template + inline bool operator<(basic_string_ref x, const charT * y) { + return x < basic_string_ref(y); + } + + template + inline bool operator<(const charT * x, basic_string_ref y) { + return basic_string_ref(x) < y; + } + +// Greater than + template + inline bool operator>(basic_string_ref x, basic_string_ref y) { + return x.compare(y) > 0; + } + + template + inline bool operator>(basic_string_ref x, const std::basic_string & y) { + return x > basic_string_ref(y); + } + + template + inline bool operator>(const std::basic_string & x, basic_string_ref y) { + return basic_string_ref(x) > y; + } + + template + inline bool operator>(basic_string_ref x, const charT * y) { + return x > basic_string_ref(y); + } + + template + inline bool operator>(const charT * x, basic_string_ref y) { + return basic_string_ref(x) > y; + } + +// Less than or equal to + template + inline bool operator<=(basic_string_ref x, basic_string_ref y) { + return x.compare(y) <= 0; + } + + template + inline bool operator<=(basic_string_ref x, const std::basic_string & y) { + return x <= basic_string_ref(y); + } + + template + inline bool operator<=(const std::basic_string & x, basic_string_ref y) { + return basic_string_ref(x) <= y; + } + + template + inline bool operator<=(basic_string_ref x, const charT * y) { + return x <= basic_string_ref(y); + } + + template + inline bool operator<=(const charT * x, basic_string_ref y) { + return basic_string_ref(x) <= y; + } + +// Greater than or equal to + template + inline bool operator>=(basic_string_ref x, basic_string_ref y) { + return x.compare(y) >= 0; + } + + template + inline bool operator>=(basic_string_ref x, const std::basic_string & y) { + return x >= basic_string_ref(y); + } + + template + inline bool operator>=(const std::basic_string & x, basic_string_ref y) { + return basic_string_ref(x) >= y; + } + + template + inline bool operator>=(basic_string_ref x, const charT * y) { + return x >= basic_string_ref(y); + } + + template + inline bool operator>=(const charT * x, basic_string_ref y) { + return basic_string_ref(x) >= y; + } + + // Inserter + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, const basic_string_ref& str) { + return boost::io::ostream_put(os, str.data(), str.size()); + } + +#if 0 + // numeric conversions + // + // These are short-term implementations. + // In a production environment, I would rather avoid the copying. + // + inline int stoi (string_ref str, size_t* idx=0, int base=10) { + return std::stoi ( std::string(str), idx, base ); + } + + inline long stol (string_ref str, size_t* idx=0, int base=10) { + return std::stol ( std::string(str), idx, base ); + } + + inline unsigned long stoul (string_ref str, size_t* idx=0, int base=10) { + return std::stoul ( std::string(str), idx, base ); + } + + inline long long stoll (string_ref str, size_t* idx=0, int base=10) { + return std::stoll ( std::string(str), idx, base ); + } + + inline unsigned long long stoull (string_ref str, size_t* idx=0, int base=10) { + return std::stoull ( std::string(str), idx, base ); + } + + inline float stof (string_ref str, size_t* idx=0) { + return std::stof ( std::string(str), idx ); + } + + inline double stod (string_ref str, size_t* idx=0) { + return std::stod ( std::string(str), idx ); + } + + inline long double stold (string_ref str, size_t* idx=0) { + return std::stold ( std::string(str), idx ); + } + + inline int stoi (wstring_ref str, size_t* idx=0, int base=10) { + return std::stoi ( std::wstring(str), idx, base ); + } + + inline long stol (wstring_ref str, size_t* idx=0, int base=10) { + return std::stol ( std::wstring(str), idx, base ); + } + + inline unsigned long stoul (wstring_ref str, size_t* idx=0, int base=10) { + return std::stoul ( std::wstring(str), idx, base ); + } + + inline long long stoll (wstring_ref str, size_t* idx=0, int base=10) { + return std::stoll ( std::wstring(str), idx, base ); + } + + inline unsigned long long stoull (wstring_ref str, size_t* idx=0, int base=10) { + return std::stoull ( std::wstring(str), idx, base ); + } + + inline float stof (wstring_ref str, size_t* idx=0) { + return std::stof ( std::wstring(str), idx ); + } + + inline double stod (wstring_ref str, size_t* idx=0) { + return std::stod ( std::wstring(str), idx ); + } + + inline long double stold (wstring_ref str, size_t* idx=0) { + return std::stold ( std::wstring(str), idx ); + } +#endif + +} + +#if 0 +namespace std { + // Hashing + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; +} +#endif + +#endif diff --git a/libs/utility/include/boost/utility/string_ref_fwd.hpp b/libs/utility/include/boost/utility/string_ref_fwd.hpp new file mode 100644 index 00000000..f58b98c1 --- /dev/null +++ b/libs/utility/include/boost/utility/string_ref_fwd.hpp @@ -0,0 +1,37 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org + + Based on the StringRef implementation in LLVM (http://llvm.org) and + N3422 by Jeffrey Yasskin + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html + +*/ + +#ifndef BOOST_STRING_REF_FWD_HPP +#define BOOST_STRING_REF_FWD_HPP + +#include +#include + +namespace boost { + + template > class basic_string_ref; + typedef basic_string_ref > string_ref; + typedef basic_string_ref > wstring_ref; + +#ifndef BOOST_NO_CXX11_CHAR16_T + typedef basic_string_ref > u16string_ref; +#endif + +#ifndef BOOST_NO_CXX11_CHAR32_T + typedef basic_string_ref > u32string_ref; +#endif + +} + +#endif diff --git a/libs/utility/include/boost/utility/string_view.hpp b/libs/utility/include/boost/utility/string_view.hpp new file mode 100644 index 00000000..3d195b6e --- /dev/null +++ b/libs/utility/include/boost/utility/string_view.hpp @@ -0,0 +1,694 @@ +/* + Copyright (c) Marshall Clow 2012-2015. + Copyright (c) Beman Dawes 2015 + Copyright (c) Glen Joseph Fernandes 2019 (glenjofe@gmail.com) + + 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) + + For more information, see http://www.boost.org + + Based on the StringRef implementation in LLVM (http://llvm.org) and + N3422 by Jeffrey Yasskin + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html + Updated July 2015 to reflect the Library Fundamentals TS + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html +*/ + +#ifndef BOOST_STRING_VIEW_HPP +#define BOOST_STRING_VIEW_HPP + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406) +// GCC 4.6 cannot handle a defaulted function with noexcept specifier +#define BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS +#endif + +namespace boost { + + namespace detail { + // A helper functor because sometimes we don't have lambdas + template + class string_view_traits_eq { + public: + string_view_traits_eq ( charT ch ) : ch_(ch) {} + bool operator()( charT val ) const { return traits::eq (ch_, val); } + charT ch_; + }; + } + + template // traits defaulted in string_view_fwd.hpp + class basic_string_view { + public: + // types + typedef traits traits_type; + typedef charT value_type; + typedef charT* pointer; + typedef const charT* const_pointer; + typedef charT& reference; + typedef const charT& const_reference; + typedef const_pointer const_iterator; // impl-defined + typedef const_iterator iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef const_reverse_iterator reverse_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1); + + // construct/copy + BOOST_CONSTEXPR basic_string_view() BOOST_NOEXCEPT + : ptr_(NULL), len_(0) {} + + // by defaulting these functions, basic_string_ref becomes + // trivially copy/move constructible. + BOOST_CONSTEXPR basic_string_view(const basic_string_view &rhs) BOOST_NOEXCEPT +#ifndef BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS + = default; +#else + : ptr_(rhs.ptr_), len_(rhs.len_) {} +#endif + + basic_string_view& operator=(const basic_string_view &rhs) BOOST_NOEXCEPT +#ifndef BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS + = default; +#else + { + ptr_ = rhs.ptr_; + len_ = rhs.len_; + return *this; + } +#endif + + template + basic_string_view(const std::basic_string& str) BOOST_NOEXCEPT + : ptr_(str.data()), len_(str.length()) {} + +// #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) +// // Constructing a string_view from a temporary string is a bad idea +// template +// basic_string_view( std::basic_string&&) +// = delete; +// #endif + + BOOST_CONSTEXPR basic_string_view(const charT* str) + : ptr_(str), len_(traits::length(str)) {} + + BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len) + : ptr_(str), len_(len) {} + + // iterators + BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return ptr_; } + BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT { return ptr_; } + BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return ptr_ + len_; } + BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT { return ptr_ + len_; } + const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); } + const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); } + const_reverse_iterator crend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); } + + // capacity + BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT { return len_; } + BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT { return len_; } + BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT { return ~static_cast(0) / (sizeof(value_type) * 2u); } + BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT { return len_ == 0; } + + // element access + BOOST_CONSTEXPR const_reference operator[](size_type pos) const BOOST_NOEXCEPT { return ptr_[pos]; } + + BOOST_CONSTEXPR const_reference at(size_type pos) const { + return pos >= len_ ? BOOST_THROW_EXCEPTION(std::out_of_range("boost::string_view::at")), ptr_[0] : ptr_[pos]; + } + + BOOST_CONSTEXPR const_reference front() const { return ptr_[0]; } + BOOST_CONSTEXPR const_reference back() const { return ptr_[len_-1]; } + BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT { return ptr_; } + + // modifiers + void clear() BOOST_NOEXCEPT { len_ = 0; } // Boost extension + + BOOST_CXX14_CONSTEXPR void remove_prefix(size_type n) { + BOOST_ASSERT(n <= size()); + // This check is deprecated and is left for backward compatibility. It will be removed in the future. + if ( n > len_ ) + n = len_; + ptr_ += n; + len_ -= n; + } + + BOOST_CXX14_CONSTEXPR void remove_suffix(size_type n) { + BOOST_ASSERT(n <= size()); + // This check is deprecated and is left for backward compatibility. It will be removed in the future. + if ( n > len_ ) + n = len_; + len_ -= n; + } + + BOOST_CXX14_CONSTEXPR void swap(basic_string_view& s) BOOST_NOEXCEPT { + std::swap(ptr_, s.ptr_); + std::swap(len_, s.len_); + } + + // basic_string_view string operations +#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS + template + explicit operator std::basic_string() const { + return std::basic_string(begin(), end()); + } +#endif + +#ifndef BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS + template > + std::basic_string to_string(const Allocator& a = Allocator()) const { + return std::basic_string(begin(), end(), a); + } +#else + std::basic_string to_string() const { + return std::basic_string(begin(), end()); + } + + template + std::basic_string to_string(const Allocator& a) const { + return std::basic_string(begin(), end(), a); + } +#endif + + size_type copy(charT* s, size_type n, size_type pos=0) const { + if (pos > size()) + BOOST_THROW_EXCEPTION(std::out_of_range("string_view::copy" )); + size_type rlen = (std::min)(n, len_ - pos); + traits_type::copy(s, data() + pos, rlen); + return rlen; + } + + BOOST_CXX14_CONSTEXPR basic_string_view substr() const { + return basic_string_view(data(), size()); + } + + BOOST_CXX14_CONSTEXPR basic_string_view substr(size_type pos, size_type n=npos) const { + if ( pos > size()) + BOOST_THROW_EXCEPTION( std::out_of_range ( "string_view::substr" ) ); + return basic_string_view(data() + pos, (std::min)(size() - pos, n)); + } + + BOOST_CXX14_CONSTEXPR int compare(basic_string_view x) const BOOST_NOEXCEPT { + const int cmp = traits::compare(ptr_, x.ptr_, (std::min)(len_, x.len_)); + return cmp != 0 ? cmp : (len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1); + } + + BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, basic_string_view x) + const { + return substr(pos1, n1).compare(x); + } + + BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, + basic_string_view x, size_type pos2, size_type n2) const { + return substr(pos1, n1).compare(x.substr(pos2, n2)); + } + + BOOST_CXX14_CONSTEXPR int compare(const charT* x) const { + return compare(basic_string_view(x)); + } + + BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, const charT* x) const { + return substr(pos1, n1).compare(basic_string_view(x)); + } + + BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, + const charT* x, size_type n2) const { + return substr(pos1, n1).compare(basic_string_view(x, n2)); + } + + // Searches + BOOST_CONSTEXPR bool starts_with(charT c) const BOOST_NOEXCEPT { // Boost extension + return !empty() && traits::eq(c, front()); + } + + BOOST_CONSTEXPR bool starts_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension + return len_ >= x.len_ && traits::compare(ptr_, x.ptr_, x.len_) == 0; + } + + BOOST_CONSTEXPR bool ends_with(charT c) const BOOST_NOEXCEPT { // Boost extension + return !empty() && traits::eq(c, back()); + } + + BOOST_CONSTEXPR bool ends_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension + return len_ >= x.len_ && + traits::compare(ptr_ + len_ - x.len_, x.ptr_, x.len_) == 0; + } + + BOOST_CXX14_CONSTEXPR bool contains(basic_string_view s) const BOOST_NOEXCEPT { + return find(s) != npos; + } + + BOOST_CXX14_CONSTEXPR bool contains(charT c) const BOOST_NOEXCEPT { + return find(c) != npos; + } + + BOOST_CXX14_CONSTEXPR bool contains(const charT* s) const BOOST_NOEXCEPT { + return find(s) != npos; + } + + // find + BOOST_CXX14_CONSTEXPR size_type find(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT { + if (pos > size()) + return npos; + if (s.empty()) + return pos; + if (s.size() > size() - pos) + return npos; + const charT* cur = ptr_ + pos; + const charT* last = cend() - s.size() + 1; + for (; cur != last ; ++cur) { + cur = traits::find(cur, last - cur, s[0]); + if (!cur) + return npos; + if (traits::compare(cur, s.cbegin(), s.size()) == 0) + return cur - ptr_; + } + return npos; + } + BOOST_CXX14_CONSTEXPR size_type find(charT c, size_type pos = 0) const BOOST_NOEXCEPT { + if (pos > size()) + return npos; + const charT* ret_ptr = traits::find(ptr_ + pos, len_ - pos, c); + if (ret_ptr) + return ret_ptr - ptr_; + return npos; + } + BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT + { return find(basic_string_view(s, n), pos); } + BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT + { return find(basic_string_view(s), pos); } + + // rfind + BOOST_CXX14_CONSTEXPR size_type rfind(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT { + if (len_ < s.len_) + return npos; + if (pos > len_ - s.len_) + pos = len_ - s.len_; + if (s.len_ == 0u) // an empty string is always found + return pos; + for (const charT* cur = ptr_ + pos; ; --cur) { + if (traits::compare(cur, s.ptr_, s.len_) == 0) + return cur - ptr_; + if (cur == ptr_) + return npos; + }; + } + BOOST_CXX14_CONSTEXPR size_type rfind(charT c, size_type pos = npos) const BOOST_NOEXCEPT + { return rfind(basic_string_view(&c, 1), pos); } + BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT + { return rfind(basic_string_view(s, n), pos); } + BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT + { return rfind(basic_string_view(s), pos); } + + // find_first_of + BOOST_CXX14_CONSTEXPR size_type find_first_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT { + if (pos >= len_ || s.len_ == 0) + return npos; + const_iterator iter = std::find_first_of + (this->cbegin () + pos, this->cend (), s.cbegin (), s.cend (), traits::eq); + return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); + } + BOOST_CXX14_CONSTEXPR size_type find_first_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT + { return find(c, pos); } + BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT + { return find_first_of(basic_string_view(s, n), pos); } + BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT + { return find_first_of(basic_string_view(s), pos); } + + // find_last_of + BOOST_CXX14_CONSTEXPR size_type find_last_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT { + if (s.len_ == 0u) + return npos; + if (pos >= len_) + pos = 0; + else + pos = len_ - (pos+1); + const_reverse_iterator iter = std::find_first_of + ( this->crbegin () + pos, this->crend (), s.cbegin (), s.cend (), traits::eq ); + return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter); + } + BOOST_CXX14_CONSTEXPR size_type find_last_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT + { return find_last_of(basic_string_view(&c, 1), pos); } + BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT + { return find_last_of(basic_string_view(s, n), pos); } + BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT + { return find_last_of(basic_string_view(s), pos); } + + // find_first_not_of + BOOST_CXX14_CONSTEXPR size_type find_first_not_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT { + if (pos >= len_) + return npos; + if (s.len_ == 0) + return pos; + const_iterator iter = find_not_of ( this->cbegin () + pos, this->cend (), s ); + return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); + } + BOOST_CXX14_CONSTEXPR size_type find_first_not_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT + { return find_first_not_of(basic_string_view(&c, 1), pos); } + BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT + { return find_first_not_of(basic_string_view(s, n), pos); } + BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT + { return find_first_not_of(basic_string_view(s), pos); } + + // find_last_not_of + BOOST_CXX14_CONSTEXPR size_type find_last_not_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT { + if (pos >= len_) + pos = len_ - 1; + if (s.len_ == 0u) + return pos; + pos = len_ - (pos+1); + const_reverse_iterator iter = find_not_of ( this->crbegin () + pos, this->crend (), s ); + return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter ); + } + BOOST_CXX14_CONSTEXPR size_type find_last_not_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT + { return find_last_not_of(basic_string_view(&c, 1), pos); } + BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT + { return find_last_not_of(basic_string_view(s, n), pos); } + BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT + { return find_last_not_of(basic_string_view(s), pos); } + + private: + template + size_type reverse_distance(r_iter first, r_iter last) const BOOST_NOEXCEPT { + // Portability note here: std::distance is not NOEXCEPT, but calling it with a string_view::reverse_iterator will not throw. + return len_ - 1 - std::distance ( first, last ); + } + + template + Iterator find_not_of(Iterator first, Iterator last, basic_string_view s) const BOOST_NOEXCEPT { + for (; first != last ; ++first) + if ( 0 == traits::find(s.ptr_, s.len_, *first)) + return first; + return last; + } + + const charT *ptr_; + std::size_t len_; + }; + + +// Comparison operators +// Equality + template + inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view x, + basic_string_view y) BOOST_NOEXCEPT { + if (x.size () != y.size ()) return false; + return x.compare(y) == 0; + } + +// Inequality + template + inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view x, + basic_string_view y) BOOST_NOEXCEPT { + if ( x.size () != y.size ()) return true; + return x.compare(y) != 0; + } + +// Less than + template + inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view x, + basic_string_view y) BOOST_NOEXCEPT { + return x.compare(y) < 0; + } + +// Greater than + template + inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view x, + basic_string_view y) BOOST_NOEXCEPT { + return x.compare(y) > 0; + } + +// Less than or equal to + template + inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view x, + basic_string_view y) BOOST_NOEXCEPT { + return x.compare(y) <= 0; + } + +// Greater than or equal to + template + inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view x, + basic_string_view y) BOOST_NOEXCEPT { + return x.compare(y) >= 0; + } + +// "sufficient additional overloads of comparison functions" + template + inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view x, + const std::basic_string & y) BOOST_NOEXCEPT { + return x == basic_string_view(y); + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator==(const std::basic_string & x, + basic_string_view y) BOOST_NOEXCEPT { + return basic_string_view(x) == y; + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view x, + const charT * y) BOOST_NOEXCEPT { + return x == basic_string_view(y); + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator==(const charT * x, + basic_string_view y) BOOST_NOEXCEPT { + return basic_string_view(x) == y; + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view x, + const std::basic_string & y) BOOST_NOEXCEPT { + return x != basic_string_view(y); + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator!=(const std::basic_string & x, + basic_string_view y) BOOST_NOEXCEPT { + return basic_string_view(x) != y; + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view x, + const charT * y) BOOST_NOEXCEPT { + return x != basic_string_view(y); + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator!=(const charT * x, + basic_string_view y) BOOST_NOEXCEPT { + return basic_string_view(x) != y; + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view x, + const std::basic_string & y) BOOST_NOEXCEPT { + return x < basic_string_view(y); + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator<(const std::basic_string & x, + basic_string_view y) BOOST_NOEXCEPT { + return basic_string_view(x) < y; + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view x, + const charT * y) BOOST_NOEXCEPT { + return x < basic_string_view(y); + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator<(const charT * x, + basic_string_view y) BOOST_NOEXCEPT { + return basic_string_view(x) < y; + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view x, + const std::basic_string & y) BOOST_NOEXCEPT { + return x > basic_string_view(y); + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator>(const std::basic_string & x, + basic_string_view y) BOOST_NOEXCEPT { + return basic_string_view(x) > y; + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view x, + const charT * y) BOOST_NOEXCEPT { + return x > basic_string_view(y); + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator>(const charT * x, + basic_string_view y) BOOST_NOEXCEPT { + return basic_string_view(x) > y; + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view x, + const std::basic_string & y) BOOST_NOEXCEPT { + return x <= basic_string_view(y); + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator<=(const std::basic_string & x, + basic_string_view y) BOOST_NOEXCEPT { + return basic_string_view(x) <= y; + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view x, + const charT * y) BOOST_NOEXCEPT { + return x <= basic_string_view(y); + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator<=(const charT * x, + basic_string_view y) BOOST_NOEXCEPT { + return basic_string_view(x) <= y; + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view x, + const std::basic_string & y) BOOST_NOEXCEPT { + return x >= basic_string_view(y); + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator>=(const std::basic_string & x, + basic_string_view y) BOOST_NOEXCEPT { + return basic_string_view(x) >= y; + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view x, + const charT * y) BOOST_NOEXCEPT { + return x >= basic_string_view(y); + } + + template + inline BOOST_CXX14_CONSTEXPR bool operator>=(const charT * x, + basic_string_view y) BOOST_NOEXCEPT { + return basic_string_view(x) >= y; + } + + // Inserter + template + inline std::basic_ostream& + operator<<(std::basic_ostream& os, + const basic_string_view& str) { + return boost::io::ostream_put(os, str.data(), str.size()); + } + +#if 0 + // numeric conversions + // + // These are short-term implementations. + // In a production environment, I would rather avoid the copying. + // + inline int stoi (string_view str, size_t* idx=0, int base=10) { + return std::stoi ( std::string(str), idx, base ); + } + + inline long stol (string_view str, size_t* idx=0, int base=10) { + return std::stol ( std::string(str), idx, base ); + } + + inline unsigned long stoul (string_view str, size_t* idx=0, int base=10) { + return std::stoul ( std::string(str), idx, base ); + } + + inline long long stoll (string_view str, size_t* idx=0, int base=10) { + return std::stoll ( std::string(str), idx, base ); + } + + inline unsigned long long stoull (string_view str, size_t* idx=0, int base=10) { + return std::stoull ( std::string(str), idx, base ); + } + + inline float stof (string_view str, size_t* idx=0) { + return std::stof ( std::string(str), idx ); + } + + inline double stod (string_view str, size_t* idx=0) { + return std::stod ( std::string(str), idx ); + } + + inline long double stold (string_view str, size_t* idx=0) { + return std::stold ( std::string(str), idx ); + } + + inline int stoi (wstring_view str, size_t* idx=0, int base=10) { + return std::stoi ( std::wstring(str), idx, base ); + } + + inline long stol (wstring_view str, size_t* idx=0, int base=10) { + return std::stol ( std::wstring(str), idx, base ); + } + + inline unsigned long stoul (wstring_view str, size_t* idx=0, int base=10) { + return std::stoul ( std::wstring(str), idx, base ); + } + + inline long long stoll (wstring_view str, size_t* idx=0, int base=10) { + return std::stoll ( std::wstring(str), idx, base ); + } + + inline unsigned long long stoull (wstring_view str, size_t* idx=0, int base=10) { + return std::stoull ( std::wstring(str), idx, base ); + } + + inline float stof (wstring_view str, size_t* idx=0) { + return std::stof ( std::wstring(str), idx ); + } + + inline double stod (wstring_view str, size_t* idx=0) { + return std::stod ( std::wstring(str), idx ); + } + + inline long double stold (wstring_view str, size_t* idx=0) { + return std::stold ( std::wstring(str), idx ); + } +#endif + + // Forward declaration of Boost.ContainerHash function + template std::size_t hash_range(It, It); + + template + std::size_t hash_value(basic_string_view s) { + return boost::hash_range(s.begin(), s.end()); + } +} + +#if 0 +namespace std { + // Hashing + template<> struct hash; + template<> struct hash; + template<> struct hash; + template<> struct hash; +} +#endif + +#endif diff --git a/libs/utility/include/boost/utility/string_view_fwd.hpp b/libs/utility/include/boost/utility/string_view_fwd.hpp new file mode 100644 index 00000000..dbda0de4 --- /dev/null +++ b/libs/utility/include/boost/utility/string_view_fwd.hpp @@ -0,0 +1,39 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org + + Based on the StringRef implementation in LLVM (http://llvm.org) and + N3422 by Jeffrey Yasskin + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html + Updated July 2015 to reflect the Library Fundamentals TS + http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html + +*/ + +#ifndef BOOST_STRING_VIEW_FWD_HPP +#define BOOST_STRING_VIEW_FWD_HPP + +#include +#include + +namespace boost { + + template > class basic_string_view; + typedef basic_string_view > string_view; + typedef basic_string_view > wstring_view; + +#ifndef BOOST_NO_CXX11_CHAR16_T + typedef basic_string_view > u16string_view; +#endif + +#ifndef BOOST_NO_CXX11_CHAR32_T + typedef basic_string_view > u32string_view; +#endif + +} + +#endif diff --git a/libs/utility/include/boost/utility/typed_in_place_factory.hpp b/libs/utility/include/boost/utility/typed_in_place_factory.hpp new file mode 100644 index 00000000..52a70612 --- /dev/null +++ b/libs/utility/include/boost/utility/typed_in_place_factory.hpp @@ -0,0 +1,82 @@ +// Copyright (C) 2003, Fernando Luis Cacciola Carballal. +// Copyright (C) 2007, Tobias Schwinger. +// +// Use, modification, and distribution is subject to 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) +// +// See http://www.boost.org/libs/optional for documentation. +// +// You are welcome to contact the author at: +// fernando_cacciola@hotmail.com +// +#ifndef BOOST_UTILITY_TYPED_INPLACE_FACTORY_04APR2007_HPP +#ifndef BOOST_PP_IS_ITERATING + +#include + +namespace boost { + +class typed_in_place_factory_base {} ; + +#ifndef BOOST_UTILITY_DOCS +#define BOOST_PP_ITERATION_LIMITS (0, BOOST_MAX_INPLACE_FACTORY_ARITY) +#define BOOST_PP_FILENAME_1 +#endif // BOOST_UTILITY_DOCS + +#include BOOST_PP_ITERATE() +} // namespace boost + +#include + +#ifndef BOOST_UTILITY_DOCS +#define BOOST_UTILITY_TYPED_INPLACE_FACTORY_04APR2007_HPP +#endif // BOOST_UTILITY_DOCS + +#else +#define N BOOST_PP_ITERATION() + +template< class T BOOST_PP_ENUM_TRAILING_PARAMS(N,class A) > +class BOOST_PP_CAT(typed_in_place_factory,N) + : + public typed_in_place_factory_base +{ +public: + + typedef T value_type; + + explicit BOOST_PP_CAT(typed_in_place_factory,N) + ( BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& a) ) +#if N > 0 + : BOOST_PP_ENUM(N, BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT, _) +#endif + {} + + void* apply (void* address) const + { + return new(address) T( BOOST_PP_ENUM_PARAMS(N, m_a) ); + } + + void* apply (void* address, std::size_t n) const + { + for(void* next = address = this->apply(address); !! --n;) + this->apply(next = static_cast(next) + sizeof(T)); + return address; + } + + BOOST_PP_REPEAT(N, BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL, _) +}; + +template< class T BOOST_PP_ENUM_TRAILING_PARAMS(N, class A) > +inline BOOST_PP_CAT(typed_in_place_factory,N)< + T BOOST_PP_ENUM_TRAILING_PARAMS(N, A) > +in_place( BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& a) ) +{ + return BOOST_PP_CAT(typed_in_place_factory,N)< + T BOOST_PP_ENUM_TRAILING_PARAMS(N, A) >( BOOST_PP_ENUM_PARAMS(N, a) ); +} + +#undef N +#endif +#endif + diff --git a/libs/utility/include/boost/utility/value_init.hpp b/libs/utility/include/boost/utility/value_init.hpp new file mode 100644 index 00000000..c0b95323 --- /dev/null +++ b/libs/utility/include/boost/utility/value_init.hpp @@ -0,0 +1,247 @@ +// (C) Copyright 2002-2008, Fernando Luis Cacciola Carballal. +// Copyright 2020 Peter Dimov +// +// 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) +// +// 21 Ago 2002 (Created) Fernando Cacciola +// 24 Dec 2007 (Refactored and worked around various compiler bugs) Fernando Cacciola, Niels Dekker +// 23 May 2008 (Fixed operator= const issue, added initialized_value) Niels Dekker, Fernando Cacciola +// 21 Ago 2008 (Added swap) Niels Dekker, Fernando Cacciola +// 20 Feb 2009 (Fixed logical const-ness issues) Niels Dekker, Fernando Cacciola +// 03 Apr 2010 (Added initialized, suggested by Jeffrey Hellrung, fixing #3472) Niels Dekker +// 30 May 2010 (Made memset call conditional, fixing #3869) Niels Dekker +// +#ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP +#define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP + +// Note: The implementation of boost::value_initialized had to deal with the +// fact that various compilers haven't fully implemented value-initialization. +// The constructor of boost::value_initialized works around these compiler +// issues, by clearing the bytes of T, before constructing the T object it +// contains. More details on these issues are at libs/utility/value_init.htm + +#include // For BOOST_NO_COMPLETE_VALUE_INITIALIZATION. +#include +#include +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +// It is safe to ignore the following warning from MSVC 7.1 or higher: +// "warning C4351: new behavior: elements of array will be default initialized" +#pragma warning(disable: 4351) +// It is safe to ignore the following MSVC warning, which may pop up when T is +// a const type: "warning C4512: assignment operator could not be generated". +#pragma warning(disable: 4512) +#endif + +#ifndef BOOST_UTILITY_DOCS + +#ifdef BOOST_NO_COMPLETE_VALUE_INITIALIZATION + // Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED + // suggests that a workaround should be applied, because of compiler issues + // regarding value-initialization. + #define BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED +#endif + +// Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND +// switches the value-initialization workaround either on or off. +#ifndef BOOST_DETAIL_VALUE_INIT_WORKAROUND + #ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED + #define BOOST_DETAIL_VALUE_INIT_WORKAROUND 1 + #else + #define BOOST_DETAIL_VALUE_INIT_WORKAROUND 0 + #endif +#endif + +#endif // BOOST_UTILITY_DOCS + +namespace boost { + +namespace detail { + + struct zero_init + { + zero_init() + { + } + + zero_init( void * p, std::size_t n ) + { + std::memset( p, 0, n ); + } + }; + +} // namespace detail + +template +class initialized +#if BOOST_DETAIL_VALUE_INIT_WORKAROUND + : detail::zero_init +#endif +{ + private: + + T data_; + + public : + + BOOST_GPU_ENABLED + initialized(): +#if BOOST_DETAIL_VALUE_INIT_WORKAROUND + zero_init( &const_cast< char& >( reinterpret_cast( data_ ) ), sizeof( data_ ) ), +#endif + data_() + { + } + + BOOST_GPU_ENABLED + explicit initialized(T const & arg): data_( arg ) + { + } + + BOOST_GPU_ENABLED + T const & data() const + { + return data_; + } + + BOOST_GPU_ENABLED + T& data() + { + return data_; + } + + BOOST_GPU_ENABLED + void swap(initialized & arg) + { + ::boost::core::invoke_swap( this->data(), arg.data() ); + } + + BOOST_GPU_ENABLED + operator T const &() const + { + return data_; + } + + BOOST_GPU_ENABLED + operator T&() + { + return data_; + } + +} ; + +template +BOOST_GPU_ENABLED +T const& get ( initialized const& x ) +{ + return x.data() ; +} + +template +BOOST_GPU_ENABLED +T& get ( initialized& x ) +{ + return x.data() ; +} + +template +BOOST_GPU_ENABLED +void swap ( initialized & lhs, initialized & rhs ) +{ + lhs.swap(rhs) ; +} + +template +class value_initialized +{ + private : + + // initialized does value-initialization by default. + initialized m_data; + + public : + + BOOST_GPU_ENABLED + value_initialized() + : + m_data() + { } + + BOOST_GPU_ENABLED + T const & data() const + { + return m_data.data(); + } + + BOOST_GPU_ENABLED + T& data() + { + return m_data.data(); + } + + BOOST_GPU_ENABLED + void swap(value_initialized & arg) + { + m_data.swap(arg.m_data); + } + + BOOST_GPU_ENABLED + operator T const &() const + { + return m_data; + } + + BOOST_GPU_ENABLED + operator T&() + { + return m_data; + } +} ; + + +template +BOOST_GPU_ENABLED +T const& get ( value_initialized const& x ) +{ + return x.data() ; +} + +template +BOOST_GPU_ENABLED +T& get ( value_initialized& x ) +{ + return x.data() ; +} + +template +BOOST_GPU_ENABLED +void swap ( value_initialized & lhs, value_initialized & rhs ) +{ + lhs.swap(rhs) ; +} + + +class initialized_value_t +{ + public : + + template BOOST_GPU_ENABLED operator T() const + { + return initialized().data(); + } +}; + +initialized_value_t const initialized_value = {} ; + + +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif diff --git a/libs/utility/index.html b/libs/utility/index.html new file mode 100644 index 00000000..3f014704 --- /dev/null +++ b/libs/utility/index.html @@ -0,0 +1,19 @@ + + + Boost.Utility + + + +Automatic redirection failed, please go to +./doc/html/index.html +
+ + Boost.Utility
+
+ 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/libs/utility/iterator_adaptors.htm b/libs/utility/iterator_adaptors.htm new file mode 100644 index 00000000..78f2d24d --- /dev/null +++ b/libs/utility/iterator_adaptors.htm @@ -0,0 +1,19 @@ + + + Boost.Iterator + + + +Automatic redirection failed, please go to +../iterator/doc/index.html +
+ + Boost.Iterator
+
+ 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/libs/utility/meta/libraries.json b/libs/utility/meta/libraries.json new file mode 100644 index 00000000..f30e1868 --- /dev/null +++ b/libs/utility/meta/libraries.json @@ -0,0 +1,133 @@ +[ + { + "key": "utility", + "name": "Utility", + "authors": [ + "Dave Abrahams and others" + ], + "description": "Various utilities, such as base-from-member idiom and binary literals in C++03.", + "documentation": "utility.htm", + "category": [ + "Miscellaneous", + "Patterns" + ], + "cxxstd": "03" + }, + { + "key": "utility/call_traits", + "name": "Call Traits", + "authors": [ + "John Maddock, Howard Hinnant, et al" + ], + "description": "Defines types for passing parameters.", + "documentation": "call_traits.htm", + "category": [ + "Generic" + ], + "cxxstd": "03" + }, + { + "key": "utility/compressed_pair", + "name": "Compressed Pair", + "authors": [ + "John Maddock, Howard Hinnant, et al" + ], + "description": "A pair class with empty member optimization.", + "documentation": "compressed_pair.htm", + "category": [ + "Data", + "Patterns" + ], + "cxxstd": "03" + }, + { + "key": "utility/identity_type", + "name": "Identity Type", + "authors": [ + "Lorenzo Caminiti" + ], + "description": "Wrap types within round parenthesis so they can always be passed as macro parameters.", + "documentation": "identity_type/", + "category": [ + "Preprocessor" + ], + "maintainers": [ + "Lorenzo Caminiti " + ], + "cxxstd": "03" + }, + { + "key": "utility/in_place_factories", + "name": "In Place Factory, Typed In Place Factory", + "authors": [ + "Fernando Cacciola" + ], + "description": "Generic in-place construction of contained objects with a variadic argument-list.", + "documentation": "in_place_factories.html", + "category": [ + "Generic" + ], + "cxxstd": "03" + }, + { + "key": "utility/operators", + "name": "Operators", + "authors": [ + "Dave Abrahams", + "Jeremy Siek" + ], + "description": "Templates to simplify operator definition in arithmetic classes and iterators.", + "documentation": "operators.htm", + "category": [ + "Generic", + "Iterators", + "Math" + ], + "maintainers": [ + "Daniel Frey " + ], + "cxxstd": "03" + }, + { + "key": "utility/result_of", + "name": "Result Of", + "description": "Determines the type of a function call expression.", + "documentation": "doc/html/utility/utilities/result_of.html", + "category": [ + "Function-objects" + ], + "authors": "", + "maintainers": [ + "Daniel Walker " + ], + "cxxstd": "03" + }, + { + "key": "utility/string_view", + "name": "String View", + "description": "String view templates.", + "documentation": "doc/html/utility/utilities/string_view.html", + "category": [ + "Containers", + "String" + ], + "authors": "Marshall Clow", + "maintainers": [ + "Marshall Clow " + ], + "cxxstd": "03" + }, + { + "key": "utility/value_initialized", + "name": "Value Initialized", + "authors": [ + "Fernando Cacciola" + ], + "description": "Wrapper for uniform-syntax value initialization, based on the original idea of David Abrahams.", + "documentation": "value_init.htm", + "category": [ + "Miscellaneous" + ], + "cxxstd": "03" + } +] diff --git a/libs/utility/operators.htm b/libs/utility/operators.htm new file mode 100644 index 00000000..d303fe1a --- /dev/null +++ b/libs/utility/operators.htm @@ -0,0 +1,19 @@ + + + Boost.Operators + + + +Automatic redirection failed, please go to +./doc/html/utility/utilities/operators.html +
+ + Boost.Operators
+
+ 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/libs/utility/sublibs b/libs/utility/sublibs new file mode 100644 index 00000000..721d7c4a --- /dev/null +++ b/libs/utility/sublibs @@ -0,0 +1 @@ +The existance of this file tells the regression reporting programs that the directory contains sub-directories which are libraries. \ No newline at end of file diff --git a/libs/utility/test/Jamfile.v2 b/libs/utility/test/Jamfile.v2 new file mode 100644 index 00000000..fdaef727 --- /dev/null +++ b/libs/utility/test/Jamfile.v2 @@ -0,0 +1,47 @@ +# Copyright David Abrahams 2003. + +# Distributed under the Boost Software License, Version 1.0. +# See http://www.boost.org/LICENSE_1_0.txt + +# For more information, see http://www.boost.org/ + +# bring in rules for testing +import testing ; + +run base_from_member_test.cpp ; +run base_from_member_ref_test.cpp ; + +run binary_test.cpp ; + +run call_traits_test.cpp : -u ; + +run compressed_pair_test.cpp ; +run compressed_pair_final_test.cpp ; + +run iterators_test.cpp ; + +run operators_test.cpp ; +compile operators_constexpr_test.cpp ; + +compile result_of_test.cpp ; + +# compile-fail string_ref_from_rvalue.cpp ; +run string_ref_test1.cpp ; +run string_ref_test2.cpp ; +run string_ref_test_io.cpp ; +# compile-fail string_view_from_rvalue.cpp ; +compile string_view_constexpr_test1.cpp ; +run string_view_test1.cpp ; +run string_view_test2.cpp ; +run string_view_test_io.cpp ; + +run value_init_test.cpp ; +run value_init_test2.cpp ; +run value_init_test3.cpp ; +run value_init_workaround_test.cpp ; +run initialized_test.cpp ; +compile-fail value_init_test_fail1.cpp ; +compile-fail value_init_test_fail2.cpp ; +compile-fail value_init_test_fail3.cpp ; +compile-fail initialized_test_fail1.cpp ; +compile-fail initialized_test_fail2.cpp ; diff --git a/libs/utility/test/base_from_member_ref_test.cpp b/libs/utility/test/base_from_member_ref_test.cpp new file mode 100644 index 00000000..52f9b870 --- /dev/null +++ b/libs/utility/test/base_from_member_ref_test.cpp @@ -0,0 +1,29 @@ +// +// Test that a base_from_member can be properly constructed +// +// Copyright 2014 Agustin Berge +// +// 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 +// + +#include + +#include + +struct foo : boost::base_from_member +{ + explicit foo(int& ref) : boost::base_from_member(ref) + { + BOOST_TEST(&member == &ref); + } +}; + +int main() +{ + int i = 0; + foo f(i); + + return boost::report_errors(); +} diff --git a/libs/utility/test/base_from_member_test.cpp b/libs/utility/test/base_from_member_test.cpp new file mode 100644 index 00000000..685c6387 --- /dev/null +++ b/libs/utility/test/base_from_member_test.cpp @@ -0,0 +1,593 @@ +// Boost test program for base-from-member class templates -----------------// + +// Copyright 2001, 2003 Daryle Walker. Use, modification, and distribution are +// subject to the Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or a copy at .) + +// See for the library's home page. + +// Revision History +// 14 Jun 2003 Adjusted code for Boost.Test changes (Daryle Walker) +// 29 Aug 2001 Initial Version (Daryle Walker) + +#include + +#include // for BOOST_NO_MEMBER_TEMPLATES +#include // for boost::noncopyable + +#include // for boost::base_from_member + +#include // for std::less +#include // for std::cout (std::ostream, std::endl indirectly) +#include // for std::set +#include // for std::type_info +#include // for std::pair, std::make_pair +#include // for std::vector + + +// Control if extra information is printed +#ifndef CONTROL_EXTRA_PRINTING +#define CONTROL_EXTRA_PRINTING 1 +#endif + + +// A (sub)object can be identified by its memory location and its type. +// Both are needed since an object can start at the same place as its +// first base class subobject and/or contained subobject. +typedef std::pair< void *, std::type_info const * > object_id; + +// Object IDs need to be printed +std::ostream & operator <<( std::ostream &os, object_id const &oi ); + +// A way to generate an object ID +template < typename T > + object_id identify( T &obj ); + +// A custom comparison type is needed +struct object_id_compare +{ + bool operator ()( object_id const &a, object_id const &b ) const; + +}; // object_id_compare + +// A singleton of this type coordinates the acknowledgements +// of objects being created and used. +class object_registrar + : private boost::noncopyable +{ +public: + + #ifndef BOOST_NO_MEMBER_TEMPLATES + template < typename T > + void register_object( T &obj ) + { this->register_object_imp( identify(obj) ); } + template < typename T, typename U > + void register_use( T &owner, U &owned ) + { this->register_use_imp( identify(owner), identify(owned) ); } + template < typename T, typename U > + void unregister_use( T &owner, U &owned ) + { this->unregister_use_imp( identify(owner), identify(owned) ); } + template < typename T > + void unregister_object( T &obj ) + { this->unregister_object_imp( identify(obj) ); } + #endif + + void register_object_imp( object_id obj ); + void register_use_imp( object_id owner, object_id owned ); + void unregister_use_imp( object_id owner, object_id owned ); + void unregister_object_imp( object_id obj ); + + typedef std::set set_type; + + typedef std::vector error_record_type; + typedef std::vector< std::pair > error_pair_type; + + set_type db_; + + error_pair_type defrauders_in_, defrauders_out_; + error_record_type overeager_, overkilled_; + +}; // object_registrar + +// A sample type to be used by containing types +class base_or_member +{ +public: + explicit base_or_member( int x = 1, double y = -0.25 ); + ~base_or_member(); + +}; // base_or_member + +// A sample type that uses base_or_member, used +// as a base for the main demonstration classes +class base_class +{ +public: + explicit base_class( base_or_member &x, base_or_member *y = 0, + base_or_member *z = 0 ); + + ~base_class(); + +private: + base_or_member *x_, *y_, *z_; + +}; // base_class + +// This bad class demonstrates the direct method of a base class needing +// to be initialized by a member. This is improper since the member +// isn't initialized until after the base class. +class bad_class + : public base_class +{ +public: + bad_class(); + ~bad_class(); + +private: + base_or_member x_; + +}; // bad_class + +// The first good class demonstrates the correct way to initialize a +// base class with a member. The member is changed to another base +// class, one that is initialized before the base that needs it. +class good_class_1 + : private boost::base_from_member + , public base_class +{ + typedef boost::base_from_member pbase_type; + typedef base_class base_type; + +public: + good_class_1(); + ~good_class_1(); + +}; // good_class_1 + +// The second good class also demonstrates the correct way to initialize +// base classes with other subobjects. This class uses the other helpers +// in the library, and shows the technique of using two base subobjects +// of the "same" type. +class good_class_2 + : private boost::base_from_member + , private boost::base_from_member + , private boost::base_from_member + , public base_class +{ + typedef boost::base_from_member pbase_type0; + typedef boost::base_from_member pbase_type1; + typedef boost::base_from_member pbase_type2; + typedef base_class base_type; + +public: + good_class_2(); + ~good_class_2(); + +}; // good_class_2 + +// Declare/define the single object registrar +object_registrar obj_reg; + + +// Main functionality +int +main() +{ + BOOST_TEST( obj_reg.db_.empty() ); + BOOST_TEST( obj_reg.defrauders_in_.empty() ); + BOOST_TEST( obj_reg.defrauders_out_.empty() ); + BOOST_TEST( obj_reg.overeager_.empty() ); + BOOST_TEST( obj_reg.overkilled_.empty() ); + + // Make a separate block to examine pre- and post-effects + { + using std::cout; + using std::endl; + + bad_class bc; + BOOST_TEST( obj_reg.db_.size() == 3 ); + BOOST_TEST( obj_reg.defrauders_in_.size() == 1 ); + + good_class_1 gc1; + BOOST_TEST( obj_reg.db_.size() == 6 ); + BOOST_TEST( obj_reg.defrauders_in_.size() == 1 ); + + good_class_2 gc2; + BOOST_TEST( obj_reg.db_.size() == 11 ); + BOOST_TEST( obj_reg.defrauders_in_.size() == 1 ); + + BOOST_TEST( obj_reg.defrauders_out_.empty() ); + BOOST_TEST( obj_reg.overeager_.empty() ); + BOOST_TEST( obj_reg.overkilled_.empty() ); + + // Getting the addresses of the objects ensure + // that they're used, and not optimized away. + cout << "Object 'bc' is at " << &bc << '.' << endl; + cout << "Object 'gc1' is at " << &gc1 << '.' << endl; + cout << "Object 'gc2' is at " << &gc2 << '.' << endl; + } + + BOOST_TEST( obj_reg.db_.empty() ); + BOOST_TEST( obj_reg.defrauders_in_.size() == 1 ); + BOOST_TEST( obj_reg.defrauders_out_.size() == 1 ); + BOOST_TEST( obj_reg.overeager_.empty() ); + BOOST_TEST( obj_reg.overkilled_.empty() ); + + return boost::report_errors(); +} + + +// Print an object's ID +std::ostream & +operator << +( + std::ostream & os, + object_id const & oi +) +{ + // I had an std::ostringstream to help, but I did not need it since + // the program never screws around with formatting. Worse, using + // std::ostringstream is an issue with some compilers. + + return os << '[' << ( oi.second ? oi.second->name() : "NOTHING" ) + << " at " << oi.first << ']'; +} + +// Get an object ID given an object +template < typename T > +inline +object_id +identify +( + T & obj +) +{ + return std::make_pair( static_cast(&obj), &(typeid( obj )) ); +} + +// Compare two object IDs +bool +object_id_compare::operator () +( + object_id const & a, + object_id const & b +) const +{ + std::less vp_cmp; + if ( vp_cmp(a.first, b.first) ) + { + return true; + } + else if ( vp_cmp(b.first, a.first) ) + { + return false; + } + else + { + // object pointers are equal, compare the types + if ( a.second == b.second ) + { + return false; + } + else if ( !a.second ) + { + return true; // NULL preceeds anything else + } + else if ( !b.second ) + { + return false; // NULL preceeds anything else + } + else + { + return a.second->before( *b.second ) != 0; + } + } +} + +// Let an object register its existence +void +object_registrar::register_object_imp +( + object_id obj +) +{ + if ( db_.count(obj) <= 0 ) + { + db_.insert( obj ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "Registered " << obj << '.' << std::endl; + #endif + } + else + { + overeager_.push_back( obj ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "Attempted to register a non-existant " << obj + << '.' << std::endl; + #endif + } +} + +// Let an object register its use of another object +void +object_registrar::register_use_imp +( + object_id owner, + object_id owned +) +{ + if ( db_.count(owned) > 0 ) + { + // We don't care to record usage registrations + } + else + { + defrauders_in_.push_back( std::make_pair(owner, owned) ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "Attempted to own a non-existant " << owned + << " by " << owner << '.' << std::endl; + #endif + } +} + +// Let an object un-register its use of another object +void +object_registrar::unregister_use_imp +( + object_id owner, + object_id owned +) +{ + if ( db_.count(owned) > 0 ) + { + // We don't care to record usage un-registrations + } + else + { + defrauders_out_.push_back( std::make_pair(owner, owned) ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "Attempted to disown a non-existant " << owned + << " by " << owner << '.' << std::endl; + #endif + } +} + +// Let an object un-register its existence +void +object_registrar::unregister_object_imp +( + object_id obj +) +{ + set_type::iterator const i = db_.find( obj ); + + if ( i != db_.end() ) + { + db_.erase( i ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "Unregistered " << obj << '.' << std::endl; + #endif + } + else + { + overkilled_.push_back( obj ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "Attempted to unregister a non-existant " << obj + << '.' << std::endl; + #endif + } +} + +// Macros to abstract the registration of objects +#ifndef BOOST_NO_MEMBER_TEMPLATES +#define PRIVATE_REGISTER_BIRTH(o) obj_reg.register_object( (o) ) +#define PRIVATE_REGISTER_DEATH(o) obj_reg.unregister_object( (o) ) +#define PRIVATE_REGISTER_USE(o, w) obj_reg.register_use( (o), (w) ) +#define PRIVATE_UNREGISTER_USE(o, w) obj_reg.unregister_use( (o), (w) ) +#else +#define PRIVATE_REGISTER_BIRTH(o) obj_reg.register_object_imp( \ + identify((o)) ) +#define PRIVATE_REGISTER_DEATH(o) obj_reg.unregister_object_imp( \ + identify((o)) ) +#define PRIVATE_REGISTER_USE(o, w) obj_reg.register_use_imp( identify((o)), \ + identify((w)) ) +#define PRIVATE_UNREGISTER_USE(o, w) obj_reg.unregister_use_imp( \ + identify((o)), identify((w)) ) +#endif + +// Create a base_or_member, with arguments to simulate member initializations +base_or_member::base_or_member +( + int x, // = 1 + double y // = -0.25 +) +{ + PRIVATE_REGISTER_BIRTH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy x-factor is " << x << " and my y-factor is " << y + << '.' << std::endl; + #endif +} + +// Destroy a base_or_member +inline +base_or_member::~base_or_member +( +) +{ + PRIVATE_REGISTER_DEATH( *this ); +} + +// Create a base_class, registering any objects used +base_class::base_class +( + base_or_member & x, + base_or_member * y, // = 0 + base_or_member * z // = 0 +) + : x_( &x ), y_( y ), z_( z ) +{ + PRIVATE_REGISTER_BIRTH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy x-factor is " << x_; + #endif + + PRIVATE_REGISTER_USE( *this, *x_ ); + + if ( y_ ) + { + #if CONTROL_EXTRA_PRINTING + std::cout << ", my y-factor is " << y_; + #endif + + PRIVATE_REGISTER_USE( *this, *y_ ); + } + + if ( z_ ) + { + #if CONTROL_EXTRA_PRINTING + std::cout << ", my z-factor is " << z_; + #endif + + PRIVATE_REGISTER_USE( *this, *z_ ); + } + + #if CONTROL_EXTRA_PRINTING + std::cout << '.' << std::endl; + #endif +} + +// Destroy a base_class, unregistering the objects it uses +base_class::~base_class +( +) +{ + PRIVATE_REGISTER_DEATH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy x-factor was " << x_; + #endif + + PRIVATE_UNREGISTER_USE( *this, *x_ ); + + if ( y_ ) + { + #if CONTROL_EXTRA_PRINTING + std::cout << ", my y-factor was " << y_; + #endif + + PRIVATE_UNREGISTER_USE( *this, *y_ ); + } + + if ( z_ ) + { + #if CONTROL_EXTRA_PRINTING + std::cout << ", my z-factor was " << z_; + #endif + + PRIVATE_UNREGISTER_USE( *this, *z_ ); + } + + #if CONTROL_EXTRA_PRINTING + std::cout << '.' << std::endl; + #endif +} + +// Create a bad_class, noting the improper construction order +bad_class::bad_class +( +) + : x_( -7, 16.75 ), base_class( x_ ) // this order doesn't matter +{ + PRIVATE_REGISTER_BIRTH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy factor is at " << &x_ + << " and my base is at " << static_cast(this) << '.' + << std::endl; + #endif +} + +// Destroy a bad_class, noting the improper destruction order +bad_class::~bad_class +( +) +{ + PRIVATE_REGISTER_DEATH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy factor was at " << &x_ + << " and my base was at " << static_cast(this) + << '.' << std::endl; + #endif +} + +// Create a good_class_1, noting the proper construction order +good_class_1::good_class_1 +( +) + : pbase_type( 8 ), base_type( member ) +{ + PRIVATE_REGISTER_BIRTH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy factor is at " << &member + << " and my base is at " << static_cast(this) << '.' + << std::endl; + #endif +} + +// Destroy a good_class_1, noting the proper destruction order +good_class_1::~good_class_1 +( +) +{ + PRIVATE_REGISTER_DEATH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy factor was at " << &member + << " and my base was at " << static_cast(this) + << '.' << std::endl; + #endif +} + +// Create a good_class_2, noting the proper construction order +good_class_2::good_class_2 +( +) + : pbase_type0(), pbase_type1(-16, 0.125), pbase_type2(2, -3) + , base_type( pbase_type1::member, &this->pbase_type0::member, + &this->pbase_type2::member ) +{ + PRIVATE_REGISTER_BIRTH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy factors are at " << &this->pbase_type0::member + << ", " << &this->pbase_type1::member << ", " + << &this->pbase_type2::member << ", and my base is at " + << static_cast(this) << '.' << std::endl; + #endif +} + +// Destroy a good_class_2, noting the proper destruction order +good_class_2::~good_class_2 +( +) +{ + PRIVATE_REGISTER_DEATH( *this ); + + #if CONTROL_EXTRA_PRINTING + std::cout << "\tMy factors were at " << &this->pbase_type0::member + << ", " << &this->pbase_type1::member << ", " + << &this->pbase_type2::member << ", and my base was at " + << static_cast(this) << '.' << std::endl; + #endif +} diff --git a/libs/utility/test/binary_test.cpp b/libs/utility/test/binary_test.cpp new file mode 100644 index 00000000..f39dc08f --- /dev/null +++ b/libs/utility/test/binary_test.cpp @@ -0,0 +1,647 @@ +/*============================================================================= + Copyright (c) 2006, 2007 Matthew Calabrese + + Use, modification and distribution is subject to 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) +==============================================================================*/ + +#include +#include +#include +#include + +#ifdef BOOST_MSVC +#pragma warning(disable:4996) // warning C4996: 'std::equal': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators' +#endif + +/* +Note: This file tests every single valid bit-grouping on its own, and some + random combinations of bit-groupings. +*/ + +std::size_t const num_random_test_values = 32; + +// Note: These hex values should all correspond with the binary array below +unsigned int const random_unsigned_ints_hex[num_random_test_values] + = { 0x0103u, 0x77ebu, 0x5f36u, 0x1f18u, 0xc530u, 0xa73au, 0xd6f8u, 0x0919u + , 0xfbb0u, 0x3e7cu, 0xd0e9u, 0x22c8u, 0x724eu, 0x14fau, 0xd98eu, 0x40b5 + , 0xeba0u, 0xfe50u, 0x688au, 0x1b05u, 0x5f9cu, 0xe4fcu, 0xa7b8u, 0xd3acu + , 0x1dddu, 0xbf04u, 0x8352u, 0xe89cu, 0x7506u, 0xe767u, 0xf489u, 0xe167 + }; + +unsigned int const random_unsigned_ints_binary[num_random_test_values] + = { BOOST_BINARY( 0 00010000 0011 ), BOOST_BINARY( 0 11101 1111 101011 ) + , BOOST_BINARY( 010111 1100110 1 1 0 ), BOOST_BINARY( 000 1 11110 00 11000 ) + , BOOST_BINARY( 110 001010 0110 000 ), BOOST_BINARY( 1010 01110011 1010 ) + , BOOST_BINARY( 11 010 1 101111 1000 ), BOOST_BINARY( 0000 100100 0110 01 ) + , BOOST_BINARY( 1111 101110 11 0000 ), BOOST_BINARY( 00111110 01111100 ) + , BOOST_BINARY( 11 010 000111 01001 ), BOOST_BINARY( 00100 010110 01000 ) + , BOOST_BINARY( 01 11001001 001110 ), BOOST_BINARY( 0010 1001111 1010 ) + , BOOST_BINARY( 1101 1 00110 0 01110 ), BOOST_BINARY( 100 000 01011010 1 ) + , BOOST_BINARY( 11 1010 1110 1000 00 ), BOOST_BINARY( 11111 110010 10000 ) + , BOOST_BINARY( 01101 00010 001010 ), BOOST_BINARY( 000 11011 000001 01 ) + , BOOST_BINARY( 01 01111 1100111 00 ), BOOST_BINARY( 1 110010 0111111 00 ) + , BOOST_BINARY( 101 0011 11 01110 00 ), BOOST_BINARY( 110100 1 110101 100 ) + , BOOST_BINARY( 00 1110111 011 101 ), BOOST_BINARY( 1011 1111 00000 100 ) + , BOOST_BINARY( 1000 00110 101 0010 ), BOOST_BINARY( 1110 10001 001110 0 ) + , BOOST_BINARY( 011 1010100 000 110 ), BOOST_BINARY( 1110 0111 01100 111 ) + , BOOST_BINARY( 11110 10010 001001 ), BOOST_BINARY( 11 1000010 1100 111 ) + }; + +unsigned int const unsigned_ints_1_bit[2] = +{ BOOST_BINARY( 0 ) +, BOOST_BINARY( 1 ) +}; + +unsigned int const unsigned_ints_2_bits[4] = +{ BOOST_BINARY( 00 ) +, BOOST_BINARY( 01 ) +, BOOST_BINARY( 10 ) +, BOOST_BINARY( 11 ) +}; + +unsigned int const unsigned_ints_3_bits[8] = +{ BOOST_BINARY( 000 ) +, BOOST_BINARY( 001 ) +, BOOST_BINARY( 010 ) +, BOOST_BINARY( 011 ) +, BOOST_BINARY( 100 ) +, BOOST_BINARY( 101 ) +, BOOST_BINARY( 110 ) +, BOOST_BINARY( 111 ) +}; + +unsigned int const unsigned_ints_4_bits[16] = +{ BOOST_BINARY( 0000 ) +, BOOST_BINARY( 0001 ) +, BOOST_BINARY( 0010 ) +, BOOST_BINARY( 0011 ) +, BOOST_BINARY( 0100 ) +, BOOST_BINARY( 0101 ) +, BOOST_BINARY( 0110 ) +, BOOST_BINARY( 0111 ) +, BOOST_BINARY( 1000 ) +, BOOST_BINARY( 1001 ) +, BOOST_BINARY( 1010 ) +, BOOST_BINARY( 1011 ) +, BOOST_BINARY( 1100 ) +, BOOST_BINARY( 1101 ) +, BOOST_BINARY( 1110 ) +, BOOST_BINARY( 1111 ) +}; + +unsigned int const unsigned_ints_5_bits[32] = +{ BOOST_BINARY( 00000 ) +, BOOST_BINARY( 00001 ) +, BOOST_BINARY( 00010 ) +, BOOST_BINARY( 00011 ) +, BOOST_BINARY( 00100 ) +, BOOST_BINARY( 00101 ) +, BOOST_BINARY( 00110 ) +, BOOST_BINARY( 00111 ) +, BOOST_BINARY( 01000 ) +, BOOST_BINARY( 01001 ) +, BOOST_BINARY( 01010 ) +, BOOST_BINARY( 01011 ) +, BOOST_BINARY( 01100 ) +, BOOST_BINARY( 01101 ) +, BOOST_BINARY( 01110 ) +, BOOST_BINARY( 01111 ) +, BOOST_BINARY( 10000 ) +, BOOST_BINARY( 10001 ) +, BOOST_BINARY( 10010 ) +, BOOST_BINARY( 10011 ) +, BOOST_BINARY( 10100 ) +, BOOST_BINARY( 10101 ) +, BOOST_BINARY( 10110 ) +, BOOST_BINARY( 10111 ) +, BOOST_BINARY( 11000 ) +, BOOST_BINARY( 11001 ) +, BOOST_BINARY( 11010 ) +, BOOST_BINARY( 11011 ) +, BOOST_BINARY( 11100 ) +, BOOST_BINARY( 11101 ) +, BOOST_BINARY( 11110 ) +, BOOST_BINARY( 11111 ) +}; + +unsigned int const unsigned_ints_6_bits[64] = +{ BOOST_BINARY( 000000 ) +, BOOST_BINARY( 000001 ) +, BOOST_BINARY( 000010 ) +, BOOST_BINARY( 000011 ) +, BOOST_BINARY( 000100 ) +, BOOST_BINARY( 000101 ) +, BOOST_BINARY( 000110 ) +, BOOST_BINARY( 000111 ) +, BOOST_BINARY( 001000 ) +, BOOST_BINARY( 001001 ) +, BOOST_BINARY( 001010 ) +, BOOST_BINARY( 001011 ) +, BOOST_BINARY( 001100 ) +, BOOST_BINARY( 001101 ) +, BOOST_BINARY( 001110 ) +, BOOST_BINARY( 001111 ) +, BOOST_BINARY( 010000 ) +, BOOST_BINARY( 010001 ) +, BOOST_BINARY( 010010 ) +, BOOST_BINARY( 010011 ) +, BOOST_BINARY( 010100 ) +, BOOST_BINARY( 010101 ) +, BOOST_BINARY( 010110 ) +, BOOST_BINARY( 010111 ) +, BOOST_BINARY( 011000 ) +, BOOST_BINARY( 011001 ) +, BOOST_BINARY( 011010 ) +, BOOST_BINARY( 011011 ) +, BOOST_BINARY( 011100 ) +, BOOST_BINARY( 011101 ) +, BOOST_BINARY( 011110 ) +, BOOST_BINARY( 011111 ) +, BOOST_BINARY( 100000 ) +, BOOST_BINARY( 100001 ) +, BOOST_BINARY( 100010 ) +, BOOST_BINARY( 100011 ) +, BOOST_BINARY( 100100 ) +, BOOST_BINARY( 100101 ) +, BOOST_BINARY( 100110 ) +, BOOST_BINARY( 100111 ) +, BOOST_BINARY( 101000 ) +, BOOST_BINARY( 101001 ) +, BOOST_BINARY( 101010 ) +, BOOST_BINARY( 101011 ) +, BOOST_BINARY( 101100 ) +, BOOST_BINARY( 101101 ) +, BOOST_BINARY( 101110 ) +, BOOST_BINARY( 101111 ) +, BOOST_BINARY( 110000 ) +, BOOST_BINARY( 110001 ) +, BOOST_BINARY( 110010 ) +, BOOST_BINARY( 110011 ) +, BOOST_BINARY( 110100 ) +, BOOST_BINARY( 110101 ) +, BOOST_BINARY( 110110 ) +, BOOST_BINARY( 110111 ) +, BOOST_BINARY( 111000 ) +, BOOST_BINARY( 111001 ) +, BOOST_BINARY( 111010 ) +, BOOST_BINARY( 111011 ) +, BOOST_BINARY( 111100 ) +, BOOST_BINARY( 111101 ) +, BOOST_BINARY( 111110 ) +, BOOST_BINARY( 111111 ) +}; + +unsigned int const unsigned_ints_7_bits[128] = +{ BOOST_BINARY( 0000000 ) +, BOOST_BINARY( 0000001 ) +, BOOST_BINARY( 0000010 ) +, BOOST_BINARY( 0000011 ) +, BOOST_BINARY( 0000100 ) +, BOOST_BINARY( 0000101 ) +, BOOST_BINARY( 0000110 ) +, BOOST_BINARY( 0000111 ) +, BOOST_BINARY( 0001000 ) +, BOOST_BINARY( 0001001 ) +, BOOST_BINARY( 0001010 ) +, BOOST_BINARY( 0001011 ) +, BOOST_BINARY( 0001100 ) +, BOOST_BINARY( 0001101 ) +, BOOST_BINARY( 0001110 ) +, BOOST_BINARY( 0001111 ) +, BOOST_BINARY( 0010000 ) +, BOOST_BINARY( 0010001 ) +, BOOST_BINARY( 0010010 ) +, BOOST_BINARY( 0010011 ) +, BOOST_BINARY( 0010100 ) +, BOOST_BINARY( 0010101 ) +, BOOST_BINARY( 0010110 ) +, BOOST_BINARY( 0010111 ) +, BOOST_BINARY( 0011000 ) +, BOOST_BINARY( 0011001 ) +, BOOST_BINARY( 0011010 ) +, BOOST_BINARY( 0011011 ) +, BOOST_BINARY( 0011100 ) +, BOOST_BINARY( 0011101 ) +, BOOST_BINARY( 0011110 ) +, BOOST_BINARY( 0011111 ) +, BOOST_BINARY( 0100000 ) +, BOOST_BINARY( 0100001 ) +, BOOST_BINARY( 0100010 ) +, BOOST_BINARY( 0100011 ) +, BOOST_BINARY( 0100100 ) +, BOOST_BINARY( 0100101 ) +, BOOST_BINARY( 0100110 ) +, BOOST_BINARY( 0100111 ) +, BOOST_BINARY( 0101000 ) +, BOOST_BINARY( 0101001 ) +, BOOST_BINARY( 0101010 ) +, BOOST_BINARY( 0101011 ) +, BOOST_BINARY( 0101100 ) +, BOOST_BINARY( 0101101 ) +, BOOST_BINARY( 0101110 ) +, BOOST_BINARY( 0101111 ) +, BOOST_BINARY( 0110000 ) +, BOOST_BINARY( 0110001 ) +, BOOST_BINARY( 0110010 ) +, BOOST_BINARY( 0110011 ) +, BOOST_BINARY( 0110100 ) +, BOOST_BINARY( 0110101 ) +, BOOST_BINARY( 0110110 ) +, BOOST_BINARY( 0110111 ) +, BOOST_BINARY( 0111000 ) +, BOOST_BINARY( 0111001 ) +, BOOST_BINARY( 0111010 ) +, BOOST_BINARY( 0111011 ) +, BOOST_BINARY( 0111100 ) +, BOOST_BINARY( 0111101 ) +, BOOST_BINARY( 0111110 ) +, BOOST_BINARY( 0111111 ) +, BOOST_BINARY( 1000000 ) +, BOOST_BINARY( 1000001 ) +, BOOST_BINARY( 1000010 ) +, BOOST_BINARY( 1000011 ) +, BOOST_BINARY( 1000100 ) +, BOOST_BINARY( 1000101 ) +, BOOST_BINARY( 1000110 ) +, BOOST_BINARY( 1000111 ) +, BOOST_BINARY( 1001000 ) +, BOOST_BINARY( 1001001 ) +, BOOST_BINARY( 1001010 ) +, BOOST_BINARY( 1001011 ) +, BOOST_BINARY( 1001100 ) +, BOOST_BINARY( 1001101 ) +, BOOST_BINARY( 1001110 ) +, BOOST_BINARY( 1001111 ) +, BOOST_BINARY( 1010000 ) +, BOOST_BINARY( 1010001 ) +, BOOST_BINARY( 1010010 ) +, BOOST_BINARY( 1010011 ) +, BOOST_BINARY( 1010100 ) +, BOOST_BINARY( 1010101 ) +, BOOST_BINARY( 1010110 ) +, BOOST_BINARY( 1010111 ) +, BOOST_BINARY( 1011000 ) +, BOOST_BINARY( 1011001 ) +, BOOST_BINARY( 1011010 ) +, BOOST_BINARY( 1011011 ) +, BOOST_BINARY( 1011100 ) +, BOOST_BINARY( 1011101 ) +, BOOST_BINARY( 1011110 ) +, BOOST_BINARY( 1011111 ) +, BOOST_BINARY( 1100000 ) +, BOOST_BINARY( 1100001 ) +, BOOST_BINARY( 1100010 ) +, BOOST_BINARY( 1100011 ) +, BOOST_BINARY( 1100100 ) +, BOOST_BINARY( 1100101 ) +, BOOST_BINARY( 1100110 ) +, BOOST_BINARY( 1100111 ) +, BOOST_BINARY( 1101000 ) +, BOOST_BINARY( 1101001 ) +, BOOST_BINARY( 1101010 ) +, BOOST_BINARY( 1101011 ) +, BOOST_BINARY( 1101100 ) +, BOOST_BINARY( 1101101 ) +, BOOST_BINARY( 1101110 ) +, BOOST_BINARY( 1101111 ) +, BOOST_BINARY( 1110000 ) +, BOOST_BINARY( 1110001 ) +, BOOST_BINARY( 1110010 ) +, BOOST_BINARY( 1110011 ) +, BOOST_BINARY( 1110100 ) +, BOOST_BINARY( 1110101 ) +, BOOST_BINARY( 1110110 ) +, BOOST_BINARY( 1110111 ) +, BOOST_BINARY( 1111000 ) +, BOOST_BINARY( 1111001 ) +, BOOST_BINARY( 1111010 ) +, BOOST_BINARY( 1111011 ) +, BOOST_BINARY( 1111100 ) +, BOOST_BINARY( 1111101 ) +, BOOST_BINARY( 1111110 ) +, BOOST_BINARY( 1111111 ) +}; +unsigned int const unsigned_ints_8_bits[256] = +{ BOOST_BINARY( 00000000 ) +, BOOST_BINARY( 00000001 ) +, BOOST_BINARY( 00000010 ) +, BOOST_BINARY( 00000011 ) +, BOOST_BINARY( 00000100 ) +, BOOST_BINARY( 00000101 ) +, BOOST_BINARY( 00000110 ) +, BOOST_BINARY( 00000111 ) +, BOOST_BINARY( 00001000 ) +, BOOST_BINARY( 00001001 ) +, BOOST_BINARY( 00001010 ) +, BOOST_BINARY( 00001011 ) +, BOOST_BINARY( 00001100 ) +, BOOST_BINARY( 00001101 ) +, BOOST_BINARY( 00001110 ) +, BOOST_BINARY( 00001111 ) +, BOOST_BINARY( 00010000 ) +, BOOST_BINARY( 00010001 ) +, BOOST_BINARY( 00010010 ) +, BOOST_BINARY( 00010011 ) +, BOOST_BINARY( 00010100 ) +, BOOST_BINARY( 00010101 ) +, BOOST_BINARY( 00010110 ) +, BOOST_BINARY( 00010111 ) +, BOOST_BINARY( 00011000 ) +, BOOST_BINARY( 00011001 ) +, BOOST_BINARY( 00011010 ) +, BOOST_BINARY( 00011011 ) +, BOOST_BINARY( 00011100 ) +, BOOST_BINARY( 00011101 ) +, BOOST_BINARY( 00011110 ) +, BOOST_BINARY( 00011111 ) +, BOOST_BINARY( 00100000 ) +, BOOST_BINARY( 00100001 ) +, BOOST_BINARY( 00100010 ) +, BOOST_BINARY( 00100011 ) +, BOOST_BINARY( 00100100 ) +, BOOST_BINARY( 00100101 ) +, BOOST_BINARY( 00100110 ) +, BOOST_BINARY( 00100111 ) +, BOOST_BINARY( 00101000 ) +, BOOST_BINARY( 00101001 ) +, BOOST_BINARY( 00101010 ) +, BOOST_BINARY( 00101011 ) +, BOOST_BINARY( 00101100 ) +, BOOST_BINARY( 00101101 ) +, BOOST_BINARY( 00101110 ) +, BOOST_BINARY( 00101111 ) +, BOOST_BINARY( 00110000 ) +, BOOST_BINARY( 00110001 ) +, BOOST_BINARY( 00110010 ) +, BOOST_BINARY( 00110011 ) +, BOOST_BINARY( 00110100 ) +, BOOST_BINARY( 00110101 ) +, BOOST_BINARY( 00110110 ) +, BOOST_BINARY( 00110111 ) +, BOOST_BINARY( 00111000 ) +, BOOST_BINARY( 00111001 ) +, BOOST_BINARY( 00111010 ) +, BOOST_BINARY( 00111011 ) +, BOOST_BINARY( 00111100 ) +, BOOST_BINARY( 00111101 ) +, BOOST_BINARY( 00111110 ) +, BOOST_BINARY( 00111111 ) +, BOOST_BINARY( 01000000 ) +, BOOST_BINARY( 01000001 ) +, BOOST_BINARY( 01000010 ) +, BOOST_BINARY( 01000011 ) +, BOOST_BINARY( 01000100 ) +, BOOST_BINARY( 01000101 ) +, BOOST_BINARY( 01000110 ) +, BOOST_BINARY( 01000111 ) +, BOOST_BINARY( 01001000 ) +, BOOST_BINARY( 01001001 ) +, BOOST_BINARY( 01001010 ) +, BOOST_BINARY( 01001011 ) +, BOOST_BINARY( 01001100 ) +, BOOST_BINARY( 01001101 ) +, BOOST_BINARY( 01001110 ) +, BOOST_BINARY( 01001111 ) +, BOOST_BINARY( 01010000 ) +, BOOST_BINARY( 01010001 ) +, BOOST_BINARY( 01010010 ) +, BOOST_BINARY( 01010011 ) +, BOOST_BINARY( 01010100 ) +, BOOST_BINARY( 01010101 ) +, BOOST_BINARY( 01010110 ) +, BOOST_BINARY( 01010111 ) +, BOOST_BINARY( 01011000 ) +, BOOST_BINARY( 01011001 ) +, BOOST_BINARY( 01011010 ) +, BOOST_BINARY( 01011011 ) +, BOOST_BINARY( 01011100 ) +, BOOST_BINARY( 01011101 ) +, BOOST_BINARY( 01011110 ) +, BOOST_BINARY( 01011111 ) +, BOOST_BINARY( 01100000 ) +, BOOST_BINARY( 01100001 ) +, BOOST_BINARY( 01100010 ) +, BOOST_BINARY( 01100011 ) +, BOOST_BINARY( 01100100 ) +, BOOST_BINARY( 01100101 ) +, BOOST_BINARY( 01100110 ) +, BOOST_BINARY( 01100111 ) +, BOOST_BINARY( 01101000 ) +, BOOST_BINARY( 01101001 ) +, BOOST_BINARY( 01101010 ) +, BOOST_BINARY( 01101011 ) +, BOOST_BINARY( 01101100 ) +, BOOST_BINARY( 01101101 ) +, BOOST_BINARY( 01101110 ) +, BOOST_BINARY( 01101111 ) +, BOOST_BINARY( 01110000 ) +, BOOST_BINARY( 01110001 ) +, BOOST_BINARY( 01110010 ) +, BOOST_BINARY( 01110011 ) +, BOOST_BINARY( 01110100 ) +, BOOST_BINARY( 01110101 ) +, BOOST_BINARY( 01110110 ) +, BOOST_BINARY( 01110111 ) +, BOOST_BINARY( 01111000 ) +, BOOST_BINARY( 01111001 ) +, BOOST_BINARY( 01111010 ) +, BOOST_BINARY( 01111011 ) +, BOOST_BINARY( 01111100 ) +, BOOST_BINARY( 01111101 ) +, BOOST_BINARY( 01111110 ) +, BOOST_BINARY( 01111111 ) +, BOOST_BINARY( 10000000 ) +, BOOST_BINARY( 10000001 ) +, BOOST_BINARY( 10000010 ) +, BOOST_BINARY( 10000011 ) +, BOOST_BINARY( 10000100 ) +, BOOST_BINARY( 10000101 ) +, BOOST_BINARY( 10000110 ) +, BOOST_BINARY( 10000111 ) +, BOOST_BINARY( 10001000 ) +, BOOST_BINARY( 10001001 ) +, BOOST_BINARY( 10001010 ) +, BOOST_BINARY( 10001011 ) +, BOOST_BINARY( 10001100 ) +, BOOST_BINARY( 10001101 ) +, BOOST_BINARY( 10001110 ) +, BOOST_BINARY( 10001111 ) +, BOOST_BINARY( 10010000 ) +, BOOST_BINARY( 10010001 ) +, BOOST_BINARY( 10010010 ) +, BOOST_BINARY( 10010011 ) +, BOOST_BINARY( 10010100 ) +, BOOST_BINARY( 10010101 ) +, BOOST_BINARY( 10010110 ) +, BOOST_BINARY( 10010111 ) +, BOOST_BINARY( 10011000 ) +, BOOST_BINARY( 10011001 ) +, BOOST_BINARY( 10011010 ) +, BOOST_BINARY( 10011011 ) +, BOOST_BINARY( 10011100 ) +, BOOST_BINARY( 10011101 ) +, BOOST_BINARY( 10011110 ) +, BOOST_BINARY( 10011111 ) +, BOOST_BINARY( 10100000 ) +, BOOST_BINARY( 10100001 ) +, BOOST_BINARY( 10100010 ) +, BOOST_BINARY( 10100011 ) +, BOOST_BINARY( 10100100 ) +, BOOST_BINARY( 10100101 ) +, BOOST_BINARY( 10100110 ) +, BOOST_BINARY( 10100111 ) +, BOOST_BINARY( 10101000 ) +, BOOST_BINARY( 10101001 ) +, BOOST_BINARY( 10101010 ) +, BOOST_BINARY( 10101011 ) +, BOOST_BINARY( 10101100 ) +, BOOST_BINARY( 10101101 ) +, BOOST_BINARY( 10101110 ) +, BOOST_BINARY( 10101111 ) +, BOOST_BINARY( 10110000 ) +, BOOST_BINARY( 10110001 ) +, BOOST_BINARY( 10110010 ) +, BOOST_BINARY( 10110011 ) +, BOOST_BINARY( 10110100 ) +, BOOST_BINARY( 10110101 ) +, BOOST_BINARY( 10110110 ) +, BOOST_BINARY( 10110111 ) +, BOOST_BINARY( 10111000 ) +, BOOST_BINARY( 10111001 ) +, BOOST_BINARY( 10111010 ) +, BOOST_BINARY( 10111011 ) +, BOOST_BINARY( 10111100 ) +, BOOST_BINARY( 10111101 ) +, BOOST_BINARY( 10111110 ) +, BOOST_BINARY( 10111111 ) +, BOOST_BINARY( 11000000 ) +, BOOST_BINARY( 11000001 ) +, BOOST_BINARY( 11000010 ) +, BOOST_BINARY( 11000011 ) +, BOOST_BINARY( 11000100 ) +, BOOST_BINARY( 11000101 ) +, BOOST_BINARY( 11000110 ) +, BOOST_BINARY( 11000111 ) +, BOOST_BINARY( 11001000 ) +, BOOST_BINARY( 11001001 ) +, BOOST_BINARY( 11001010 ) +, BOOST_BINARY( 11001011 ) +, BOOST_BINARY( 11001100 ) +, BOOST_BINARY( 11001101 ) +, BOOST_BINARY( 11001110 ) +, BOOST_BINARY( 11001111 ) +, BOOST_BINARY( 11010000 ) +, BOOST_BINARY( 11010001 ) +, BOOST_BINARY( 11010010 ) +, BOOST_BINARY( 11010011 ) +, BOOST_BINARY( 11010100 ) +, BOOST_BINARY( 11010101 ) +, BOOST_BINARY( 11010110 ) +, BOOST_BINARY( 11010111 ) +, BOOST_BINARY( 11011000 ) +, BOOST_BINARY( 11011001 ) +, BOOST_BINARY( 11011010 ) +, BOOST_BINARY( 11011011 ) +, BOOST_BINARY( 11011100 ) +, BOOST_BINARY( 11011101 ) +, BOOST_BINARY( 11011110 ) +, BOOST_BINARY( 11011111 ) +, BOOST_BINARY( 11100000 ) +, BOOST_BINARY( 11100001 ) +, BOOST_BINARY( 11100010 ) +, BOOST_BINARY( 11100011 ) +, BOOST_BINARY( 11100100 ) +, BOOST_BINARY( 11100101 ) +, BOOST_BINARY( 11100110 ) +, BOOST_BINARY( 11100111 ) +, BOOST_BINARY( 11101000 ) +, BOOST_BINARY( 11101001 ) +, BOOST_BINARY( 11101010 ) +, BOOST_BINARY( 11101011 ) +, BOOST_BINARY( 11101100 ) +, BOOST_BINARY( 11101101 ) +, BOOST_BINARY( 11101110 ) +, BOOST_BINARY( 11101111 ) +, BOOST_BINARY( 11110000 ) +, BOOST_BINARY( 11110001 ) +, BOOST_BINARY( 11110010 ) +, BOOST_BINARY( 11110011 ) +, BOOST_BINARY( 11110100 ) +, BOOST_BINARY( 11110101 ) +, BOOST_BINARY( 11110110 ) +, BOOST_BINARY( 11110111 ) +, BOOST_BINARY( 11111000 ) +, BOOST_BINARY( 11111001 ) +, BOOST_BINARY( 11111010 ) +, BOOST_BINARY( 11111011 ) +, BOOST_BINARY( 11111100 ) +, BOOST_BINARY( 11111101 ) +, BOOST_BINARY( 11111110 ) +, BOOST_BINARY( 11111111 ) +}; + +struct left_is_not_one_less_than_right +{ + bool operator ()( unsigned int left, unsigned int right ) const + { + return right != left + 1; + } +}; + +template< std::size_t Size > +bool is_ascending_from_0_array( unsigned int const (&array)[Size] ) +{ + unsigned int const* const curr = array, + * const end = array + Size; + + return ( *curr == 0 ) + && ( std::adjacent_find( curr, end + , left_is_not_one_less_than_right() + ) + == end + ); +} + +std::size_t const unsigned_int_id = 1, + unsigned_long_int_id = 2; + +typedef char (&unsigned_int_id_type)[unsigned_int_id]; +typedef char (&unsigned_long_int_id_type)[unsigned_long_int_id]; + +// Note: Functions only used for type checking +unsigned_int_id_type binary_type_checker( unsigned int ); +unsigned_long_int_id_type binary_type_checker( unsigned long int ); + +int main() +{ + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_1_bit ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_2_bits ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_3_bits ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_4_bits ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_5_bits ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_6_bits ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_7_bits ) ); + BOOST_TEST( is_ascending_from_0_array( unsigned_ints_8_bits ) ); + + BOOST_TEST( std::equal( &random_unsigned_ints_hex[0] + , random_unsigned_ints_hex + num_random_test_values + , &random_unsigned_ints_binary[0] + ) + ); + + BOOST_TEST( sizeof( binary_type_checker( BOOST_BINARY_U( 110100 1010 ) ) ) + == unsigned_int_id + ); + + BOOST_TEST( sizeof( binary_type_checker( BOOST_BINARY_UL( 11110 ) ) ) + == unsigned_long_int_id + ); + + BOOST_TEST( sizeof( binary_type_checker( BOOST_BINARY_LU( 10 0001 ) ) ) + == unsigned_long_int_id + ); + + return boost::report_errors(); +} diff --git a/libs/utility/test/call_traits_test.cpp b/libs/utility/test/call_traits_test.cpp new file mode 100644 index 00000000..57ad67ce --- /dev/null +++ b/libs/utility/test/call_traits_test.cpp @@ -0,0 +1,418 @@ +// boost::compressed_pair test program + +// (C) Copyright John Maddock 2000. +// Use, modification and distribution are subject to 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). + + +// standalone test program for +// 18 Mar 2002: +// Changed some names to prevent conflicts with some new type_traits additions. +// 03 Oct 2000: +// Enabled extra tests for VC6. + +#include +#include +#include +#include +#include + +#include +#include + +#ifdef BOOST_MSVC +#pragma warning(disable:4181) // : warning C4181: qualifier applied to reference type; ignored +#endif + +// a way prevent warnings for unused variables +template inline void unused_variable(const T&) {} + +// +// struct contained models a type that contains a type (for example std::pair) +// arrays are contained by value, and have to be treated as a special case: +// +template +struct contained +{ + // define our typedefs first, arrays are stored by value + // so value_type is not the same as result_type: + typedef typename boost::call_traits::param_type param_type; + typedef typename boost::call_traits::reference reference; + typedef typename boost::call_traits::const_reference const_reference; + typedef T value_type; + typedef typename boost::call_traits::value_type result_type; + + // stored value: + value_type v_; + + // constructors: + contained() {} + contained(param_type p) : v_(p){} + // return byval: + result_type value()const { return v_; } + // return by_ref: + reference get() { return v_; } + const_reference const_get()const { return v_; } + // pass value: + void call(param_type){} +private: + contained& operator=(const contained&); +}; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct contained +{ + typedef typename boost::call_traits::param_type param_type; + typedef typename boost::call_traits::reference reference; + typedef typename boost::call_traits::const_reference const_reference; + typedef T value_type[N]; + typedef typename boost::call_traits::value_type result_type; + + value_type v_; + + contained(param_type p) + { + std::copy(p, p+N, v_); + } + // return byval: + result_type value()const { return v_; } + // return by_ref: + reference get() { return v_; } + const_reference const_get()const { return v_; } + void call(param_type){} +private: + contained& operator=(const contained&); +}; +#endif + +template +contained::value_type> test_wrap_type(const T& t) +{ + typedef typename boost::call_traits::value_type ct; + return contained(t); +} + +namespace test{ + +template +std::pair< + typename boost::call_traits::value_type, + typename boost::call_traits::value_type> + make_pair(const T1& t1, const T2& t2) +{ + return std::pair< + typename boost::call_traits::value_type, + typename boost::call_traits::value_type>(t1, t2); +} + +} // namespace test + +using namespace std; + +// +// struct call_traits_checker: +// verifies behaviour of contained example: +// +template +struct call_traits_checker +{ + typedef typename boost::call_traits::param_type param_type; + void operator()(param_type); +}; + +template +void call_traits_checker::operator()(param_type p) +{ + T t(p); + contained c(t); + cout << "checking contained<" << typeid(T).name() << ">..." << endl; + BOOST_CHECK(t == c.value()); + BOOST_CHECK(t == c.get()); + BOOST_CHECK(t == c.const_get()); +#ifndef __ICL + //cout << "typeof contained<" << typeid(T).name() << ">::v_ is: " << typeid(&contained::v_).name() << endl; + cout << "typeof contained<" << typeid(T).name() << ">::value() is: " << typeid(&contained::value).name() << endl; + cout << "typeof contained<" << typeid(T).name() << ">::get() is: " << typeid(&contained::get).name() << endl; + cout << "typeof contained<" << typeid(T).name() << ">::const_get() is: " << typeid(&contained::const_get).name() << endl; + cout << "typeof contained<" << typeid(T).name() << ">::call() is: " << typeid(&contained::call).name() << endl; + cout << endl; +#endif +} + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct call_traits_checker +{ + typedef typename boost::call_traits::param_type param_type; + void operator()(param_type t) + { + contained c(t); + cout << "checking contained<" << typeid(T[N]).name() << ">..." << endl; + unsigned int i = 0; + for(i = 0; i < N; ++i) + BOOST_CHECK(t[i] == c.value()[i]); + for(i = 0; i < N; ++i) + BOOST_CHECK(t[i] == c.get()[i]); + for(i = 0; i < N; ++i) + BOOST_CHECK(t[i] == c.const_get()[i]); + + cout << "typeof contained<" << typeid(T[N]).name() << ">::v_ is: " << typeid(&contained::v_).name() << endl; + cout << "typeof contained<" << typeid(T[N]).name() << ">::value is: " << typeid(&contained::value).name() << endl; + cout << "typeof contained<" << typeid(T[N]).name() << ">::get is: " << typeid(&contained::get).name() << endl; + cout << "typeof contained<" << typeid(T[N]).name() << ">::const_get is: " << typeid(&contained::const_get).name() << endl; + cout << "typeof contained<" << typeid(T[N]).name() << ">::call is: " << typeid(&contained::call).name() << endl; + cout << endl; + } +}; +#endif + +// +// check_wrap: +template +void check_wrap(const W& w, const U& u) +{ + cout << "checking " << typeid(W).name() << "..." << endl; + BOOST_CHECK(w.value() == u); +} + +// +// check_make_pair: +// verifies behaviour of "make_pair": +// +template +void check_make_pair(T c, U u, V v) +{ + cout << "checking std::pair<" << typeid(c.first).name() << ", " << typeid(c.second).name() << ">..." << endl; + BOOST_CHECK(c.first == u); + BOOST_CHECK(c.second == v); + cout << endl; +} + + +struct comparible_UDT +{ + int i_; + comparible_UDT() : i_(2){} + comparible_UDT(const comparible_UDT& other) : i_(other.i_){} + comparible_UDT& operator=(const comparible_UDT& other) + { + i_ = other.i_; + return *this; + } + bool operator == (const comparible_UDT& v) const { return v.i_ == i_; } +}; + +int main() +{ + call_traits_checker c1; + comparible_UDT u; + c1(u); + call_traits_checker c2; + call_traits_checker c2b; + int i = 2; + c2(i); + c2b(one); + int* pi = &i; + int a[2] = {1,2}; +#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) && !defined(__ICL) + call_traits_checker c3; + c3(pi); + call_traits_checker c4; + c4(i); + call_traits_checker c5; + c5(i); +#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__) && !defined(__SUNPRO_CC) + call_traits_checker c6; + c6(a); +#endif +#endif + + check_wrap(test_wrap_type(2), 2); +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) + check_wrap(test_wrap_type(a), a); + check_make_pair(test::make_pair(a, a), a, a); +#endif + + // cv-qualifiers applied to reference types should have no effect + // declare these here for later use with is_reference and remove_reference: + typedef int& r_type; + typedef const r_type cr_type; + + BOOST_CHECK_TYPE(comparible_UDT, boost::call_traits::value_type); + BOOST_CHECK_TYPE(comparible_UDT&, boost::call_traits::reference); + BOOST_CHECK_TYPE(const comparible_UDT&, boost::call_traits::const_reference); + BOOST_CHECK_TYPE(const comparible_UDT&, boost::call_traits::param_type); + BOOST_CHECK_TYPE(int, boost::call_traits::value_type); + BOOST_CHECK_TYPE(int&, boost::call_traits::reference); + BOOST_CHECK_TYPE(const int&, boost::call_traits::const_reference); + BOOST_CHECK_TYPE(const int, boost::call_traits::param_type); + BOOST_CHECK_TYPE(int*, boost::call_traits::value_type); + BOOST_CHECK_TYPE(int*&, boost::call_traits::reference); + BOOST_CHECK_TYPE(int*const&, boost::call_traits::const_reference); + BOOST_CHECK_TYPE(int*const, boost::call_traits::param_type); +#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) + BOOST_CHECK_TYPE(int&, boost::call_traits::value_type); + BOOST_CHECK_TYPE(int&, boost::call_traits::reference); + BOOST_CHECK_TYPE(const int&, boost::call_traits::const_reference); + BOOST_CHECK_TYPE(int&, boost::call_traits::param_type); +#if !(defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1))) + BOOST_CHECK_TYPE(int&, boost::call_traits::value_type); + BOOST_CHECK_TYPE(int&, boost::call_traits::reference); + BOOST_CHECK_TYPE(const int&, boost::call_traits::const_reference); + BOOST_CHECK_TYPE(int&, boost::call_traits::param_type); +#else + std::cout << "Your compiler cannot instantiate call_traits, skipping four tests (4 errors)" << std::endl; +#endif + BOOST_CHECK_TYPE(const int&, boost::call_traits::value_type); + BOOST_CHECK_TYPE(const int&, boost::call_traits::reference); + BOOST_CHECK_TYPE(const int&, boost::call_traits::const_reference); + BOOST_CHECK_TYPE(const int&, boost::call_traits::param_type); +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + BOOST_CHECK_TYPE(const int*, boost::call_traits::value_type); + BOOST_CHECK_TYPE(int(&)[3], boost::call_traits::reference); + BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits::const_reference); + BOOST_CHECK_TYPE(const int*const, boost::call_traits::param_type); + BOOST_CHECK_TYPE(const int*, boost::call_traits::value_type); + BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits::reference); + BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits::const_reference); + BOOST_CHECK_TYPE(const int*const, boost::call_traits::param_type); + // test with abstract base class: + BOOST_CHECK_TYPE(test_abc1, boost::call_traits::value_type); + BOOST_CHECK_TYPE(test_abc1&, boost::call_traits::reference); + BOOST_CHECK_TYPE(const test_abc1&, boost::call_traits::const_reference); + BOOST_CHECK_TYPE(const test_abc1&, boost::call_traits::param_type); +#else + std::cout << "You're compiler does not support partial template specialiation, skipping 8 tests (8 errors)" << std::endl; +#endif +#else + std::cout << "You're compiler does not support partial template specialiation, skipping 20 tests (20 errors)" << std::endl; +#endif + // test with an incomplete type: + BOOST_CHECK_TYPE(incomplete_type, boost::call_traits::value_type); + BOOST_CHECK_TYPE(incomplete_type&, boost::call_traits::reference); + BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits::const_reference); + BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits::param_type); + // test enum: + BOOST_CHECK_TYPE(enum_UDT, boost::call_traits::value_type); + BOOST_CHECK_TYPE(enum_UDT&, boost::call_traits::reference); + BOOST_CHECK_TYPE(const enum_UDT&, boost::call_traits::const_reference); + BOOST_CHECK_TYPE(const enum_UDT, boost::call_traits::param_type); + return 0; +} + +// +// define call_traits tests to check that the assertions in the docs do actually work +// this is an compile-time only set of tests: +// +template +struct call_traits_test +{ + typedef ::boost::call_traits ct; + typedef typename ct::param_type param_type; + typedef typename ct::reference reference; + typedef typename ct::const_reference const_reference; + typedef typename ct::value_type value_type; + static void assert_construct(param_type val); +}; + +template +void call_traits_test::assert_construct(typename call_traits_test::param_type val) +{ + // + // this is to check that the call_traits assertions are valid: + T t(val); + value_type v(t); + reference r(t); + const_reference cr(t); + param_type p(t); + value_type v2(v); + value_type v3(r); + value_type v4(p); + reference r2(v); + reference r3(r); + const_reference cr2(v); + const_reference cr3(r); + const_reference cr4(cr); + const_reference cr5(p); + param_type p2(v); + param_type p3(r); + param_type p4(p); + + unused_variable(v2); + unused_variable(v3); + unused_variable(v4); + unused_variable(r2); + unused_variable(r3); + unused_variable(cr2); + unused_variable(cr3); + unused_variable(cr4); + unused_variable(cr5); + unused_variable(p2); + unused_variable(p3); + unused_variable(p4); +} +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct call_traits_test +{ + typedef ::boost::call_traits ct; + typedef typename ct::param_type param_type; + typedef typename ct::reference reference; + typedef typename ct::const_reference const_reference; + typedef typename ct::value_type value_type; + static void assert_construct(param_type val); +}; + +template +void call_traits_test::assert_construct(typename boost::call_traits::param_type val) +{ + // + // this is to check that the call_traits assertions are valid: + T t; + value_type v(t); + value_type v5(val); + reference r = t; + const_reference cr = t; + reference r2 = r; + #ifndef BOOST_BORLANDC + // C++ Builder buglet: + const_reference cr2 = r; + #endif + param_type p(t); + value_type v2(v); + const_reference cr3 = cr; + value_type v3(r); + value_type v4(p); + param_type p2(v); + param_type p3(r); + param_type p4(p); + + unused_variable(v2); + unused_variable(v3); + unused_variable(v4); + unused_variable(v5); +#ifndef BOOST_BORLANDC + unused_variable(r2); + unused_variable(cr2); +#endif + unused_variable(cr3); + unused_variable(p2); + unused_variable(p3); + unused_variable(p4); +} +#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +// +// now check call_traits assertions by instantiating call_traits_test: +template struct call_traits_test; +template struct call_traits_test; +template struct call_traits_test; +#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) +template struct call_traits_test; +template struct call_traits_test; +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) +template struct call_traits_test; +#endif +#endif + diff --git a/libs/utility/test/compressed_pair_final_test.cpp b/libs/utility/test/compressed_pair_final_test.cpp new file mode 100644 index 00000000..247f3fce --- /dev/null +++ b/libs/utility/test/compressed_pair_final_test.cpp @@ -0,0 +1,55 @@ +/* +Copyright 2018 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_FINAL) +#include +#include + +struct type1 { + operator bool() const { + return false; + } +}; + +struct type2 final { + operator bool() const { + return false; + } +}; + +#if !defined(BOOST_IS_FINAL) +namespace boost { + +template<> +struct is_final + : true_type { }; + +} /* boost*/ +#endif + +template +void test() +{ + boost::compressed_pair p; + BOOST_TEST(!p.first()); + BOOST_TEST(!p.second()); +} + +int main() +{ + test(); + test(); + test(); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif diff --git a/libs/utility/test/compressed_pair_test.cpp b/libs/utility/test/compressed_pair_test.cpp new file mode 100644 index 00000000..ea10b2c0 --- /dev/null +++ b/libs/utility/test/compressed_pair_test.cpp @@ -0,0 +1,387 @@ +// boost::compressed_pair test program + +// (C) Copyright John Maddock 2000. +// Use, modification and distribution are subject to 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). + +// standalone test program for +// Revised 03 Oct 2000: +// Enabled tests for VC6. + +#include +#include +#include + +#include +#include + +using namespace boost; + +struct empty_UDT +{ + ~empty_UDT(){}; + empty_UDT& operator=(const empty_UDT&){ return *this; } + bool operator==(const empty_UDT&)const + { return true; } +}; +struct empty_POD_UDT +{ + empty_POD_UDT& operator=(const empty_POD_UDT&){ return *this; } + bool operator==(const empty_POD_UDT&)const + { return true; } +}; + +struct non_empty1 +{ + int i; + non_empty1() : i(1){} + non_empty1(int v) : i(v){} + friend bool operator==(const non_empty1& a, const non_empty1& b) + { return a.i == b.i; } +}; + +struct non_empty2 +{ + int i; + non_empty2() : i(3){} + non_empty2(int v) : i(v){} + friend bool operator==(const non_empty2& a, const non_empty2& b) + { return a.i == b.i; } +}; + +#ifdef __GNUC__ +using std::swap; +#endif + +template +struct compressed_pair_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template +void compressed_pair_tester::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) +{ +#ifndef __GNUC__ + // gcc 2.90 can't cope with function scope using + // declarations, and generates an internal compiler error... + using std::swap; +#endif + // default construct: + boost::compressed_pair cp1; + // first param construct: + boost::compressed_pair cp2(p1); + cp2.second() = p2; + BOOST_TEST(cp2.first() == p1); + BOOST_TEST(cp2.second() == p2); + // second param construct: + boost::compressed_pair cp3(p2); + cp3.first() = p1; + BOOST_TEST(cp3.second() == p2); + BOOST_TEST(cp3.first() == p1); + // both param construct: + boost::compressed_pair cp4(p1, p2); + BOOST_TEST(cp4.first() == p1); + BOOST_TEST(cp4.second() == p2); + boost::compressed_pair cp5(p3, p4); + BOOST_TEST(cp5.first() == p3); + BOOST_TEST(cp5.second() == p4); + // check const members: + const boost::compressed_pair& cpr1 = cp4; + BOOST_TEST(cpr1.first() == p1); + BOOST_TEST(cpr1.second() == p2); + + // copy construct: + boost::compressed_pair cp6(cp4); + BOOST_TEST(cp6.first() == p1); + BOOST_TEST(cp6.second() == p2); + // assignment: + cp1 = cp4; + BOOST_TEST(cp1.first() == p1); + BOOST_TEST(cp1.second() == p2); + cp1 = cp5; + BOOST_TEST(cp1.first() == p3); + BOOST_TEST(cp1.second() == p4); + // swap: + cp4.swap(cp5); + BOOST_TEST(cp4.first() == p3); + BOOST_TEST(cp4.second() == p4); + BOOST_TEST(cp5.first() == p1); + BOOST_TEST(cp5.second() == p2); + swap(cp4,cp5); + BOOST_TEST(cp4.first() == p1); + BOOST_TEST(cp4.second() == p2); + BOOST_TEST(cp5.first() == p3); + BOOST_TEST(cp5.second() == p4); +} + +// +// tests for case where one or both +// parameters are reference types: +// +template +struct compressed_pair_reference_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template +void compressed_pair_reference_tester::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) +{ +#ifndef __GNUC__ + // gcc 2.90 can't cope with function scope using + // declarations, and generates an internal compiler error... + using std::swap; +#endif + // both param construct: + boost::compressed_pair cp4(p1, p2); + BOOST_TEST(cp4.first() == p1); + BOOST_TEST(cp4.second() == p2); + boost::compressed_pair cp5(p3, p4); + BOOST_TEST(cp5.first() == p3); + BOOST_TEST(cp5.second() == p4); + // check const members: + const boost::compressed_pair& cpr1 = cp4; + BOOST_TEST(cpr1.first() == p1); + BOOST_TEST(cpr1.second() == p2); + + // copy construct: + boost::compressed_pair cp6(cp4); + BOOST_TEST(cp6.first() == p1); + BOOST_TEST(cp6.second() == p2); + // assignment: + // VC6 bug: + // When second() is an empty class, VC6 performs the + // assignment by doing a memcpy - even though the empty + // class is really a zero sized base class, the result + // is that the memory of first() gets trampled over. + // Similar arguments apply to the case that first() is + // an empty base class. + // Strangely the problem is dependent upon the compiler + // settings - some generate the problem others do not. + cp4.first() = p3; + cp4.second() = p4; + BOOST_TEST(cp4.first() == p3); + BOOST_TEST(cp4.second() == p4); +} +// +// supplimentary tests for case where first arg only is a reference type: +// +template +struct compressed_pair_reference1_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template +void compressed_pair_reference1_tester::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) +{ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // first param construct: + boost::compressed_pair cp2(p1); + cp2.second() = p2; + BOOST_TEST(cp2.first() == p1); + BOOST_TEST(cp2.second() == p2); +#endif +} +// +// supplimentary tests for case where second arg only is a reference type: +// +template +struct compressed_pair_reference2_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template +void compressed_pair_reference2_tester::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) +{ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + // second param construct: + boost::compressed_pair cp3(p2); + cp3.first() = p1; + BOOST_TEST(cp3.second() == p2); + BOOST_TEST(cp3.first() == p1); +#endif +} + +// +// tests for where one or the other parameter is an array: +// +template +struct compressed_pair_array1_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template +void compressed_pair_array1_tester::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) +{ + // default construct: + boost::compressed_pair cp1; + // second param construct: + boost::compressed_pair cp3(p2); + cp3.first()[0] = p1[0]; + BOOST_TEST(cp3.second() == p2); + BOOST_TEST(cp3.first()[0] == p1[0]); + // check const members: + const boost::compressed_pair& cpr1 = cp3; + BOOST_TEST(cpr1.first()[0] == p1[0]); + BOOST_TEST(cpr1.second() == p2); + + BOOST_TEST(sizeof(T1) == sizeof(cp1.first())); +} + +template +struct compressed_pair_array2_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template +void compressed_pair_array2_tester::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) +{ + // default construct: + boost::compressed_pair cp1; + // first param construct: + boost::compressed_pair cp2(p1); + cp2.second()[0] = p2[0]; + BOOST_TEST(cp2.first() == p1); + BOOST_TEST(cp2.second()[0] == p2[0]); + // check const members: + const boost::compressed_pair& cpr1 = cp2; + BOOST_TEST(cpr1.first() == p1); + BOOST_TEST(cpr1.second()[0] == p2[0]); + + BOOST_TEST(sizeof(T2) == sizeof(cp1.second())); +} + +template +struct compressed_pair_array_tester +{ + // define the types we need: + typedef T1 first_type; + typedef T2 second_type; + typedef typename call_traits::param_type first_param_type; + typedef typename call_traits::param_type second_param_type; + // define our test proc: + static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); +}; + +template +void compressed_pair_array_tester::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) +{ + // default construct: + boost::compressed_pair cp1; + cp1.first()[0] = p1[0]; + cp1.second()[0] = p2[0]; + BOOST_TEST(cp1.first()[0] == p1[0]); + BOOST_TEST(cp1.second()[0] == p2[0]); + // check const members: + const boost::compressed_pair& cpr1 = cp1; + BOOST_TEST(cpr1.first()[0] == p1[0]); + BOOST_TEST(cpr1.second()[0] == p2[0]); + + BOOST_TEST(sizeof(T1) == sizeof(cp1.first())); + BOOST_TEST(sizeof(T2) == sizeof(cp1.second())); +} + +int main() +{ + // declare some variables to pass to the tester: + non_empty1 ne1(2); + non_empty1 ne2(3); + non_empty2 ne3(4); + non_empty2 ne4(5); + empty_POD_UDT e1; + empty_UDT e2; + + // T1 != T2, both non-empty + compressed_pair_tester::test(ne1, ne3, ne2, ne4); + // T1 != T2, T2 empty + compressed_pair_tester::test(ne1, e1, ne2, e1); + // T1 != T2, T1 empty + compressed_pair_tester::test(e1, ne3, e1, ne4); + // T1 != T2, both empty + compressed_pair_tester::test(e1, e2, e1, e2); + // T1 == T2, both non-empty + compressed_pair_tester::test(ne1, ne1, ne2, ne2); + // T1 == T2, both empty + compressed_pair_tester::test(e2, e2, e2, e2); + + + // test references: + + // T1 != T2, both non-empty + compressed_pair_reference_tester::test(ne1, ne3, ne2, ne4); + compressed_pair_reference_tester::test(ne1, ne3, ne2, ne4); + compressed_pair_reference1_tester::test(ne1, ne3, ne2, ne4); + compressed_pair_reference2_tester::test(ne1, ne3, ne2, ne4); + // T1 != T2, T2 empty + compressed_pair_reference_tester::test(ne1, e1, ne2, e1); + compressed_pair_reference1_tester::test(ne1, e1, ne2, e1); + // T1 != T2, T1 empty + compressed_pair_reference_tester::test(e1, ne3, e1, ne4); + compressed_pair_reference2_tester::test(e1, ne3, e1, ne4); + // T1 == T2, both non-empty + compressed_pair_reference_tester::test(ne1, ne1, ne2, ne2); + + // tests arrays: + non_empty1 nea1[2]; + non_empty1 nea2[2]; + non_empty2 nea3[2]; + non_empty2 nea4[2]; + nea1[0] = non_empty1(5); + nea2[0] = non_empty1(6); + nea3[0] = non_empty2(7); + nea4[0] = non_empty2(8); + + // T1 != T2, both non-empty + compressed_pair_array1_tester::test(nea1, ne3, nea2, ne4); + compressed_pair_array2_tester::test(ne1, nea3, ne2, nea4); + compressed_pair_array_tester::test(nea1, nea3, nea2, nea4); + // T1 != T2, T2 empty + compressed_pair_array1_tester::test(nea1, e1, nea2, e1); + // T1 != T2, T1 empty + compressed_pair_array2_tester::test(e1, nea3, e1, nea4); + // T1 == T2, both non-empty + compressed_pair_array_tester::test(nea1, nea1, nea2, nea2); + return boost::report_errors(); +} diff --git a/libs/utility/test/initialized_test.cpp b/libs/utility/test/initialized_test.cpp new file mode 100644 index 00000000..0b8852f1 --- /dev/null +++ b/libs/utility/test/initialized_test.cpp @@ -0,0 +1,116 @@ +// Copyright 2010, Niels Dekker. +// +// 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) +// +// Test program for boost::initialized. +// +// 2 May 2010 (Created) Niels Dekker + +#include +#include + +#include + +namespace +{ + // Typical use case for boost::initialized: A generic class that + // holds a value of type T, which must be initialized by either + // value-initialization or direct-initialization. + template class key_value_pair + { + std::string m_key; + boost::initialized m_value; + public: + + // Value-initializes the object held by m_value. + key_value_pair() { } + + // Value-initializes the object held by m_value. + explicit key_value_pair(const std::string& key) + : + m_key(key) + { + } + + // Direct-initializes the object held by m_value. + key_value_pair(const std::string& key, const T& value) + : + m_key(key), m_value(value) + { + } + + const T& get_value() const + { + return m_value; + } + }; + + + // Tells whether the argument is value-initialized. + bool is_value_initialized(const int& arg) + { + return arg == 0; + } + + + // Tells whether the argument is value-initialized. + bool is_value_initialized(const std::string& arg) + { + return arg.empty(); + } + + struct foo + { + int data; + }; + + bool operator==(const foo& lhs, const foo& rhs) + { + return lhs.data == rhs.data; + } + + + // Tells whether the argument is value-initialized. + bool is_value_initialized(const foo& arg) + { + return arg.data == 0; + } + + + template + void test_key_value_pair(const T& magic_value) + { + // The value component of a default key_value_pair must be value-initialized. + key_value_pair default_key_value_pair; + BOOST_TEST( is_value_initialized(default_key_value_pair.get_value() ) ); + + // The value component of a key_value_pair that only has its key explicitly specified + // must also be value-initialized. + BOOST_TEST( is_value_initialized(key_value_pair("key").get_value()) ); + + // However, the value component of the following key_value_pair must be + // "magic_value", as it must be direct-initialized. + BOOST_TEST( key_value_pair("key", magic_value).get_value() == magic_value ); + } +} + + +// Tests boost::initialize for a fundamental type, a type with a +// user-defined constructor, and a user-defined type without +// a user-defined constructor. +int main() +{ + + const int magic_number = 42; + test_key_value_pair(magic_number); + + const std::string magic_string = "magic value"; + test_key_value_pair(magic_string); + + const foo magic_foo = { 42 }; + test_key_value_pair(magic_foo); + + return boost::report_errors(); +} diff --git a/libs/utility/test/initialized_test_fail1.cpp b/libs/utility/test/initialized_test_fail1.cpp new file mode 100644 index 00000000..ffeecab5 --- /dev/null +++ b/libs/utility/test/initialized_test_fail1.cpp @@ -0,0 +1,33 @@ +// Copyright 2010, Niels Dekker. +// +// 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) +// +// Test program for boost::initialized. Must fail to compile. +// +// Initial: 2 May 2010 + +#include + +namespace +{ + void direct_initialize_from_int() + { + // Okay: initialized supports direct-initialization from T. + boost::initialized direct_initialized_int(1); + } + + void copy_initialize_from_int() + { + // The following line should not compile, because initialized + // was not intended to supports copy-initialization from T. + boost::initialized copy_initialized_int = 1; + } +} + +int main() +{ + // This should fail to compile, so there is no need to call any function. + return 0; +} diff --git a/libs/utility/test/initialized_test_fail2.cpp b/libs/utility/test/initialized_test_fail2.cpp new file mode 100644 index 00000000..f3fbf391 --- /dev/null +++ b/libs/utility/test/initialized_test_fail2.cpp @@ -0,0 +1,37 @@ +// Copyright 2010, Niels Dekker. +// +// 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) +// +// Test program for boost::initialized. Must fail to compile. +// +// Initial: 2 May 2010 + +#include + +namespace +{ + void from_value_initialized_to_initialized() + { + boost::value_initialized value_initialized_int; + + // Okay: initialized can be initialized by value_initialized. + boost::initialized initialized_int(value_initialized_int); + } + + void from_initialized_to_value_initialized() + { + boost::initialized initialized_int(13); + + // The following line should not compile, because initialized + // should not be convertible to value_initialized. + boost::value_initialized value_initialized_int(initialized_int); + } +} + +int main() +{ + // This should fail to compile, so there is no need to call any function. + return 0; +} diff --git a/libs/utility/test/iterators_test.cpp b/libs/utility/test/iterators_test.cpp new file mode 100644 index 00000000..8f2d04d0 --- /dev/null +++ b/libs/utility/test/iterators_test.cpp @@ -0,0 +1,322 @@ +// Demonstrate and test boost/operators.hpp on std::iterators --------------// + +// (C) Copyright Jeremy Siek 1999. +// 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) + +// See http://www.boost.org for most recent version including documentation. + +// Revision History +// 29 May 01 Factored implementation, added comparison tests, use Test Tools +// library (Daryle Walker) +// 12 Dec 99 Initial version with iterator operators (Jeremy Siek) + +#include + +#include // for BOOST_STATIC_CONSTANT +#include // for boost::random_access_iterator_helper + +#include // for std::ptrdiff_t, std::size_t +#include // for std::strcmp +#include // for std::cout (std::endl, ends, and flush indirectly) +#include // for std::string +#include // for std::stringstream + +# ifdef BOOST_NO_STDC_NAMESPACE + namespace std { using ::strcmp; } +# endif + + +// Iterator test class +template +struct test_iter + : public boost::random_access_iterator_helper< + test_iter, T, std::ptrdiff_t, P, R> +{ + typedef test_iter self; + typedef R Reference; + typedef std::ptrdiff_t Distance; + +public: + explicit test_iter(T* i =0) : _i(i) { } + test_iter(const self& x) : _i(x._i) { } + self& operator=(const self& x) { _i = x._i; return *this; } + Reference operator*() const { return *_i; } + self& operator++() { ++_i; return *this; } + self& operator--() { --_i; return *this; } + self& operator+=(Distance n) { _i += n; return *this; } + self& operator-=(Distance n) { _i -= n; return *this; } + bool operator==(const self& x) const { return _i == x._i; } + bool operator<(const self& x) const { return _i < x._i; } + friend Distance operator-(const self& x, const self& y) { + return x._i - y._i; + } +protected: + P _i; +}; + +// Iterator operator testing classes +class test_opr_base +{ +protected: + // Test data and types + BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u ); + + typedef std::string fruit_array_type[ fruit_length ]; + + static fruit_array_type fruit; + +}; // test_opr_base + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +const std::size_t test_opr_base::fruit_length; +#endif + +template +class test_opr + : public test_opr_base +{ + typedef test_opr self_type; + +public: + // Types + typedef T value_type; + typedef R reference; + typedef P pointer; + + typedef test_iter iter_type; + + // Test controller + static void master_test( char const name[] ); + +private: + // Test data + static iter_type const fruit_begin; + static iter_type const fruit_end; + + // Test parts + static void post_increment_test(); + static void post_decrement_test(); + static void indirect_referral_test(); + static void offset_addition_test(); + static void reverse_offset_addition_test(); + static void offset_subtraction_test(); + static void comparison_test(); + static void indexing_test(); + +}; // test_opr + + +// Class-static data definitions +test_opr_base::fruit_array_type + test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" }; + +template + typename test_opr::iter_type const + test_opr::fruit_begin = test_iter( fruit ); + +template +typename test_opr::iter_type const + test_opr::fruit_end = test_iter( fruit + fruit_length ); + + +// Main testing function +int +main() +{ + using std::string; + + typedef test_opr test1_type; + typedef test_opr test2_type; + + test1_type::master_test( "non-const string" ); + test2_type::master_test( "const string" ); + + return boost::report_errors(); +} + +// Tests for all of the operators added by random_access_iterator_helper +template +void +test_opr::master_test +( + char const name[] +) +{ + std::cout << "Doing test run for " << name << '.' << std::endl; + + post_increment_test(); + post_decrement_test(); + indirect_referral_test(); + offset_addition_test(); + reverse_offset_addition_test(); + offset_subtraction_test(); + comparison_test(); + indexing_test(); +} + +// Test post-increment +template +void +test_opr::post_increment_test +( +) +{ + std::cout << "\tDoing post-increment test." << std::endl; + + std::stringstream oss; + for ( iter_type i = fruit_begin ; i != fruit_end ; ) + { + oss << *i++ << ' '; + } + + BOOST_TEST( oss.str() == "apple orange pear peach grape plum "); +} + +// Test post-decrement +template +void +test_opr::post_decrement_test +( +) +{ + std::cout << "\tDoing post-decrement test." << std::endl; + + std::stringstream oss; + for ( iter_type i = fruit_end ; i != fruit_begin ; ) + { + i--; + oss << *i << ' '; + } + + BOOST_TEST( oss.str() == "plum grape peach pear orange apple "); +} + +// Test indirect structure referral +template +void +test_opr::indirect_referral_test +( +) +{ + std::cout << "\tDoing indirect reference test." << std::endl; + + std::stringstream oss; + for ( iter_type i = fruit_begin ; i != fruit_end ; ++i ) + { + oss << i->size() << ' '; + } + + BOOST_TEST( oss.str() == "5 6 4 5 5 4 "); +} + +// Test offset addition +template +void +test_opr::offset_addition_test +( +) +{ + std::cout << "\tDoing offset addition test." << std::endl; + + std::ptrdiff_t const two = 2; + std::stringstream oss; + for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two ) + { + oss << *i << ' '; + } + + BOOST_TEST( oss.str() == "apple pear grape "); +} + +// Test offset addition, in reverse order +template +void +test_opr::reverse_offset_addition_test +( +) +{ + std::cout << "\tDoing reverse offset addition test." << std::endl; + + std::ptrdiff_t const two = 2; + std::stringstream oss; + for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i ) + { + oss << *i << ' '; + } + + BOOST_TEST( oss.str() == "apple pear grape "); +} + +// Test offset subtraction +template +void +test_opr::offset_subtraction_test +( +) +{ + std::cout << "\tDoing offset subtraction test." << std::endl; + + std::ptrdiff_t const two = 2; + std::stringstream oss; + for ( iter_type i = fruit_end ; fruit_begin < i ; ) + { + i = i - two; + if ( (fruit_begin < i) || (fruit_begin == i) ) + { + oss << *i << ' '; + } + } + + BOOST_TEST( oss.str() == "grape pear apple "); +} + +// Test comparisons +template +void +test_opr::comparison_test +( +) +{ + using std::cout; + using std::ptrdiff_t; + + cout << "\tDoing comparison tests.\n\t\tPass:"; + + for ( iter_type i = fruit_begin ; i != fruit_end ; ++i ) + { + ptrdiff_t const i_offset = i - fruit_begin; + + cout << ' ' << *i << std::flush; + for ( iter_type j = fruit_begin ; j != fruit_end ; ++j ) + { + ptrdiff_t const j_offset = j - fruit_begin; + + BOOST_TEST( (i != j) == (i_offset != j_offset) ); + BOOST_TEST( (i > j) == (i_offset > j_offset) ); + BOOST_TEST( (i <= j) == (i_offset <= j_offset) ); + BOOST_TEST( (i >= j) == (i_offset >= j_offset) ); + } + } + cout << std::endl; +} + +// Test indexing +template +void +test_opr::indexing_test +( +) +{ + std::cout << "\tDoing indexing test." << std::endl; + + std::stringstream oss; + for ( std::size_t k = 0u ; k < fruit_length ; ++k ) + { + oss << fruit_begin[ k ] << ' '; + } + + BOOST_TEST( oss.str() == "apple orange pear peach grape plum "); +} diff --git a/libs/utility/test/operators_constexpr_test.cpp b/libs/utility/test/operators_constexpr_test.cpp new file mode 100644 index 00000000..02d31868 --- /dev/null +++ b/libs/utility/test/operators_constexpr_test.cpp @@ -0,0 +1,59 @@ +/* +Copyright 2020 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ + +#include +#if !defined(BOOST_NO_CXX11_CONSTEXPR) && \ + (!defined(BOOST_MSVC) || (BOOST_MSVC >= 1922)) +#include +#include + +namespace { + +class Value + : boost::operators { +public: + BOOST_OPERATORS_CONSTEXPR explicit Value(int v) + : v_(v) { } + + BOOST_OPERATORS_CONSTEXPR bool + operator<(const Value& x) const { + return v_ < x.v_; + } + + BOOST_OPERATORS_CONSTEXPR bool + operator==(const Value& x) const { + return v_ == x.v_; + } + +private: + int v_; +}; + +} // namespace + +BOOST_STATIC_ASSERT(!static_cast(Value(1) == Value(2))); +BOOST_STATIC_ASSERT(Value(1) != Value(2)); +BOOST_STATIC_ASSERT(Value(1) < Value(2)); +BOOST_STATIC_ASSERT(Value(1) <= Value(2)); +BOOST_STATIC_ASSERT(!static_cast(Value(1) > Value(2))); +BOOST_STATIC_ASSERT(!static_cast(Value(1) >= Value(2))); + +BOOST_STATIC_ASSERT(!static_cast(Value(2) == Value(1))); +BOOST_STATIC_ASSERT(Value(2) != Value(1)); +BOOST_STATIC_ASSERT(!static_cast(Value(2) < Value(1))); +BOOST_STATIC_ASSERT(!static_cast(Value(2) <= Value(1))); +BOOST_STATIC_ASSERT(Value(2) > Value(1)); +BOOST_STATIC_ASSERT(Value(2) >= Value(1)); + +BOOST_STATIC_ASSERT(Value(1) == Value(1)); +BOOST_STATIC_ASSERT(!static_cast(Value(1) != Value(1))); +BOOST_STATIC_ASSERT(!static_cast(Value(1) < Value(1))); +BOOST_STATIC_ASSERT(Value(1) <= Value(1)); +BOOST_STATIC_ASSERT(!static_cast(Value(1) > Value(1))); +BOOST_STATIC_ASSERT(Value(1) >= Value(1)); +#endif diff --git a/libs/utility/test/operators_test.cpp b/libs/utility/test/operators_test.cpp new file mode 100644 index 00000000..7e77261f --- /dev/null +++ b/libs/utility/test/operators_test.cpp @@ -0,0 +1,938 @@ +// Demonstrate and test boost/operators.hpp -------------------------------// + +// Copyright Beman Dawes 1999. 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) + +// See http://www.boost.org/libs/utility for documentation. + +// Revision History +// 03 Apr 08 Added convertible_to_bool (Daniel Frey) +// 01 Oct 01 Added tests for "left" operators +// and new grouped operators. (Helmut Zeisel) +// 20 May 01 Output progress messages. Added tests for new operator +// templates. Updated random number generator. Changed tests to +// use Boost Test Tools library. (Daryle Walker) +// 04 Jun 00 Added regression test for a bug I found (David Abrahams) +// 17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy) +// ?? ??? 00 Major update to randomly test all one- and two- argument forms by +// wrapping integral types and comparing the results of operations +// to the results for the raw types (David Abrahams) +// 12 Dec 99 Minor update, output confirmation message. +// 15 Nov 99 Initial version + +#include // for BOOST_MSVC +#include // for the tested items +#include // for boost::detail::minstd_rand +#include + +#include // for std::cout (std::endl indirectly) + +namespace +{ + // avoiding a template version of true_value so as to not confuse VC++ + int true_value(int x) { return x; } + long true_value(long x) { return x; } + signed char true_value(signed char x) { return x; } + unsigned int true_value(unsigned int x) { return x; } + unsigned long true_value(unsigned long x) { return x; } + unsigned char true_value(unsigned char x) { return x; } + + // verify the minimum requirements for some operators + class convertible_to_bool + { + private: + bool _value; + + typedef bool convertible_to_bool::*unspecified_bool_type; + + void operator!() const; + + public: + convertible_to_bool( const bool value ) : _value( value ) {} + + operator unspecified_bool_type() const + { return _value ? &convertible_to_bool::_value : 0; } + }; + + // The use of operators<> here tended to obscure + // interactions with certain compiler bugs + template + class Wrapped1 + : boost::operators > + , boost::shiftable > + { + public: + explicit Wrapped1( T v = T() ) : _value(v) {} + T value() const { return _value; } + + convertible_to_bool operator<(const Wrapped1& x) const + { return _value < x._value; } + convertible_to_bool operator==(const Wrapped1& x) const + { return _value == x._value; } + + Wrapped1& operator+=(const Wrapped1& x) + { _value += x._value; return *this; } + Wrapped1& operator-=(const Wrapped1& x) + { _value -= x._value; return *this; } + Wrapped1& operator*=(const Wrapped1& x) + { _value *= x._value; return *this; } + Wrapped1& operator/=(const Wrapped1& x) + { _value /= x._value; return *this; } + Wrapped1& operator%=(const Wrapped1& x) + { _value %= x._value; return *this; } + Wrapped1& operator|=(const Wrapped1& x) + { _value |= x._value; return *this; } + Wrapped1& operator&=(const Wrapped1& x) + { _value &= x._value; return *this; } + Wrapped1& operator^=(const Wrapped1& x) + { _value ^= x._value; return *this; } + Wrapped1& operator<<=(const Wrapped1& x) + { _value <<= x._value; return *this; } + Wrapped1& operator>>=(const Wrapped1& x) + { _value >>= x._value; return *this; } + Wrapped1& operator++() { ++_value; return *this; } + Wrapped1& operator--() { --_value; return *this; } + + private: + T _value; + }; + template + T true_value(Wrapped1 x) { return x.value(); } + + template + class Wrapped2 + : boost::operators > + , boost::operators2, U> + , boost::shiftable1 + , boost::shiftable2, U > > + { + public: + explicit Wrapped2( T v = T() ) : _value(v) {} + T value() const { return _value; } + + convertible_to_bool operator<(const Wrapped2& x) const + { return _value < x._value; } + convertible_to_bool operator==(const Wrapped2& x) const + { return _value == x._value; } + + Wrapped2& operator+=(const Wrapped2& x) + { _value += x._value; return *this; } + Wrapped2& operator-=(const Wrapped2& x) + { _value -= x._value; return *this; } + Wrapped2& operator*=(const Wrapped2& x) + { _value *= x._value; return *this; } + Wrapped2& operator/=(const Wrapped2& x) + { _value /= x._value; return *this; } + Wrapped2& operator%=(const Wrapped2& x) + { _value %= x._value; return *this; } + Wrapped2& operator|=(const Wrapped2& x) + { _value |= x._value; return *this; } + Wrapped2& operator&=(const Wrapped2& x) + { _value &= x._value; return *this; } + Wrapped2& operator^=(const Wrapped2& x) + { _value ^= x._value; return *this; } + Wrapped2& operator<<=(const Wrapped2& x) + { _value <<= x._value; return *this; } + Wrapped2& operator>>=(const Wrapped2& x) + { _value >>= x._value; return *this; } + Wrapped2& operator++() { ++_value; return *this; } + Wrapped2& operator--() { --_value; return *this; } + + convertible_to_bool operator<(U u) const + { return _value < u; } + convertible_to_bool operator>(U u) const + { return _value > u; } + convertible_to_bool operator==(U u) const + { return _value == u; } + + Wrapped2& operator+=(U u) { _value += u; return *this; } + Wrapped2& operator-=(U u) { _value -= u; return *this; } + Wrapped2& operator*=(U u) { _value *= u; return *this; } + Wrapped2& operator/=(U u) { _value /= u; return *this; } + Wrapped2& operator%=(U u) { _value %= u; return *this; } + Wrapped2& operator|=(U u) { _value |= u; return *this; } + Wrapped2& operator&=(U u) { _value &= u; return *this; } + Wrapped2& operator^=(U u) { _value ^= u; return *this; } + Wrapped2& operator<<=(U u) { _value <<= u; return *this; } + Wrapped2& operator>>=(U u) { _value >>= u; return *this; } + + private: + T _value; + }; + template + T true_value(Wrapped2 x) { return x.value(); } + + template + class Wrapped3 + : boost::equivalent > + , boost::partially_ordered > + , boost::equality_comparable > + { + public: + explicit Wrapped3( T v = T() ) : _value(v) {} + T value() const { return _value; } + + convertible_to_bool operator<(const Wrapped3& x) const + { return _value < x._value; } + + private: + T _value; + }; + template + T true_value(Wrapped3 x) { return x.value(); } + + template + class Wrapped4 + : boost::equality_comparable1 + , boost::equivalent1 + , boost::partially_ordered1 > > > + , boost::partially_ordered2, U + , boost::equivalent2, U + , boost::equality_comparable2, U> > > + { + public: + explicit Wrapped4( T v = T() ) : _value(v) {} + T value() const { return _value; } + + convertible_to_bool operator<(const Wrapped4& x) const + { return _value < x._value; } + + convertible_to_bool operator<(U u) const + { return _value < u; } + convertible_to_bool operator>(U u) const + { return _value > u; } + + private: + T _value; + }; + template + T true_value(Wrapped4 x) { return x.value(); } + + // U must be convertible to T + template + class Wrapped5 + : boost::ordered_field_operators2, U> + , boost::ordered_field_operators1 > + { + public: + explicit Wrapped5( T v = T() ) : _value(v) {} + + // Conversion from U to Wrapped5 + Wrapped5(U u) : _value(u) {} + + T value() const { return _value; } + + convertible_to_bool operator<(const Wrapped5& x) const + { return _value < x._value; } + convertible_to_bool operator<(U u) const + { return _value < u; } + convertible_to_bool operator>(U u) const + { return _value > u; } + convertible_to_bool operator==(const Wrapped5& u) const + { return _value == u._value; } + convertible_to_bool operator==(U u) const + { return _value == u; } + + Wrapped5& operator/=(const Wrapped5& u) { _value /= u._value; return *this;} + Wrapped5& operator/=(U u) { _value /= u; return *this;} + Wrapped5& operator*=(const Wrapped5& u) { _value *= u._value; return *this;} + Wrapped5& operator*=(U u) { _value *= u; return *this;} + Wrapped5& operator-=(const Wrapped5& u) { _value -= u._value; return *this;} + Wrapped5& operator-=(U u) { _value -= u; return *this;} + Wrapped5& operator+=(const Wrapped5& u) { _value += u._value; return *this;} + Wrapped5& operator+=(U u) { _value += u; return *this;} + + private: + T _value; + }; + template + T true_value(Wrapped5 x) { return x.value(); } + + // U must be convertible to T + template + class Wrapped6 + : boost::ordered_euclidean_ring_operators2, U> + , boost::ordered_euclidean_ring_operators1 > + { + public: + explicit Wrapped6( T v = T() ) : _value(v) {} + + // Conversion from U to Wrapped6 + Wrapped6(U u) : _value(u) {} + + T value() const { return _value; } + + convertible_to_bool operator<(const Wrapped6& x) const + { return _value < x._value; } + convertible_to_bool operator<(U u) const + { return _value < u; } + convertible_to_bool operator>(U u) const + { return _value > u; } + convertible_to_bool operator==(const Wrapped6& u) const + { return _value == u._value; } + convertible_to_bool operator==(U u) const + { return _value == u; } + + Wrapped6& operator%=(const Wrapped6& u) { _value %= u._value; return *this;} + Wrapped6& operator%=(U u) { _value %= u; return *this;} + Wrapped6& operator/=(const Wrapped6& u) { _value /= u._value; return *this;} + Wrapped6& operator/=(U u) { _value /= u; return *this;} + Wrapped6& operator*=(const Wrapped6& u) { _value *= u._value; return *this;} + Wrapped6& operator*=(U u) { _value *= u; return *this;} + Wrapped6& operator-=(const Wrapped6& u) { _value -= u._value; return *this;} + Wrapped6& operator-=(U u) { _value -= u; return *this;} + Wrapped6& operator+=(const Wrapped6& u) { _value += u._value; return *this;} + Wrapped6& operator+=(U u) { _value += u; return *this;} + + private: + T _value; + }; + template + T true_value(Wrapped6 x) { return x.value(); } + + // MyInt uses only the single template-argument form of all_operators<> + typedef Wrapped1 MyInt; + + typedef Wrapped2 MyLong; + + typedef Wrapped3 MyChar; + + typedef Wrapped4 MyShort; + + typedef Wrapped5 MyDoubleInt; + + typedef Wrapped6 MyLongInt; + + template + void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + BOOST_TEST( true_value(y1) == true_value(y2) ); + BOOST_TEST( true_value(x1) == true_value(x2) ); + } + + template + void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + BOOST_TEST( static_cast(x1 < y1) == static_cast(x2 < y2) ); + BOOST_TEST( static_cast(x1 <= y1) == static_cast(x2 <= y2) ); + BOOST_TEST( static_cast(x1 >= y1) == static_cast(x2 >= y2) ); + BOOST_TEST( static_cast(x1 > y1) == static_cast(x2 > y2) ); + } + + template + void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_less_than_comparable_aux( x1, y1, x2, y2 ); + test_less_than_comparable_aux( y1, x1, y2, x2 ); + } + + template + void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + BOOST_TEST( static_cast(x1 == y1) == static_cast(x2 == y2) ); + BOOST_TEST( static_cast(x1 != y1) == static_cast(x2 != y2) ); + } + + template + void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_equality_comparable_aux( x1, y1, x2, y2 ); + test_equality_comparable_aux( y1, x1, y2, x2 ); + } + + template + void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + BOOST_TEST( (x1 * y1).value() == (x2 * y2) ); + } + + template + void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_multipliable_aux( x1, y1, x2, y2 ); + test_multipliable_aux( y1, x1, y2, x2 ); + } + + template + void test_value_equality(A a, B b) + { + BOOST_TEST(a.value() == b); + } + +#define TEST_OP_R(op) test_value_equality(x1 op y1, x2 op y2) +#define TEST_OP_L(op) test_value_equality(y1 op x1, y2 op x2) + + template + void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + TEST_OP_R(+); + } + + template + void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_addable_aux( x1, y1, x2, y2 ); + test_addable_aux( y1, x1, y2, x2 ); + } + + template + void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + TEST_OP_R(-); + } + + template + void test_subtractable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + TEST_OP_L(-); + } + + template + void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + if ( y2 != 0 ) + TEST_OP_R(/); + } + + template + void test_dividable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + if ( x2 != 0 ) + TEST_OP_L(/); + } + + template + void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + if ( y2 != 0 ) + TEST_OP_R(%); + } + + template + void test_modable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + if ( x2 != 0 ) + TEST_OP_L(%); + } + + template + void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + TEST_OP_R(^); + } + + template + void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_xorable_aux( x1, y1, x2, y2 ); + test_xorable_aux( y1, x1, y2, x2 ); + } + + template + void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + TEST_OP_R(&); + } + + template + void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_andable_aux( x1, y1, x2, y2 ); + test_andable_aux( y1, x1, y2, x2 ); + } + + template + void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + TEST_OP_R(|); + } + + template + void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + test_orable_aux( x1, y1, x2, y2 ); + test_orable_aux( y1, x1, y2, x2 ); + } + + template + void test_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + TEST_OP_R(<<); + } + + template + void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + sanity_check( x1, y1, x2, y2 ); + TEST_OP_R(>>); + } + + template + void test_incrementable(X1 x1, X2 x2) + { + sanity_check( x1, x1, x2, x2 ); + BOOST_TEST( (x1++).value() == x2++ ); + BOOST_TEST( x1.value() == x2 ); + } + + template + void test_decrementable(X1 x1, X2 x2) + { + sanity_check( x1, x1, x2, x2 ); + BOOST_TEST( (x1--).value() == x2-- ); + BOOST_TEST( x1.value() == x2 ); + } + + template + void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + test_less_than_comparable( x1, y1, x2, y2 ); + test_equality_comparable( x1, y1, x2, y2 ); + test_multipliable( x1, y1, x2, y2 ); + test_addable( x1, y1, x2, y2 ); + test_subtractable( x1, y1, x2, y2 ); + test_dividable( x1, y1, x2, y2 ); + test_modable( x1, y1, x2, y2 ); + test_xorable( x1, y1, x2, y2 ); + test_andable( x1, y1, x2, y2 ); + test_orable( x1, y1, x2, y2 ); + test_left_shiftable( x1, y1, x2, y2 ); + test_right_shiftable( x1, y1, x2, y2 ); + test_incrementable( x1, x2 ); + test_decrementable( x1, x2 ); + } + + template + void test_left(X1 x1, Y1 y1, X2 x2, Y2 y2) + { + test_subtractable_left( x1, y1, x2, y2 ); + test_dividable_left( x1, y1, x2, y2 ); + test_modable_left( x1, y1, x2, y2 ); + } + + template + struct tester + { + void operator()(boost::detail::minstd_rand& randomizer) const + { + Big b1 = Big( randomizer() ); + Big b2 = Big( randomizer() ); + Small s = Small( randomizer() ); + + test_all( Wrapped1(b1), Wrapped1(b2), b1, b2 ); + test_all( Wrapped2(b1), s, b1, s ); + } + }; + + template + struct tester_left + { + void operator()(boost::detail::minstd_rand& randomizer) const + { + Big b1 = Big( randomizer() ); + Small s = Small( randomizer() ); + + test_left( Wrapped6(b1), s, b1, s ); + } + }; + + // added as a regression test. We had a bug which this uncovered. + struct Point + : boost::addable > + { + Point( int h, int v ) : h(h), v(v) {} + Point() :h(0), v(0) {} + const Point& operator+=( const Point& rhs ) + { h += rhs.h; v += rhs.v; return *this; } + const Point& operator-=( const Point& rhs ) + { h -= rhs.h; v -= rhs.v; return *this; } + + int h; + int v; + }; + +} // unnamed namespace + + +// workaround for MSVC bug; for some reasons the compiler doesn't instantiate +// inherited operator templates at the moment it must, so the following +// explicit instantiations force it to do that. + +#if defined(BOOST_MSVC) && (_MSC_VER < 1300) +template Wrapped1; +template Wrapped1; +template Wrapped1; +template Wrapped1; + +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; +template Wrapped2; + +template Wrapped6; +template Wrapped6; +template Wrapped6; +template Wrapped6; +template Wrapped6; +template Wrapped6; +#endif + +#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) ) + +int +main() +{ + using std::cout; + using std::endl; + + // Regression test. + Point x; + x = x + Point(3, 4); + x = x - Point(3, 4); + + cout << "Created point, and operated on it." << endl; + +#if !defined(UBSAN) + // Using random values produce UB in various tests, such as shifting by more than the left operand capacity or signed integer overflows + for (int n = 0; n < 1000; ++n) // was 10,000 but took too long (Beman) + { + boost::detail::minstd_rand r; + tester()(r); + tester()(r); + tester()(r); + tester()(r); + tester()(r); + + tester()(r); + tester()(r); + tester()(r); + tester()(r); + tester()(r); + + tester_left()(r); + tester_left()(r); + tester_left()(r); + + tester_left()(r); + tester_left()(r); + tester_left()(r); + } + + cout << "Did random tester loop." << endl; +#endif // !defined(UBSAN) + + MyInt i1(1); + MyInt i2(2); + MyInt i; + + BOOST_TEST( i1.value() == 1 ); + BOOST_TEST( i2.value() == 2 ); + BOOST_TEST( i.value() == 0 ); + + cout << "Created MyInt objects.\n"; + + PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) ); + + BOOST_TEST( static_cast(i2 == i) ); + BOOST_TEST( static_cast(i1 != i2) ); + BOOST_TEST( static_cast(i1 < i2) ); + BOOST_TEST( static_cast(i1 <= i2) ); + BOOST_TEST( static_cast(i <= i2) ); + BOOST_TEST( static_cast(i2 > i1) ); + BOOST_TEST( static_cast(i2 >= i1) ); + BOOST_TEST( static_cast(i2 >= i) ); + + PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) ); + PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) ); + PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) ); + PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) ); + PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) ); + PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) ); + PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) ); + PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) ); + PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) ); + PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) ); + PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) ); + PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) ); + + PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) ); + PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) ); + + cout << "Performed tests on MyInt objects.\n"; + + MyLong j1(1); + MyLong j2(2); + MyLong j; + + BOOST_TEST( j1.value() == 1 ); + BOOST_TEST( j2.value() == 2 ); + BOOST_TEST( j.value() == 0 ); + + cout << "Created MyLong objects.\n"; + + PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) ); + + BOOST_TEST( static_cast(j2 == j) ); + BOOST_TEST( static_cast(2 == j) ); + BOOST_TEST( static_cast(j2 == 2) ); + BOOST_TEST( static_cast(j == j2) ); + BOOST_TEST( static_cast(j1 != j2) ); + BOOST_TEST( static_cast(j1 != 2) ); + BOOST_TEST( static_cast(1 != j2) ); + BOOST_TEST( static_cast(j1 < j2) ); + BOOST_TEST( static_cast(1 < j2) ); + BOOST_TEST( static_cast(j1 < 2) ); + BOOST_TEST( static_cast(j1 <= j2) ); + BOOST_TEST( static_cast(1 <= j2) ); + BOOST_TEST( static_cast(j1 <= j) ); + BOOST_TEST( static_cast(j <= j2) ); + BOOST_TEST( static_cast(2 <= j2) ); + BOOST_TEST( static_cast(j <= 2) ); + BOOST_TEST( static_cast(j2 > j1) ); + BOOST_TEST( static_cast(2 > j1) ); + BOOST_TEST( static_cast(j2 > 1) ); + BOOST_TEST( static_cast(j2 >= j1) ); + BOOST_TEST( static_cast(2 >= j1) ); + BOOST_TEST( static_cast(j2 >= 1) ); + BOOST_TEST( static_cast(j2 >= j) ); + BOOST_TEST( static_cast(2 >= j) ); + BOOST_TEST( static_cast(j2 >= 2) ); + + BOOST_TEST( static_cast((j1 + 2) == 3) ); + BOOST_TEST( static_cast((1 + j2) == 3) ); + PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) ); + + BOOST_TEST( static_cast((j + 2) == 5) ); + BOOST_TEST( static_cast((3 + j2) == 5) ); + PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) ); + + BOOST_TEST( static_cast((j - 1) == 4) ); + PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) ); + + BOOST_TEST( static_cast((j * 2) == 8) ); + BOOST_TEST( static_cast((4 * j2) == 8) ); + PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) ); + + BOOST_TEST( static_cast((j / 2) == 4) ); + PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) ); + + BOOST_TEST( static_cast((j % 3) == 1) ); + PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) ); + + PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) ); + + BOOST_TEST( static_cast((1 | j2 | j) == 7) ); + BOOST_TEST( static_cast((j1 | 2 | j) == 7) ); + BOOST_TEST( static_cast((j1 | j2 | 4) == 7) ); + PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) ); + + BOOST_TEST( static_cast((7 & j2) == 2) ); + BOOST_TEST( static_cast((j & 2) == 2) ); + PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) ); + + PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) ); + + BOOST_TEST( static_cast((3 ^ j1) == 2) ); + BOOST_TEST( static_cast((j ^ 1) == 2) ); + PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) ); + + PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) ); + + BOOST_TEST( static_cast((j1 << 2) == 4) ); + BOOST_TEST( static_cast((j2 << 1) == 4) ); + PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) ); + + BOOST_TEST( static_cast((j >> 2) == 1) ); + BOOST_TEST( static_cast((j2 >> 1) == 1) ); + PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) ); + + cout << "Performed tests on MyLong objects.\n"; + + MyChar k1(1); + MyChar k2(2); + MyChar k; + + BOOST_TEST( k1.value() == 1 ); + BOOST_TEST( k2.value() == 2 ); + BOOST_TEST( k.value() == 0 ); + + cout << "Created MyChar objects.\n"; + + PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) ); + + BOOST_TEST( static_cast(k2 == k) ); + BOOST_TEST( static_cast(k1 != k2) ); + BOOST_TEST( static_cast(k1 < k2) ); + BOOST_TEST( static_cast(k1 <= k2) ); + BOOST_TEST( static_cast(k <= k2) ); + BOOST_TEST( static_cast(k2 > k1) ); + BOOST_TEST( static_cast(k2 >= k1) ); + BOOST_TEST( static_cast(k2 >= k) ); + + cout << "Performed tests on MyChar objects.\n"; + + MyShort l1(1); + MyShort l2(2); + MyShort l; + + BOOST_TEST( l1.value() == 1 ); + BOOST_TEST( l2.value() == 2 ); + BOOST_TEST( l.value() == 0 ); + + cout << "Created MyShort objects.\n"; + + PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) ); + + BOOST_TEST( static_cast(l2 == l) ); + BOOST_TEST( static_cast(2 == l) ); + BOOST_TEST( static_cast(l2 == 2) ); + BOOST_TEST( static_cast(l == l2) ); + BOOST_TEST( static_cast(l1 != l2) ); + BOOST_TEST( static_cast(l1 != 2) ); + BOOST_TEST( static_cast(1 != l2) ); + BOOST_TEST( static_cast(l1 < l2) ); + BOOST_TEST( static_cast(1 < l2) ); + BOOST_TEST( static_cast(l1 < 2) ); + BOOST_TEST( static_cast(l1 <= l2) ); + BOOST_TEST( static_cast(1 <= l2) ); + BOOST_TEST( static_cast(l1 <= l) ); + BOOST_TEST( static_cast(l <= l2) ); + BOOST_TEST( static_cast(2 <= l2) ); + BOOST_TEST( static_cast(l <= 2) ); + BOOST_TEST( static_cast(l2 > l1) ); + BOOST_TEST( static_cast(2 > l1) ); + BOOST_TEST( static_cast(l2 > 1) ); + BOOST_TEST( static_cast(l2 >= l1) ); + BOOST_TEST( static_cast(2 >= l1) ); + BOOST_TEST( static_cast(l2 >= 1) ); + BOOST_TEST( static_cast(l2 >= l) ); + BOOST_TEST( static_cast(2 >= l) ); + BOOST_TEST( static_cast(l2 >= 2) ); + + cout << "Performed tests on MyShort objects.\n"; + + MyDoubleInt di1(1); + MyDoubleInt di2(2.); + MyDoubleInt half(0.5); + MyDoubleInt di; + MyDoubleInt tmp; + + BOOST_TEST( di1.value() == 1 ); + BOOST_TEST( di2.value() == 2 ); + BOOST_TEST( di2.value() == 2 ); + BOOST_TEST( di.value() == 0 ); + + cout << "Created MyDoubleInt objects.\n"; + + PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) ); + + BOOST_TEST( static_cast(di2 == di) ); + BOOST_TEST( static_cast(2 == di) ); + BOOST_TEST( static_cast(di == 2) ); + BOOST_TEST( static_cast(di1 < di2) ); + BOOST_TEST( static_cast(1 < di2) ); + BOOST_TEST( static_cast(di1 <= di2) ); + BOOST_TEST( static_cast(1 <= di2) ); + BOOST_TEST( static_cast(di2 > di1) ); + BOOST_TEST( static_cast(di2 > 1) ); + BOOST_TEST( static_cast(di2 >= di1) ); + BOOST_TEST( static_cast(di2 >= 1) ); + BOOST_TEST( static_cast(di1 / di2 == half) ); + BOOST_TEST( static_cast(di1 / 2 == half) ); + BOOST_TEST( static_cast(1 / di2 == half) ); + PRIVATE_EXPR_TEST( (tmp=di1), static_cast((tmp/=2) == half) ); + PRIVATE_EXPR_TEST( (tmp=di1), static_cast((tmp/=di2) == half) ); + BOOST_TEST( static_cast(di1 * di2 == di2) ); + BOOST_TEST( static_cast(di1 * 2 == di2) ); + BOOST_TEST( static_cast(1 * di2 == di2) ); + PRIVATE_EXPR_TEST( (tmp=di1), static_cast((tmp*=2) == di2) ); + PRIVATE_EXPR_TEST( (tmp=di1), static_cast((tmp*=di2) == di2) ); + BOOST_TEST( static_cast(di2 - di1 == di1) ); + BOOST_TEST( static_cast(di2 - 1 == di1) ); + BOOST_TEST( static_cast(2 - di1 == di1) ); + PRIVATE_EXPR_TEST( (tmp=di2), static_cast((tmp-=1) == di1) ); + PRIVATE_EXPR_TEST( (tmp=di2), static_cast((tmp-=di1) == di1) ); + BOOST_TEST( static_cast(di1 + di1 == di2) ); + BOOST_TEST( static_cast(di1 + 1 == di2) ); + BOOST_TEST( static_cast(1 + di1 == di2) ); + PRIVATE_EXPR_TEST( (tmp=di1), static_cast((tmp+=1) == di2) ); + PRIVATE_EXPR_TEST( (tmp=di1), static_cast((tmp+=di1) == di2) ); + + cout << "Performed tests on MyDoubleInt objects.\n"; + + MyLongInt li1(1); + MyLongInt li2(2); + MyLongInt li; + MyLongInt tmp2; + + BOOST_TEST( li1.value() == 1 ); + BOOST_TEST( li2.value() == 2 ); + BOOST_TEST( li.value() == 0 ); + + cout << "Created MyLongInt objects.\n"; + + PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) ); + + BOOST_TEST( static_cast(li2 == li) ); + BOOST_TEST( static_cast(2 == li) ); + BOOST_TEST( static_cast(li == 2) ); + BOOST_TEST( static_cast(li1 < li2) ); + BOOST_TEST( static_cast(1 < li2) ); + BOOST_TEST( static_cast(li1 <= li2) ); + BOOST_TEST( static_cast(1 <= li2) ); + BOOST_TEST( static_cast(li2 > li1) ); + BOOST_TEST( static_cast(li2 > 1) ); + BOOST_TEST( static_cast(li2 >= li1) ); + BOOST_TEST( static_cast(li2 >= 1) ); + BOOST_TEST( static_cast(li1 % li2 == li1) ); + BOOST_TEST( static_cast(li1 % 2 == li1) ); + BOOST_TEST( static_cast(1 % li2 == li1) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast((tmp2%=2) == li1) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast((tmp2%=li2) == li1) ); + BOOST_TEST( static_cast(li1 / li2 == 0) ); + BOOST_TEST( static_cast(li1 / 2 == 0) ); + BOOST_TEST( static_cast(1 / li2 == 0) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast((tmp2/=2) == 0) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast((tmp2/=li2) == 0) ); + BOOST_TEST( static_cast(li1 * li2 == li2) ); + BOOST_TEST( static_cast(li1 * 2 == li2) ); + BOOST_TEST( static_cast(1 * li2 == li2) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast((tmp2*=2) == li2) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast((tmp2*=li2) == li2) ); + BOOST_TEST( static_cast(li2 - li1 == li1) ); + BOOST_TEST( static_cast(li2 - 1 == li1) ); + BOOST_TEST( static_cast(2 - li1 == li1) ); + PRIVATE_EXPR_TEST( (tmp2=li2), static_cast((tmp2-=1) == li1) ); + PRIVATE_EXPR_TEST( (tmp2=li2), static_cast((tmp2-=li1) == li1) ); + BOOST_TEST( static_cast(li1 + li1 == li2) ); + BOOST_TEST( static_cast(li1 + 1 == li2) ); + BOOST_TEST( static_cast(1 + li1 == li2) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast((tmp2+=1) == li2) ); + PRIVATE_EXPR_TEST( (tmp2=li1), static_cast((tmp2+=li1) == li2) ); + + cout << "Performed tests on MyLongInt objects.\n"; + + return boost::report_errors(); +} diff --git a/libs/utility/test/result_of_test.cpp b/libs/utility/test/result_of_test.cpp new file mode 100644 index 00000000..290043b3 --- /dev/null +++ b/libs/utility/test/result_of_test.cpp @@ -0,0 +1,322 @@ +// Boost result_of library + +// Copyright Douglas Gregor 2003-2004. Use, modification and +// distribution is subject to 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) + +// Examples: +// To run the default test: +// $ cd libs/utility/test && bjam +// To test decltype on g++ 2.7: +// $ cd libs/utility/test && bjam cxxflags="-std=c++11 -D BOOST_RESULT_OF_USE_DECLTYPE" + +#include + +// For more information, see http://www.boost.org/libs/utility +#include +#include +#include +#include + +struct int_result_type +{ + typedef int result_type; + result_type operator()(float); +}; + +struct int_result_of +{ + template struct result { typedef int type; }; + result::type operator()(double); + result::type operator()(double) const; + result::type operator()(); + result::type operator()() volatile; +}; + +struct int_result_type_and_float_result_of_and_char_return +{ + typedef int result_type; + template struct result { typedef float type; }; + char operator()(char); +}; + +template +struct int_result_type_template +{ + typedef int result_type; + result_type operator()(float); +}; + +template +struct int_result_of_template +{ + template struct result; + template struct result { typedef int type; }; + typename result(double)>::type operator()(double); + typename result(double)>::type operator()(double) const; + typename result(double)>::type operator()(); + typename result(double)>::type operator()() volatile; +}; + +template +struct int_result_type_and_float_result_of_and_char_return_template +{ + typedef int result_type; + template struct result; + template struct result { typedef float type; }; + char operator()(char); +}; + +template +struct cv_overload_check {}; + +struct result_of_member_function_template +{ + template struct result; + + template struct result { typedef That type; }; + template typename result::type operator()(T); + + template struct result { typedef cv_overload_check type; }; + template typename result::type operator()(T) const; + + template struct result { typedef cv_overload_check type; }; + template typename result::type operator()(T) volatile; + + template struct result { typedef cv_overload_check type; }; + template typename result::type operator()(T) const volatile; + + template struct result { typedef That & type; }; + template typename result::type operator()(T &, T); + + template struct result { typedef That const & type; }; + template typename result::type operator()(T const &, T); + + template struct result { typedef That volatile & type; }; + template typename result::type operator()(T volatile &, T); + + template struct result { typedef That const volatile & type; }; + template typename result::type operator()(T const volatile &, T); +}; + +struct no_result_type_or_result +{ + short operator()(double); + cv_overload_check operator()(double) const; + cv_overload_check operator()(double) volatile; + cv_overload_check operator()(double) const volatile; + int operator()(); + cv_overload_check operator()() const; + cv_overload_check operator()() volatile; + cv_overload_check operator()() const volatile; +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + short operator()(int&&); + int operator()(int&); + long operator()(int const&); +#endif +}; + +template +struct no_result_type_or_result_template +{ + short operator()(double); + cv_overload_check operator()(double) const; + cv_overload_check operator()(double) volatile; + cv_overload_check operator()(double) const volatile; + int operator()(); + cv_overload_check operator()() const; + cv_overload_check operator()() volatile; + cv_overload_check operator()() const volatile; +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + short operator()(int&&); + int operator()(int&); + long operator()(int const&); +#endif +}; + +// sfinae_tests are derived from example code from Joel de Guzman, +// which demonstrated the interaction between result_of and SFINAE. +template +typename boost::result_of::type +sfinae_test(F f, Arg const& arg) +{ + return f(arg); +} + +template +typename boost::result_of::type +sfinae_test(F f, Arg& arg) +{ + return f(arg); +} + +int sfinae_test_f(int& i) +{ + return i; +} + +struct X {}; + +int main() +{ + using namespace boost; + + typedef int (*func_ptr)(float, double); + typedef int (&func_ref)(float, double); + typedef int (*func_ptr_0)(); + typedef int (&func_ref_0)(); + typedef void (*func_ptr_void)(float, double); + typedef void (&func_ref_void)(float, double); + typedef void (*func_ptr_void_0)(); + typedef void (&func_ref_void_0)(); + typedef int (X::*mem_func_ptr)(float); + typedef int (X::*mem_func_ptr_c)(float) const; + typedef int (X::*mem_func_ptr_v)(float) volatile; + typedef int (X::*mem_func_ptr_cv)(float) const volatile; + typedef int (X::*mem_func_ptr_0)(); + + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(float)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(double)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(double)>::type, int>::value)); + + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(float)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(double)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(double)>::type, int>::value)); + + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, void>::value)); + + // Prior to decltype, result_of could not deduce the return type + // of nullary function objects unless they exposed a result_type. +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, int>::value)); +#else + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, void>::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, void>::value)); +#endif + + // Prior to decltype, result_of ignored a nested result<> if + // result_type was defined. After decltype, result_of deduces the + // actual return type of the function object, ignoring both + // result<> and result_type. +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) + BOOST_STATIC_ASSERT((is_same::type, char>::value)); + BOOST_STATIC_ASSERT((is_same(char)>::type, char>::value)); +#else + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(char)>::type, int>::value)); +#endif + + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(char)>::type, int>::value)); + + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + + BOOST_STATIC_ASSERT((is_same::type, double>::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, int &>::value)); + BOOST_STATIC_ASSERT((is_same::type, int const &>::value)); + BOOST_STATIC_ASSERT((is_same::type, int volatile &>::value)); + BOOST_STATIC_ASSERT((is_same::type, int const volatile &>::value)); + + BOOST_STATIC_ASSERT((is_same::type, double>::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, int &>::value)); + BOOST_STATIC_ASSERT((is_same::type, int const &>::value)); + BOOST_STATIC_ASSERT((is_same::type, int volatile &>::value)); + BOOST_STATIC_ASSERT((is_same::type, int const volatile &>::value)); + + typedef int (*pf_t)(int); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type,int>::value)); + + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type,int>::value)); + +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) + BOOST_STATIC_ASSERT((is_same::type, short>::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + + BOOST_STATIC_ASSERT((is_same(double)>::type, short>::value)); + BOOST_STATIC_ASSERT((is_same(double)>::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same(double)>::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same(double)>::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value)); + + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_STATIC_ASSERT((is_same::type, short>::value)); + BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, long>::value)); + BOOST_STATIC_ASSERT((is_same(int&&)>::type, short>::value)); + BOOST_STATIC_ASSERT((is_same(int&)>::type, int>::value)); + BOOST_STATIC_ASSERT((is_same(int const&)>::type, long>::value)); +#endif +#endif + +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) + int i = 123; + sfinae_test(sfinae_test_f, i); +#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) + + return 0; +} diff --git a/libs/utility/test/string_ref_from_rvalue.cpp b/libs/utility/test/string_ref_from_rvalue.cpp new file mode 100644 index 00000000..6ec8a5a2 --- /dev/null +++ b/libs/utility/test/string_ref_from_rvalue.cpp @@ -0,0 +1,26 @@ +/* + Copyright (c) Marshall Clow 2017. + + 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) + + For more information, see http://www.boost.org +*/ + +#include +#include +#include + +#include + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) +#error "Unsupported test" +#endif + +std::string makeatemp() { return "abc"; } + +int main() +{ + boost::basic_string_ref sv(makeatemp()); + return 0; +} diff --git a/libs/utility/test/string_ref_test1.cpp b/libs/utility/test/string_ref_test1.cpp new file mode 100644 index 00000000..5ab8869f --- /dev/null +++ b/libs/utility/test/string_ref_test1.cpp @@ -0,0 +1,111 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org +*/ + +#include +#include +#include +#include + +#include + +#include + +typedef boost::string_ref string_ref; + +// Should be equal +void interop ( const std::string &str, string_ref ref ) { +// BOOST_TEST ( str == ref ); + BOOST_TEST ( str.size () == ref.size ()); + BOOST_TEST ( std::equal ( str.begin (), str.end (), ref.begin ())); + BOOST_TEST ( std::equal ( str.rbegin (), str.rend (), ref.rbegin ())); + } + +void null_tests ( const char *p ) { +// All zero-length string-refs should be equal + string_ref sr1; // NULL, 0 + string_ref sr2 ( NULL, 0 ); + string_ref sr3 ( p, 0 ); + string_ref sr4 ( p ); + sr4.clear (); + + BOOST_TEST ( sr1 == sr2 ); + BOOST_TEST ( sr1 == sr3 ); + BOOST_TEST ( sr2 == sr3 ); + BOOST_TEST ( sr1 == sr4 ); + } + +// make sure that substrings work just like strings +void test_substr ( const std::string &str ) { + const std::size_t sz = str.size (); + string_ref ref ( str ); + +// Substrings at the end + for ( std::size_t i = 0; i <= sz; ++ i ) + interop ( str.substr ( i ), ref.substr ( i )); + +// Substrings at the beginning + for ( std::size_t i = 0; i <= sz; ++ i ) + interop ( str.substr ( 0, i ), ref.substr ( 0, i )); + +// All possible substrings + for ( std::size_t i = 0; i < sz; ++i ) + for ( std::size_t j = i; j < sz; ++j ) + interop ( str.substr ( i, j ), ref.substr ( i, j )); + } + +// make sure that removing prefixes and suffixes work just like strings +void test_remove ( const std::string &str ) { + const std::size_t sz = str.size (); + std::string work; + string_ref ref; + + for ( std::size_t i = 1; i <= sz; ++i ) { + work = str; + ref = str; + while ( ref.size () >= i ) { + interop ( work, ref ); + work.erase ( 0, i ); + ref.remove_prefix (i); + } + } + + for ( std::size_t i = 1; i < sz; ++ i ) { + work = str; + ref = str; + while ( ref.size () >= i ) { + interop ( work, ref ); + work.erase ( work.size () - i, i ); + ref.remove_suffix (i); + } + } + } + +const char *test_strings [] = { + "", + "1", + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + "0123456789", + NULL + }; + +int main() +{ + const char **p = &test_strings[0]; + + while ( *p != NULL ) { + interop ( *p, *p ); + test_substr ( *p ); + test_remove ( *p ); + null_tests ( *p ); + + p++; + } + + return boost::report_errors(); +} diff --git a/libs/utility/test/string_ref_test2.cpp b/libs/utility/test/string_ref_test2.cpp new file mode 100644 index 00000000..59c699b1 --- /dev/null +++ b/libs/utility/test/string_ref_test2.cpp @@ -0,0 +1,325 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org +*/ + +#include +#include +#include // for std::strchr +#include +#include + +#include + +#include + +typedef boost::string_ref string_ref; + +void ends_with ( const char *arg ) { + const std::size_t sz = std::strlen ( arg ); + string_ref sr ( arg ); + string_ref sr2 ( arg ); + const char *p = arg; + + while ( *p ) { + BOOST_TEST ( sr.ends_with ( p )); + ++p; + } + + while ( !sr2.empty ()) { + BOOST_TEST ( sr.ends_with ( sr2 )); + sr2.remove_prefix (1); + } + + sr2 = arg; + while ( !sr2.empty ()) { + BOOST_TEST ( sr.ends_with ( sr2 )); + sr2.remove_prefix (1); + } + + char ch = sz == 0 ? '\0' : arg [ sz - 1 ]; + sr2 = arg; + if ( sz > 0 ) + BOOST_TEST ( sr2.ends_with ( ch )); + BOOST_TEST ( !sr2.ends_with ( ++ch )); + BOOST_TEST ( sr2.ends_with ( string_ref ())); + } + +void starts_with ( const char *arg ) { + const std::size_t sz = std::strlen ( arg ); + string_ref sr ( arg ); + string_ref sr2 ( arg ); + std::string foo ( arg ); + while ( !foo.empty ()) { + BOOST_TEST ( sr.starts_with ( foo )); + foo.erase ( foo.end () - 1 ); + } + + while ( !sr2.empty ()) { + BOOST_TEST ( sr.starts_with ( sr2 )); + sr2.remove_suffix (1); + } + + char ch = *arg; + sr2 = arg; + if ( sz > 0 ) + BOOST_TEST ( sr2.starts_with ( ch )); + BOOST_TEST ( !sr2.starts_with ( ++ch )); + BOOST_TEST ( sr2.starts_with ( string_ref ())); + } + +void reverse ( const char *arg ) { +// Round trip + string_ref sr1 ( arg ); + std::string string1 ( sr1.rbegin (), sr1.rend ()); + string_ref sr2 ( string1 ); + std::string string2 ( sr2.rbegin (), sr2.rend ()); + + BOOST_TEST ( std::equal ( sr2.rbegin (), sr2.rend (), arg )); + BOOST_TEST ( string2 == arg ); + BOOST_TEST ( std::equal ( sr1.begin (), sr1.end (), string2.begin ())); + } + +// This helper function eliminates signed vs. unsigned warnings +string_ref::size_type ptr_diff ( const char *res, const char *base ) { + BOOST_TEST ( res >= base ); + return static_cast ( res - base ); + } + +void find ( const char *arg ) { + string_ref sr1; + string_ref sr2; + const char *p; + +// When we search for the empty string, we find it at position 0 + BOOST_TEST ( sr1.find (sr2) == 0 ); + BOOST_TEST ( sr1.rfind(sr2) == 0 ); + +// Look for each character in the string(searching from the start) + p = arg; + sr1 = arg; + while ( *p ) { + string_ref::size_type pos = sr1.find(*p); + BOOST_TEST ( pos != string_ref::npos && ( pos <= ptr_diff ( p, arg ))); + ++p; + } + +// Look for each character in the string (searching from the end) + p = arg; + sr1 = arg; + while ( *p ) { + string_ref::size_type pos = sr1.rfind(*p); + BOOST_TEST ( pos != string_ref::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg ))); + ++p; + } + +// Look for pairs on characters (searching from the start) + sr1 = arg; + p = arg; + while ( *p && *(p+1)) { + string_ref sr3 ( p, 2 ); + string_ref::size_type pos = sr1.find ( sr3 ); + BOOST_TEST ( pos != string_ref::npos && pos <= static_cast( p - arg )); + p++; + } + + sr1 = arg; + p = arg; +// for all possible chars, see if we find them in the right place. +// Note that strchr will/might do the _wrong_ thing if we search for NULL + for ( int ch = 1; ch < 256; ++ch ) { + string_ref::size_type pos = sr1.find(ch); + const char *strp = std::strchr ( arg, ch ); + BOOST_TEST (( strp == NULL ) == ( pos == string_ref::npos )); + if ( strp != NULL ) + BOOST_TEST ( ptr_diff ( strp, arg ) == pos ); + } + + sr1 = arg; + p = arg; +// for all possible chars, see if we find them in the right place. +// Note that strchr will/might do the _wrong_ thing if we search for NULL + for ( int ch = 1; ch < 256; ++ch ) { + string_ref::size_type pos = sr1.rfind(ch); + const char *strp = std::strrchr ( arg, ch ); + BOOST_TEST (( strp == NULL ) == ( pos == string_ref::npos )); + if ( strp != NULL ) + BOOST_TEST ( ptr_diff ( strp, arg ) == pos ); + } + + +// Find everything at the start + p = arg; + sr1 = arg; + while ( !sr1.empty ()) { + string_ref::size_type pos = sr1.find(*p); + BOOST_TEST ( pos == 0 ); + sr1.remove_prefix (1); + ++p; + } + +// Find everything at the end + sr1 = arg; + p = arg + std::strlen ( arg ) - 1; + while ( !sr1.empty ()) { + string_ref::size_type pos = sr1.rfind(*p); + BOOST_TEST ( pos == sr1.size () - 1 ); + sr1.remove_suffix (1); + --p; + } + +// Find everything at the start + sr1 = arg; + p = arg; + while ( !sr1.empty ()) { + string_ref::size_type pos = sr1.find_first_of(*p); + BOOST_TEST ( pos == 0 ); + sr1.remove_prefix (1); + ++p; + } + + +// Find everything at the end + sr1 = arg; + p = arg + std::strlen ( arg ) - 1; + while ( !sr1.empty ()) { + string_ref::size_type pos = sr1.find_last_of(*p); + BOOST_TEST ( pos == sr1.size () - 1 ); + sr1.remove_suffix (1); + --p; + } + +// Basic sanity checking for "find_first_of / find_first_not_of" + sr1 = arg; + sr2 = arg; + while ( !sr1.empty() ) { + BOOST_TEST ( sr1.find_first_of ( sr2 ) == 0 ); + BOOST_TEST ( sr1.find_first_not_of ( sr2 ) == string_ref::npos ); + sr1.remove_prefix ( 1 ); + } + + p = arg; + sr1 = arg; + while ( *p ) { + string_ref::size_type pos1 = sr1.find_first_of(*p); + string_ref::size_type pos2 = sr1.find_first_not_of(*p); + BOOST_TEST ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg )); + if ( pos2 != string_ref::npos ) { + for ( std::size_t i = 0 ; i < pos2; ++i ) + BOOST_TEST ( sr1[i] == *p ); + BOOST_TEST ( sr1 [ pos2 ] != *p ); + } + + BOOST_TEST ( pos2 != pos1 ); + ++p; + } + +// Basic sanity checking for "find_last_of / find_last_not_of" + sr1 = arg; + sr2 = arg; + while ( !sr1.empty() ) { + BOOST_TEST ( sr1.find_last_of ( sr2 ) == ( sr1.size () - 1 )); + BOOST_TEST ( sr1.find_last_not_of ( sr2 ) == string_ref::npos ); + sr1.remove_suffix ( 1 ); + } + + p = arg; + sr1 = arg; + while ( *p ) { + string_ref::size_type pos1 = sr1.find_last_of(*p); + string_ref::size_type pos2 = sr1.find_last_not_of(*p); + BOOST_TEST ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg )); + BOOST_TEST ( pos2 == string_ref::npos || pos1 < sr1.size ()); + if ( pos2 != string_ref::npos ) { + for ( std::size_t i = sr1.size () -1 ; i > pos2; --i ) + BOOST_TEST ( sr1[i] == *p ); + BOOST_TEST ( sr1 [ pos2 ] != *p ); + } + + BOOST_TEST ( pos2 != pos1 ); + ++p; + } + + } + + +void to_string ( const char *arg ) { + string_ref sr1; + std::string str1; + std::string str2; + + str1.assign ( arg ); + sr1 = arg; +// str2 = sr1.to_string > (); + str2 = sr1.to_string (); + BOOST_TEST ( str1 == str2 ); + +#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS + std::string str3 = static_cast ( sr1 ); + BOOST_TEST ( str1 == str3 ); +#endif + } + +void compare ( const char *arg ) { + string_ref sr1; + std::string str1; + std::string str2 = str1; + + str1.assign ( arg ); + sr1 = arg; + BOOST_TEST ( sr1 == sr1); // compare string_ref and string_ref + BOOST_TEST ( sr1 == str1); // compare string and string_ref + BOOST_TEST ( str1 == sr1 ); // compare string_ref and string + BOOST_TEST ( sr1 == arg ); // compare string_ref and pointer + BOOST_TEST ( arg == sr1 ); // compare pointer and string_ref + + if ( sr1.size () > 0 ) { + (*str1.rbegin())++; + BOOST_TEST ( sr1 != str1 ); + BOOST_TEST ( str1 != sr1 ); + BOOST_TEST ( sr1 < str1 ); + BOOST_TEST ( sr1 <= str1 ); + BOOST_TEST ( str1 > sr1 ); + BOOST_TEST ( str1 >= sr1 ); + + (*str1.rbegin()) -= 2; + BOOST_TEST ( sr1 != str1 ); + BOOST_TEST ( str1 != sr1 ); + BOOST_TEST ( sr1 > str1 ); + BOOST_TEST ( sr1 >= str1 ); + BOOST_TEST ( str1 < sr1 ); + BOOST_TEST ( str1 <= sr1 ); + } + } + +const char *test_strings [] = { + "", + "0", + "abc", + "AAA", // all the same + "adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf", + "abc\0asdfadsfasf", + NULL + }; + +int main() +{ + const char **p = &test_strings[0]; + + while ( *p != NULL ) { + starts_with ( *p ); + ends_with ( *p ); + reverse ( *p ); + find ( *p ); + to_string ( *p ); + compare ( *p ); + + p++; + } + + return boost::report_errors(); +} diff --git a/libs/utility/test/string_ref_test_io.cpp b/libs/utility/test/string_ref_test_io.cpp new file mode 100644 index 00000000..3609f915 --- /dev/null +++ b/libs/utility/test/string_ref_test_io.cpp @@ -0,0 +1,184 @@ +/* + * Copyright Andrey Semashev 2013. + * 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) + */ +/*! + * \file string_ref_test_io.cpp + * \author Andrey Semashev + * \date 26.05.2013 + * + * \brief This header contains tests for stream operations of \c basic_string_ref. + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +/* Current implementations seem to be missing codecvt facets to convert chars to char16_t and char32_t even though the types are available. +*/ + +static const char* test_strings[] = +{ + "begin", + "abcd", + "end" +}; + +//! The context with test data for particular character type +template< typename CharT > +struct context +{ + typedef CharT char_type; + typedef std::basic_string< char_type > string_type; + typedef std::basic_ostringstream< char_type > ostream_type; + + string_type begin, abcd, end; + + context() + { + boost::string_ref str = test_strings[0]; + std::copy(str.begin(), str.end(), std::back_inserter(begin)); + + str = test_strings[1]; + std::copy(str.begin(), str.end(), std::back_inserter(abcd)); + + str = test_strings[2]; + std::copy(str.begin(), str.end(), std::back_inserter(end)); + } +}; + +// Test regular output +template +void test_string_ref_output() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_ref< char_type > string_ref_type; + + context< char_type > ctx; + + ostream_type strm; + strm << string_ref_type(ctx.abcd); + BOOST_TEST(strm.str() == ctx.abcd); +} + +// Test support for padding +template +void test_padding() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_ref< char_type > string_ref_type; + + context< char_type > ctx; + + // Test for padding + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } + + // Test for long padding + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(100) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } + + // Test that short width does not truncate the string + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(1) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } +} + +// Test support for padding fill +template +void test_padding_fill() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_ref< char_type > string_ref_type; + + context< char_type > ctx; + + ostream_type strm_ref; + strm_ref << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); +} + +// Test support for alignment +template +void test_alignment() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_ref< char_type > string_ref_type; + + context< char_type > ctx; + + // Left alignment + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::left << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::left << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } + + // Right alignment + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::right << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::right << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } +} + +template +void test() +{ + test_string_ref_output(); + test_padding(); + test_padding_fill(); + test_alignment(); +} + +int main() +{ + test(); + test(); + return boost::report_errors(); +} diff --git a/libs/utility/test/string_view_constexpr_test1.cpp b/libs/utility/test/string_view_constexpr_test1.cpp new file mode 100644 index 00000000..51a2652d --- /dev/null +++ b/libs/utility/test/string_view_constexpr_test1.cpp @@ -0,0 +1,115 @@ +/* + Copyright (c) Marshall Clow 2017-2017. + + 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) + + For more information, see http://www.boost.org +*/ + +#include // for placement new +#include +#include // for NULL, std::size_t, std::ptrdiff_t +#include // for std::strchr and std::strcmp +#include // for std::malloc and std::free +#include // for EOF + +#include +#include + +#if __cplusplus >= 201402L +struct constexpr_char_traits +{ + typedef char char_type; + typedef int int_type; + typedef std::streamoff off_type; + typedef std::streampos pos_type; + typedef std::mbstate_t state_type; + + static void assign(char_type& c1, const char_type& c2) noexcept { c1 = c2; } + static constexpr bool eq(char_type c1, char_type c2) noexcept { return c1 == c2; } + static constexpr bool lt(char_type c1, char_type c2) noexcept { return c1 < c2; } + + static constexpr int compare(const char_type* s1, const char_type* s2, std::size_t n) noexcept; + static constexpr std::size_t length(const char_type* s) noexcept; + static constexpr const char_type* find(const char_type* s, std::size_t n, const char_type& a) noexcept; + static constexpr char_type* move(char_type* s1, const char_type* s2, std::size_t n) noexcept; + static constexpr char_type* copy(char_type* s1, const char_type* s2, std::size_t n) noexcept; + static constexpr char_type* assign(char_type* s, std::size_t n, char_type a) noexcept; + + static constexpr int_type not_eof(int_type c) noexcept { return eq_int_type(c, eof()) ? ~eof() : c; } + static constexpr char_type to_char_type(int_type c) noexcept { return char_type(c); } + static constexpr int_type to_int_type(char_type c) noexcept { return int_type(c); } + static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept { return c1 == c2; } + static constexpr int_type eof() noexcept { return EOF; } +}; + +// yields: +// 0 if for each i in [0,n), X::eq(s1[i],s2[i]) is true; +// else, a negative value if, for some j in [0,n), X::lt(s1[j],s2[j]) is true and +// for each i in [0,j) X::eq(s2[i],s2[i]) is true; +// else a positive value. +constexpr int constexpr_char_traits::compare(const char_type* s1, const char_type* s2, std::size_t n) noexcept +{ + for (; n != 0; --n, ++s1, ++s2) + { + if (lt(*s1, *s2)) + return -1; + if (lt(*s2, *s1)) + return 1; + } + return 0; +} + +// yields: the smallest i such that X::eq(s[i],charT()) is true. +constexpr std::size_t constexpr_char_traits::length(const char_type* s) noexcept +{ + std::size_t len = 0; + for (; !eq(*s, char_type(0)); ++s) + ++len; + return len; +} + +typedef boost::basic_string_view string_view; + +int main() +{ + constexpr string_view sv1; + constexpr string_view sv2{"abc", 3}; // ptr, len + constexpr string_view sv3{"def"}; // ptr + + constexpr const char *s1 = ""; + constexpr const char *s2 = "abc"; + + static_assert( (sv1 == sv1), "" ); + + static_assert(!(sv1 == sv2), "" ); + static_assert( (sv1 != sv2), "" ); + static_assert( (sv1 < sv2), "" ); + static_assert( (sv1 <= sv2), "" ); + static_assert(!(sv1 > sv2), "" ); + static_assert(!(sv1 >= sv2), "" ); + + static_assert(!(s1 == sv2), "" ); + static_assert( (s1 != sv2), "" ); + static_assert( (s1 < sv2), "" ); + static_assert( (s1 <= sv2), "" ); + static_assert(!(s1 > sv2), "" ); + static_assert(!(s1 >= sv2), "" ); + + static_assert(!(sv1 == s2), "" ); + static_assert( (sv1 != s2), "" ); + static_assert( (sv1 < s2), "" ); + static_assert( (sv1 <= s2), "" ); + static_assert(!(sv1 > s2), "" ); + static_assert(!(sv1 >= s2), "" ); + + static_assert( sv1.compare(sv2) < 0, "" ); + static_assert( sv1.compare(sv1) == 0, "" ); + static_assert( sv3.compare(sv1) > 0, "" ); + + static_assert( sv1.compare(s2) < 0, "" ); + static_assert( sv1.compare(s1) == 0, "" ); + static_assert( sv3.compare(s1) > 0, "" ); +} +#endif diff --git a/libs/utility/test/string_view_from_rvalue.cpp b/libs/utility/test/string_view_from_rvalue.cpp new file mode 100644 index 00000000..a7649395 --- /dev/null +++ b/libs/utility/test/string_view_from_rvalue.cpp @@ -0,0 +1,26 @@ +/* + Copyright (c) Marshall Clow 2017. + + 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) + + For more information, see http://www.boost.org +*/ + +#include +#include +#include + +#include + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) +#error "Unsupported test" +#endif + +std::string makeatemp() { return "abc"; } + +int main() +{ + boost::basic_string_view sv(makeatemp()); + return 0; +} diff --git a/libs/utility/test/string_view_test1.cpp b/libs/utility/test/string_view_test1.cpp new file mode 100644 index 00000000..22912c0c --- /dev/null +++ b/libs/utility/test/string_view_test1.cpp @@ -0,0 +1,121 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org +*/ + +#include +#include +#include +#include + +#include +#include + +#include + +typedef boost::string_view string_view; + +// Should be equal +void interop ( const std::string &str, string_view ref ) { +// BOOST_TEST ( str == ref ); + BOOST_TEST ( str.size () == ref.size ()); + BOOST_TEST ( std::equal ( str.begin (), str.end (), ref.begin ())); + BOOST_TEST ( std::equal ( str.rbegin (), str.rend (), ref.rbegin ())); + } + +void null_tests ( const char *p ) { +// All zero-length string-refs should be equal + string_view sr1; // NULL, 0 + string_view sr2 ( NULL, 0 ); + string_view sr3 ( p, 0 ); + string_view sr4 ( p ); + sr4.clear (); + + BOOST_TEST ( sr1 == sr2 ); + BOOST_TEST ( sr1 == sr3 ); + BOOST_TEST ( sr2 == sr3 ); + BOOST_TEST ( sr1 == sr4 ); + } + +// make sure that substrings work just like strings +void test_substr ( const std::string &str ) { + const std::size_t sz = str.size (); + string_view ref ( str ); + +// Substrings at the end + for ( std::size_t i = 0; i <= sz; ++ i ) + interop ( str.substr ( i ), ref.substr ( i )); + +// Substrings at the beginning + for ( std::size_t i = 0; i <= sz; ++ i ) + interop ( str.substr ( 0, i ), ref.substr ( 0, i )); + +// All possible substrings + for ( std::size_t i = 0; i < sz; ++i ) + for ( std::size_t j = i; j < sz; ++j ) + interop ( str.substr ( i, j ), ref.substr ( i, j )); + } + +// make sure that removing prefixes and suffixes work just like strings +void test_remove ( const std::string &str ) { + const std::size_t sz = str.size (); + std::string work; + string_view ref; + + for ( std::size_t i = 1; i <= sz; ++i ) { + work = str; + ref = str; + while ( ref.size () >= i ) { + interop ( work, ref ); + work.erase ( 0, i ); + ref.remove_prefix (i); + } + } + + for ( std::size_t i = 1; i < sz; ++ i ) { + work = str; + ref = str; + while ( ref.size () >= i ) { + interop ( work, ref ); + work.erase ( work.size () - i, i ); + ref.remove_suffix (i); + } + } + } + +void test_hash(const std::string& str) { + string_view ref = str; + BOOST_TEST(boost::hash_value(ref) == boost::hash_value(str)); + boost::hash hstr; + boost::hash hsv; + BOOST_TEST(hsv(ref) == hstr(str)); + } + +const char *test_strings [] = { + "", + "1", + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + "0123456789", + NULL + }; + +int main() +{ + const char **p = &test_strings[0]; + + while ( *p != NULL ) { + interop ( *p, *p ); + test_substr ( *p ); + test_remove ( *p ); + null_tests ( *p ); + test_hash( *p ); + + p++; + } + + return boost::report_errors(); +} diff --git a/libs/utility/test/string_view_test2.cpp b/libs/utility/test/string_view_test2.cpp new file mode 100644 index 00000000..6834091b --- /dev/null +++ b/libs/utility/test/string_view_test2.cpp @@ -0,0 +1,440 @@ +/* + Copyright (c) Marshall Clow 2012-2012. + + 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) + + For more information, see http://www.boost.org +*/ + +#include // for placement new +#include +#include +#include // for std::equal +#include // for NULL, std::size_t, std::ptrdiff_t +#include // for std::strlen, std::strchr and std::strcmp +#include // for std::malloc and std::free + +#include +#include + +#include + +typedef boost::string_view string_view; + +void ends_with ( const char *arg ) { + const std::size_t sz = std::strlen ( arg ); + string_view sr ( arg ); + string_view sr2 ( arg ); + const char *p = arg; + + while ( *p ) { + BOOST_TEST ( sr.ends_with ( p )); + ++p; + } + + while ( !sr2.empty ()) { + BOOST_TEST ( sr.ends_with ( sr2 )); + sr2.remove_prefix (1); + } + + sr2 = arg; + while ( !sr2.empty ()) { + BOOST_TEST ( sr.ends_with ( sr2 )); + sr2.remove_prefix (1); + } + + char ch = sz == 0 ? '\0' : arg [ sz - 1 ]; + sr2 = arg; + if ( sz > 0 ) + BOOST_TEST ( sr2.ends_with ( ch )); + BOOST_TEST ( !sr2.ends_with ( ++ch )); + BOOST_TEST ( sr2.ends_with ( string_view())); + } + +void starts_with ( const char *arg ) { + const std::size_t sz = std::strlen ( arg ); + string_view sr ( arg ); + string_view sr2 ( arg ); + std::string foo ( arg ); + while ( !foo.empty ()) { + BOOST_TEST ( sr.starts_with ( foo )); + foo.erase ( foo.end () - 1 ); + } + + while ( !sr2.empty ()) { + BOOST_TEST ( sr.starts_with ( sr2 )); + sr2.remove_suffix (1); + } + + char ch = *arg; + sr2 = arg; + if ( sz > 0 ) + BOOST_TEST ( sr2.starts_with ( ch )); + BOOST_TEST ( !sr2.starts_with ( ++ch )); + BOOST_TEST ( sr2.starts_with ( string_view ())); + } + +void contains ( const char *arg ) { + const std::size_t sz = std::strlen ( arg ); + string_view sr ( arg ); + string_view sr2 ( arg ); + std::string foo ( arg ); + while ( !foo.empty ()) { + BOOST_TEST ( sr.contains ( foo )); + if ( ( foo.size () & 1u ) != 0u ) + foo.erase ( foo.end () - 1 ); + else + foo.erase ( foo.begin () ); + } + + while ( !sr2.empty ()) { + BOOST_TEST ( sr.contains ( sr2 )); + if ( ( sr2.size () & 1u ) != 0u ) + sr2.remove_suffix (1); + else + sr2.remove_prefix (1); + } + + sr2 = arg; + for ( std::size_t i = 0; i < sz; ++i ) + BOOST_TEST ( sr2.contains ( arg[i] )); + BOOST_TEST ( !sr2.contains ( '\a' )); + BOOST_TEST ( sr2.contains ( string_view ())); + } + +void reverse ( const char *arg ) { +// Round trip + string_view sr1 ( arg ); + std::string string1 ( sr1.rbegin (), sr1.rend ()); + string_view sr2 ( string1 ); + std::string string2 ( sr2.rbegin (), sr2.rend ()); + + BOOST_TEST ( std::equal ( sr2.rbegin (), sr2.rend (), arg )); + BOOST_TEST ( string2 == arg ); + BOOST_TEST ( std::equal ( sr1.begin (), sr1.end (), string2.begin ())); + } + +// This helper function eliminates signed vs. unsigned warnings +string_view::size_type ptr_diff ( const char *res, const char *base ) { + BOOST_TEST ( res >= base ); + return static_cast ( res - base ); + } + +void find ( const char *arg ) { + string_view sr1; + string_view sr2; + const char *p; + +// When we search for the empty string, we find it at position 0 + BOOST_TEST ( sr1.find (sr2) == 0 ); + BOOST_TEST ( sr1.rfind(sr2) == 0 ); + +// Look for each character in the string(searching from the start) + p = arg; + sr1 = arg; + while ( *p ) { + string_view::size_type pos = sr1.find(*p); + BOOST_TEST ( pos != string_view::npos && ( pos <= ptr_diff ( p, arg ))); + ++p; + } + +// Look for each character in the string (searching from the end) + p = arg; + sr1 = arg; + while ( *p ) { + string_view::size_type pos = sr1.rfind(*p); + BOOST_TEST ( pos != string_view::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg ))); + ++p; + } + +// Look for pairs on characters (searching from the start) + sr1 = arg; + p = arg; + while ( *p && *(p+1)) { + string_view sr3 ( p, 2 ); + string_view::size_type pos = sr1.find ( sr3 ); + BOOST_TEST ( pos != string_view::npos && pos <= static_cast( p - arg )); + p++; + } + + sr1 = arg; + p = arg; +// for all possible chars, see if we find them in the right place. +// Note that strchr will/might do the _wrong_ thing if we search for NULL + for ( int ch = 1; ch < 256; ++ch ) { + string_view::size_type pos = sr1.find(ch); + const char *strp = std::strchr ( arg, ch ); + BOOST_TEST (( strp == NULL ) == ( pos == string_view::npos )); + if ( strp != NULL ) + BOOST_TEST ( ptr_diff ( strp, arg ) == pos ); + } + + sr1 = arg; + p = arg; +// for all possible chars, see if we find them in the right place. +// Note that strchr will/might do the _wrong_ thing if we search for NULL + for ( int ch = 1; ch < 256; ++ch ) { + string_view::size_type pos = sr1.rfind(ch); + const char *strp = std::strrchr ( arg, ch ); + BOOST_TEST (( strp == NULL ) == ( pos == string_view::npos )); + if ( strp != NULL ) + BOOST_TEST ( ptr_diff ( strp, arg ) == pos ); + } + + +// Find everything at the start + p = arg; + sr1 = arg; + while ( !sr1.empty ()) { + string_view::size_type pos = sr1.find(*p); + BOOST_TEST ( pos == 0 ); + sr1.remove_prefix (1); + ++p; + } + +// Find everything at the end + sr1 = arg; + p = arg + std::strlen ( arg ) - 1; + while ( !sr1.empty ()) { + string_view::size_type pos = sr1.rfind(*p); + BOOST_TEST ( pos == sr1.size () - 1 ); + sr1.remove_suffix (1); + --p; + } + +// Find everything at the start + sr1 = arg; + p = arg; + while ( !sr1.empty ()) { + string_view::size_type pos = sr1.find_first_of(*p); + BOOST_TEST ( pos == 0 ); + sr1.remove_prefix (1); + ++p; + } + + +// Find everything at the end + sr1 = arg; + p = arg + std::strlen ( arg ) - 1; + while ( !sr1.empty ()) { + string_view::size_type pos = sr1.find_last_of(*p); + BOOST_TEST ( pos == sr1.size () - 1 ); + sr1.remove_suffix (1); + --p; + } + +// Basic sanity checking for "find_first_of / find_first_not_of" + sr1 = arg; + sr2 = arg; + while ( !sr1.empty() ) { + BOOST_TEST ( sr1.find_first_of ( sr2 ) == 0 ); + BOOST_TEST ( sr1.find_first_not_of ( sr2 ) == string_view::npos ); + sr1.remove_prefix ( 1 ); + } + + p = arg; + sr1 = arg; + while ( *p ) { + string_view::size_type pos1 = sr1.find_first_of(*p); + string_view::size_type pos2 = sr1.find_first_not_of(*p); + BOOST_TEST ( pos1 != string_view::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg )); + if ( pos2 != string_view::npos ) { + for ( string_view::size_type i = 0 ; i < pos2; ++i ) + BOOST_TEST ( sr1[i] == *p ); + BOOST_TEST ( sr1 [ pos2 ] != *p ); + } + + BOOST_TEST ( pos2 != pos1 ); + ++p; + } + +// Basic sanity checking for "find_last_of / find_last_not_of" + sr1 = arg; + sr2 = arg; + while ( !sr1.empty() ) { + BOOST_TEST ( sr1.find_last_of ( sr2 ) == ( sr1.size () - 1 )); + BOOST_TEST ( sr1.find_last_not_of ( sr2 ) == string_view::npos ); + sr1.remove_suffix ( 1 ); + } + + p = arg; + sr1 = arg; + while ( *p ) { + string_view::size_type pos1 = sr1.find_last_of(*p); + string_view::size_type pos2 = sr1.find_last_not_of(*p); + BOOST_TEST ( pos1 != string_view::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg )); + BOOST_TEST ( pos2 == string_view::npos || pos1 < sr1.size ()); + if ( pos2 != string_view::npos ) { + for ( string_view::size_type i = sr1.size () -1 ; i > pos2; --i ) + BOOST_TEST ( sr1[i] == *p ); + BOOST_TEST ( sr1 [ pos2 ] != *p ); + } + + BOOST_TEST ( pos2 != pos1 ); + ++p; + } + + } + +template +class custom_allocator { +public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef void* void_pointer; + typedef const void* const_void_pointer; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T& reference; + typedef const T& const_reference; + + template + struct rebind { + typedef custom_allocator other; + }; + + custom_allocator() BOOST_NOEXCEPT {} + template + custom_allocator(custom_allocator const&) BOOST_NOEXCEPT {} + + pointer allocate(size_type n) const { + return static_cast(std::malloc(sizeof(value_type) * n)); + } + void deallocate(pointer p, size_type) const BOOST_NOEXCEPT { + std::free(p); + } + + pointer address(reference value) const BOOST_NOEXCEPT { + return &value; + } + + const_pointer address(const_reference value) const BOOST_NOEXCEPT { + return &value; + } + + BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT { + return (~(size_type)0u) / sizeof(value_type); + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + void construct(U* ptr, Args&&... args) const { + ::new((void*)ptr) U(static_cast(args)...); + } +#else + template + void construct(U* ptr, V&& value) const { + ::new((void*)ptr) U(static_cast(value)); + } +#endif +#else + template + void construct(U* ptr, const V& value) const { + ::new((void*)ptr) U(value); + } +#endif + + template + void construct(U* ptr) const { + ::new((void*)ptr) U(); + } + + template + void destroy(U* ptr) const { + (void)ptr; + ptr->~U(); + } + }; + +template +BOOST_CONSTEXPR bool operator==(const custom_allocator &, const custom_allocator &) BOOST_NOEXCEPT { + return true; + } +template +BOOST_CONSTEXPR bool operator!=(const custom_allocator &, const custom_allocator &) BOOST_NOEXCEPT { + return false; + } + +void to_string ( const char *arg ) { + string_view sr1; + std::string str1; + std::string str2; + + str1.assign ( arg ); + sr1 = arg; +// str2 = sr1.to_string > (); + str2 = sr1.to_string (); + BOOST_TEST ( str1 == str2 ); + + std::basic_string, custom_allocator > str3 = sr1.to_string(custom_allocator()); + BOOST_TEST ( std::strcmp(str1.c_str(), str3.c_str()) == 0 ); + +#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS + std::string str4 = static_cast ( sr1 ); + BOOST_TEST ( str1 == str4 ); +#endif + } + +void compare ( const char *arg ) { + string_view sr1; + std::string str1; + std::string str2 = str1; + + str1.assign ( arg ); + sr1 = arg; + BOOST_TEST ( sr1 == sr1); // compare string_view and string_view + BOOST_TEST ( sr1 == str1); // compare string and string_view + BOOST_TEST ( str1 == sr1 ); // compare string_view and string + BOOST_TEST ( sr1 == arg ); // compare string_view and pointer + BOOST_TEST ( arg == sr1 ); // compare pointer and string_view + + if ( sr1.size () > 0 ) { + (*str1.rbegin())++; + BOOST_TEST ( sr1 != str1 ); + BOOST_TEST ( str1 != sr1 ); + BOOST_TEST ( sr1 < str1 ); + BOOST_TEST ( sr1 <= str1 ); + BOOST_TEST ( str1 > sr1 ); + BOOST_TEST ( str1 >= sr1 ); + + (*str1.rbegin()) -= 2; + BOOST_TEST ( sr1 != str1 ); + BOOST_TEST ( str1 != sr1 ); + BOOST_TEST ( sr1 > str1 ); + BOOST_TEST ( sr1 >= str1 ); + BOOST_TEST ( str1 < sr1 ); + BOOST_TEST ( str1 <= sr1 ); + } + } + +const char *test_strings [] = { + "", + "0", + "abc", + "AAA", // all the same + "adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf", + "abc\0asdfadsfasf", + NULL + }; + +int main() +{ + const char **p = &test_strings[0]; + + while ( *p != NULL ) { + starts_with ( *p ); + ends_with ( *p ); + contains ( *p ); + reverse ( *p ); + find ( *p ); + to_string ( *p ); + compare ( *p ); + + ++p; + } + + return boost::report_errors(); +} diff --git a/libs/utility/test/string_view_test_io.cpp b/libs/utility/test/string_view_test_io.cpp new file mode 100644 index 00000000..416ff338 --- /dev/null +++ b/libs/utility/test/string_view_test_io.cpp @@ -0,0 +1,184 @@ +/* + * Copyright Andrey Semashev 2013. + * 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) + */ +/*! + * \file string_ref_test_io.cpp + * \author Andrey Semashev + * \date 26.05.2013 + * + * \brief This header contains tests for stream operations of \c basic_string_ref. + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +/* Current implementations seem to be missing codecvt facets to convert chars to char16_t and char32_t even though the types are available. +*/ + +static const char* test_strings[] = +{ + "begin", + "abcd", + "end" +}; + +//! The context with test data for particular character type +template< typename CharT > +struct context +{ + typedef CharT char_type; + typedef std::basic_string< char_type > string_type; + typedef std::basic_ostringstream< char_type > ostream_type; + + string_type begin, abcd, end; + + context() + { + boost::string_view str = test_strings[0]; + std::copy(str.begin(), str.end(), std::back_inserter(begin)); + + str = test_strings[1]; + std::copy(str.begin(), str.end(), std::back_inserter(abcd)); + + str = test_strings[2]; + std::copy(str.begin(), str.end(), std::back_inserter(end)); + } +}; + +// Test regular output +template +void test_string_view_output() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_view< char_type > string_view_type; + + context< char_type > ctx; + + ostream_type strm; + strm << string_view_type(ctx.abcd); + BOOST_TEST(strm.str() == ctx.abcd); +} + +// Test support for padding +template +void test_padding() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_view< char_type > string_view_type; + + context< char_type > ctx; + + // Test for padding + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(8) << string_view_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } + + // Test for long padding + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(100) << string_view_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } + + // Test that short width does not truncate the string + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::setw(1) << string_view_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } +} + +// Test support for padding fill +template +void test_padding_fill() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_view< char_type > string_view_type; + + context< char_type > ctx; + + ostream_type strm_ref; + strm_ref << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << string_view_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); +} + +// Test support for alignment +template +void test_alignment() +{ + typedef CharT char_type; + typedef std::basic_ostringstream< char_type > ostream_type; + typedef boost::basic_string_view< char_type > string_view_type; + + context< char_type > ctx; + + // Left alignment + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::left << std::setw(8) << string_view_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::left << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } + + // Right alignment + { + ostream_type strm_ref; + strm_ref << ctx.begin << std::right << std::setw(8) << string_view_type(ctx.abcd) << ctx.end; + + ostream_type strm_correct; + strm_correct << ctx.begin << std::right << std::setw(8) << ctx.abcd << ctx.end; + + BOOST_TEST(strm_ref.str() == strm_correct.str()); + } +} + +template +void test() +{ + test_string_view_output(); + test_padding(); + test_padding_fill(); + test_alignment(); +} + +int main() +{ + test(); + test(); + return boost::report_errors(); +} diff --git a/libs/utility/test/value_init_test.cpp b/libs/utility/test/value_init_test.cpp new file mode 100644 index 00000000..78bd3b18 --- /dev/null +++ b/libs/utility/test/value_init_test.cpp @@ -0,0 +1,373 @@ +// Copyright 2002-2008, Fernando Luis Cacciola Carballal. +// +// 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) +// +// Test program for "boost/utility/value_init.hpp" +// +// 21 Ago 2002 (Created) Fernando Cacciola +// 15 Jan 2008 (Added tests regarding compiler issues) Fernando Cacciola, Niels Dekker +// 23 May 2008 (Added tests regarding initialized_value) Niels Dekker +// 21 Ago 2008 (Added swap test) Niels Dekker + +#include // For memcmp. +#include +#include + +#include "boost/utility/value_init.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include +#include +#include + +// +// Sample POD type +// +struct POD +{ + POD () : f(0), c(0), i(0){} + + POD ( char c_, int i_, float f_ ) : f(f_), c(c_), i(i_) {} + + friend std::ostream& operator << ( std::ostream& os, POD const& pod ) + { return os << '(' << pod.c << ',' << pod.i << ',' << pod.f << ')' ; } + + friend bool operator == ( POD const& lhs, POD const& rhs ) + { return lhs.f == rhs.f && lhs.c == rhs.c && lhs.i == rhs.i ; } + + float f; + char c; + int i; +} ; + +// +// Sample non POD type +// +struct NonPODBase +{ + virtual ~NonPODBase() {} +} ; +struct NonPOD : NonPODBase +{ + NonPOD () : id() {} + explicit NonPOD ( std::string const& id_) : id(id_) {} + + friend std::ostream& operator << ( std::ostream& os, NonPOD const& npod ) + { return os << '(' << npod.id << ')' ; } + + friend bool operator == ( NonPOD const& lhs, NonPOD const& rhs ) + { return lhs.id == rhs.id ; } + + std::string id ; +} ; + +// +// Sample aggregate POD struct type +// Some compilers do not correctly value-initialize such a struct, for example: +// Borland C++ Report #51854, "Value-initialization: POD struct should be zero-initialized " +// http://qc.codegear.com/wc/qcmain.aspx?d=51854 +// +struct AggregatePODStruct +{ + float f; + char c; + int i; +}; + +bool operator == ( AggregatePODStruct const& lhs, AggregatePODStruct const& rhs ) +{ return lhs.f == rhs.f && lhs.c == rhs.c && lhs.i == rhs.i ; } + +// +// An aggregate struct that contains an std::string and an int. +// Pavel Kuznetsov (MetaCommunications Engineering) used a struct like +// this to reproduce the Microsoft Visual C++ compiler bug, reported as +// Feedback ID 100744, "Value-initialization in new-expression" +// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744 +// +struct StringAndInt +{ + std::string s; + int i; +}; + +bool operator == ( StringAndInt const& lhs, StringAndInt const& rhs ) +{ return lhs.s == rhs.s && lhs.i == rhs.i ; } + + +// +// A struct that has an explicit (user defined) destructor. +// Some compilers do not correctly value-initialize such a struct, for example: +// Microsoft Visual C++, Feedback ID 100744, "Value-initialization in new-expression" +// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744 +// +struct StructWithDestructor +{ + int i; + ~StructWithDestructor() {} +}; + +bool operator == ( StructWithDestructor const& lhs, StructWithDestructor const& rhs ) +{ return lhs.i == rhs.i ; } + + +// +// A struct that has a virtual function. +// Some compilers do not correctly value-initialize such a struct either, for example: +// Microsoft Visual C++, Feedback ID 100744, "Value-initialization in new-expression" +// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744 +// +struct StructWithVirtualFunction +{ + int i; + virtual void VirtualFunction(); +}; + +void StructWithVirtualFunction::VirtualFunction() +{ +} + +bool operator == ( StructWithVirtualFunction const& lhs, StructWithVirtualFunction const& rhs ) +{ return lhs.i == rhs.i ; } + + +// +// A struct that is derived from an aggregate POD struct. +// Some compilers do not correctly value-initialize such a struct, for example: +// GCC Bugzilla Bug 30111, "Value-initialization of POD base class doesn't initialize members", +// reported by Jonathan Wakely, http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 +// +struct DerivedFromAggregatePODStruct : AggregatePODStruct +{ + DerivedFromAggregatePODStruct() : AggregatePODStruct() {} +}; + +// +// A struct that wraps an aggregate POD struct as data member. +// +struct AggregatePODStructWrapper +{ + AggregatePODStructWrapper() : dataMember() {} + AggregatePODStruct dataMember; +}; + +bool operator == ( AggregatePODStructWrapper const& lhs, AggregatePODStructWrapper const& rhs ) +{ return lhs.dataMember == rhs.dataMember ; } + +typedef unsigned char ArrayOfBytes[256]; + + +// +// A struct that allows testing whether the appropriate copy functions are called. +// +struct CopyFunctionCallTester +{ + bool is_copy_constructed; + bool is_assignment_called; + + CopyFunctionCallTester() + : is_copy_constructed(false), is_assignment_called(false) {} + + CopyFunctionCallTester(const CopyFunctionCallTester & ) + : is_copy_constructed(true), is_assignment_called(false) {} + + CopyFunctionCallTester & operator=(const CopyFunctionCallTester & ) + { + is_assignment_called = true ; + return *this ; + } +}; + + +// +// A struct that allows testing whether its customized swap function is called. +// +struct SwapFunctionCallTester +{ + bool is_custom_swap_called; + int data; + + SwapFunctionCallTester() + : is_custom_swap_called(false), data(0) {} + + SwapFunctionCallTester(const SwapFunctionCallTester & arg) + : is_custom_swap_called(false), data(arg.data) {} + + void swap(SwapFunctionCallTester & arg) + { + std::swap(data, arg.data); + is_custom_swap_called = true; + arg.is_custom_swap_called = true; + } +}; + +void swap(SwapFunctionCallTester & lhs, SwapFunctionCallTester & rhs) +{ + lhs.swap(rhs); +} + + + +template +void check_initialized_value ( T const& y ) +{ + T initializedValue = boost::initialized_value ; + BOOST_TEST ( y == initializedValue ) ; +} + +#ifdef BOOST_BORLANDC +#if BOOST_BORLANDC == 0x582 +void check_initialized_value( NonPOD const& ) +{ + // The initialized_value check is skipped for Borland 5.82 + // and this type (NonPOD), because the following statement + // won't compile on this particular compiler version: + // NonPOD initializedValue = boost::initialized_value() ; + // + // This is caused by a compiler bug, that is fixed with a newer version + // of the Borland compiler. The Release Notes for Delphi(R) 2007 for + // Win32(R) and C++Builder(R) 2007 (http://dn.codegear.com/article/36575) + // say about similar statements: + // both of these statements now compile but under 5.82 got the error: + // Error E2015: Ambiguity between 'V::V(const A &)' and 'V::V(const V &)' +} +#endif +#endif + +// +// This test function tests boost::value_initialized for a specific type T. +// The first argument (y) is assumed have the value of a value-initialized object. +// Returns true on success. +// +template +bool test ( T const& y, T const& z ) +{ + const int errors_before_test = boost::detail::test_errors(); + + check_initialized_value(y); + + boost::value_initialized x ; + BOOST_TEST ( y == x ) ; + BOOST_TEST ( y == boost::get(x) ) ; + + static_cast(x) = z ; + boost::get(x) = z ; + BOOST_TEST ( x == z ) ; + + boost::value_initialized const x_c ; + BOOST_TEST ( y == x_c ) ; + BOOST_TEST ( y == boost::get(x_c) ) ; + T& x_c_ref = const_cast( boost::get(x_c) ) ; + x_c_ref = z ; + BOOST_TEST ( x_c == z ) ; + + boost::value_initialized const copy1 = x; + BOOST_TEST ( boost::get(copy1) == boost::get(x) ) ; + + boost::value_initialized copy2; + copy2 = x; + BOOST_TEST ( boost::get(copy2) == boost::get(x) ) ; + + { + boost::value_initialized * ptr = new boost::value_initialized; + BOOST_TEST ( y == *ptr ) ; + delete ptr; + } + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + boost::value_initialized cx ; + BOOST_TEST ( y == cx ) ; + BOOST_TEST ( y == boost::get(cx) ) ; + + boost::value_initialized const cx_c ; + BOOST_TEST ( y == cx_c ) ; + BOOST_TEST ( y == boost::get(cx_c) ) ; +#endif + + return boost::detail::test_errors() == errors_before_test ; +} + +int main() +{ + BOOST_TEST ( test( 0,1234 ) ) ; + BOOST_TEST ( test( 0.0,12.34 ) ) ; + BOOST_TEST ( test( POD(0,0,0.0), POD('a',1234,56.78f) ) ) ; + BOOST_TEST ( test( NonPOD( std::string() ), NonPOD( std::string("something") ) ) ) ; + + NonPOD NonPOD_object( std::string("NonPOD_object") ); + BOOST_TEST ( test( 0, &NonPOD_object ) ) ; + + AggregatePODStruct zeroInitializedAggregatePODStruct = { 0.0f, '\0', 0 }; + AggregatePODStruct nonZeroInitializedAggregatePODStruct = { 1.25f, 'a', -1 }; + BOOST_TEST ( test(zeroInitializedAggregatePODStruct, nonZeroInitializedAggregatePODStruct) ); + + StringAndInt stringAndInt0; + StringAndInt stringAndInt1; + stringAndInt0.i = 0; + stringAndInt1.i = 1; + stringAndInt1.s = std::string("1"); + BOOST_TEST ( test(stringAndInt0, stringAndInt1) ); + + StructWithDestructor structWithDestructor0; + StructWithDestructor structWithDestructor1; + structWithDestructor0.i = 0; + structWithDestructor1.i = 1; + BOOST_TEST ( test(structWithDestructor0, structWithDestructor1) ); + + StructWithVirtualFunction structWithVirtualFunction0; + StructWithVirtualFunction structWithVirtualFunction1; + structWithVirtualFunction0.i = 0; + structWithVirtualFunction1.i = 1; + BOOST_TEST ( test(structWithVirtualFunction0, structWithVirtualFunction1) ); + + DerivedFromAggregatePODStruct derivedFromAggregatePODStruct0; + DerivedFromAggregatePODStruct derivedFromAggregatePODStruct1; + static_cast(derivedFromAggregatePODStruct0) = zeroInitializedAggregatePODStruct; + static_cast(derivedFromAggregatePODStruct1) = nonZeroInitializedAggregatePODStruct; + BOOST_TEST ( test(derivedFromAggregatePODStruct0, derivedFromAggregatePODStruct1) ); + + AggregatePODStructWrapper aggregatePODStructWrapper0; + AggregatePODStructWrapper aggregatePODStructWrapper1; + aggregatePODStructWrapper0.dataMember = zeroInitializedAggregatePODStruct; + aggregatePODStructWrapper1.dataMember = nonZeroInitializedAggregatePODStruct; + BOOST_TEST ( test(aggregatePODStructWrapper0, aggregatePODStructWrapper1) ); + + ArrayOfBytes zeroInitializedArrayOfBytes = { 0 }; + boost::value_initialized valueInitializedArrayOfBytes; + BOOST_TEST (std::memcmp(get(valueInitializedArrayOfBytes), zeroInitializedArrayOfBytes, sizeof(ArrayOfBytes)) == 0); + + boost::value_initialized valueInitializedArrayOfBytes2; + valueInitializedArrayOfBytes2 = valueInitializedArrayOfBytes; + BOOST_TEST (std::memcmp(get(valueInitializedArrayOfBytes), get(valueInitializedArrayOfBytes2), sizeof(ArrayOfBytes)) == 0); + + boost::value_initialized copyFunctionCallTester1; + BOOST_TEST ( ! get(copyFunctionCallTester1).is_copy_constructed); + BOOST_TEST ( ! get(copyFunctionCallTester1).is_assignment_called); + + boost::value_initialized copyFunctionCallTester2 = boost::value_initialized(copyFunctionCallTester1); + BOOST_TEST ( get(copyFunctionCallTester2).is_copy_constructed); + BOOST_TEST ( ! get(copyFunctionCallTester2).is_assignment_called); + + boost::value_initialized copyFunctionCallTester3; + copyFunctionCallTester3 = boost::value_initialized(copyFunctionCallTester1); + BOOST_TEST ( ! get(copyFunctionCallTester3).is_copy_constructed); + BOOST_TEST ( get(copyFunctionCallTester3).is_assignment_called); + + boost::value_initialized swapFunctionCallTester1; + boost::value_initialized swapFunctionCallTester2; + get(swapFunctionCallTester1).data = 1; + get(swapFunctionCallTester2).data = 2; + boost::core::invoke_swap(swapFunctionCallTester1, swapFunctionCallTester2); + BOOST_TEST( get(swapFunctionCallTester1).data == 2 ); + BOOST_TEST( get(swapFunctionCallTester2).data == 1 ); + BOOST_TEST( get(swapFunctionCallTester1).is_custom_swap_called ); + BOOST_TEST( get(swapFunctionCallTester2).is_custom_swap_called ); + + return boost::report_errors(); +} + + diff --git a/libs/utility/test/value_init_test2.cpp b/libs/utility/test/value_init_test2.cpp new file mode 100644 index 00000000..e3438ccd --- /dev/null +++ b/libs/utility/test/value_init_test2.cpp @@ -0,0 +1,169 @@ +// Copyright 2010, Niels Dekker. +// +// 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) +// +// Test program for the boost::value_initialized workaround. +// +// 17 June 2010 (Created) Niels Dekker + +#include +#include +#include +#include + +namespace +{ + struct empty_struct + { + }; + + // A POD aggregate struct derived from an empty struct. + // Similar to struct Foo1 from Microsoft Visual C++ bug report 484295, + // "VC++ does not value-initialize members of derived classes without + // user-declared constructor", reported in 2009 by Sylvester Hesp: + // https://connect.microsoft.com/VisualStudio/feedback/details/484295 + struct derived_struct: empty_struct + { + int data; + }; + + bool is_value_initialized(const derived_struct& arg) + { + return arg.data == 0; + } + + + class virtual_destructor_holder + { + public: + int i; + virtual ~virtual_destructor_holder() + { + } + }; + + bool is_value_initialized(const virtual_destructor_holder& arg) + { + return arg.i == 0; + } + + // Equivalent to the Stats class from GCC Bug 33916, + // "Default constructor fails to initialize array members", reported in 2007 by + // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 + // and fixed for GCC 4.2.4. + class private_int_array_pair + { + friend bool is_value_initialized(const private_int_array_pair& arg); + private: + int first[12]; + int second[12]; + }; + + bool is_value_initialized(const private_int_array_pair& arg) + { + for ( unsigned i = 0; i < 12; ++i) + { + if ( (arg.first[i] != 0) || (arg.second[i] != 0) ) + { + return false; + } + } + return true; + } + + struct int_pair_struct + { + int first; + int second; + }; + + typedef int int_pair_struct::*ptr_to_member_type; + + struct ptr_to_member_struct + { + ptr_to_member_type data; + }; + + bool is_value_initialized(const ptr_to_member_struct& arg) + { + return arg.data == 0; + } + + template + bool is_value_initialized(const T(& arg)[2]) + { + return + is_value_initialized(arg[0]) && + is_value_initialized(arg[1]); + } + + template + bool is_value_initialized(const boost::value_initialized& arg) + { + return is_value_initialized(arg.data()); + } + + // Returns zero when the specified object is value-initializated, and one otherwise. + // Prints a message to standard output if the value-initialization has failed. + template + unsigned failed_to_value_initialized(const T& object, const char *const object_name) + { + if ( is_value_initialized(object) ) + { + return 0u; + } + else + { + std::cout << "Note: Failed to value-initialize " << object_name << '.' << std::endl; + return 1u; + } + } + +// A macro that passed both the name and the value of the specified object to +// the function above here. +#define FAILED_TO_VALUE_INITIALIZE(value) failed_to_value_initialized(value, #value) + + // Equivalent to the dirty_stack() function from GCC Bug 33916, + // "Default constructor fails to initialize array members", reported in 2007 by + // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 + void dirty_stack() + { + unsigned char array_on_stack[4096]; + for (unsigned i = 0; i < sizeof(array_on_stack); ++i) + { + array_on_stack[i] = 0x11; + } + } + +} + + +int main() +{ +#ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED + + std::cout << "BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED is defined.\n\n"; + +#endif + + dirty_stack(); + + BOOST_TEST( is_value_initialized( boost::value_initialized() ) ); + BOOST_TEST( is_value_initialized( boost::value_initialized() ) ); + BOOST_TEST( is_value_initialized( boost::value_initialized() ) ); + +#if !BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1925) ) + + // Null pointers to data members are represented as -1 in MSVC, but + // value initialization sets them to all zero. The workaround employed + // by value_initialized<> is to memset the storage to all zero, which + // doesn't help. + + BOOST_TEST( is_value_initialized( boost::value_initialized() ) ); + +#endif + + return boost::report_errors(); +} diff --git a/libs/utility/test/value_init_test3.cpp b/libs/utility/test/value_init_test3.cpp new file mode 100644 index 00000000..d90834d5 --- /dev/null +++ b/libs/utility/test/value_init_test3.cpp @@ -0,0 +1,40 @@ +// Copyright 2020 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include + +#if __cplusplus >= 201103L || ( defined(BOOST_MSVC) && BOOST_MSVC >= 1900 ) + +struct X +{ + int a; + char b; +}; + +struct Y: boost::value_initialized +{ + char c = 42; +}; + +int main() +{ + Y y; + + BOOST_TEST_EQ( y.data().a, 0 ); + BOOST_TEST_EQ( y.data().b, 0 ); + BOOST_TEST_EQ( y.c, 42 ); + + return boost::report_errors(); +} + +#else + +BOOST_PRAGMA_MESSAGE( "Skipping test because compiler doesn't support in-class member initializers" ) + +int main() {} + +#endif diff --git a/libs/utility/test/value_init_test_fail1.cpp b/libs/utility/test/value_init_test_fail1.cpp new file mode 100644 index 00000000..c298427d --- /dev/null +++ b/libs/utility/test/value_init_test_fail1.cpp @@ -0,0 +1,27 @@ +// Copyright 2002, Fernando Luis Cacciola Carballal. +// +// 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) +// +// Test program for "boost/utility/value_init.hpp" +// +// Initial: 21 Agu 2002 + +#include +#include + +#include "boost/utility/value_init.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +int main() +{ + boost::value_initialized const x_c ; + + get(x_c) = 1234 ; // this should produce an ERROR + + return 0; +} diff --git a/libs/utility/test/value_init_test_fail2.cpp b/libs/utility/test/value_init_test_fail2.cpp new file mode 100644 index 00000000..7cf3dcb6 --- /dev/null +++ b/libs/utility/test/value_init_test_fail2.cpp @@ -0,0 +1,27 @@ +// Copyright 2002, Fernando Luis Cacciola Carballal. +// +// 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) +// +// Test program for "boost/utility/value_init.hpp" +// +// Initial: 21 Agu 2002 + +#include +#include + +#include "boost/utility/value_init.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +int main() +{ + boost::value_initialized cx ; + + get(cx) = 1234 ; // this should produce an ERROR + + return 0; +} diff --git a/libs/utility/test/value_init_test_fail3.cpp b/libs/utility/test/value_init_test_fail3.cpp new file mode 100644 index 00000000..562bcc26 --- /dev/null +++ b/libs/utility/test/value_init_test_fail3.cpp @@ -0,0 +1,27 @@ +// Copyright 2002, Fernando Luis Cacciola Carballal. +// +// 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) +// +// Test program for "boost/utility/value_init.hpp" +// +// Initial: 21 Agu 2002 + +#include +#include + +#include "boost/utility/value_init.hpp" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +int main() +{ + boost::value_initialized const cx_c ; + + get(cx_c) = 1234 ; // this should produce an ERROR + + return 0; +} diff --git a/libs/utility/test/value_init_workaround_test.cpp b/libs/utility/test/value_init_workaround_test.cpp new file mode 100644 index 00000000..9ffdffc5 --- /dev/null +++ b/libs/utility/test/value_init_workaround_test.cpp @@ -0,0 +1,163 @@ +// Copyright 2010, Niels Dekker. +// +// 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) +// +// Test program for the boost::value_initialized workaround. +// +// 17 June 2010 (Created) Niels Dekker + +// Switch the workaround off, before inluding "value_init.hpp". +#define BOOST_DETAIL_VALUE_INIT_WORKAROUND 0 +#include + +#include // For cout. +#include // For EXIT_SUCCESS and EXIT_FAILURE. + +namespace +{ + struct empty_struct + { + }; + + // A POD aggregate struct derived from an empty struct. + // Similar to struct Foo1 from Microsoft Visual C++ bug report 484295, + // "VC++ does not value-initialize members of derived classes without + // user-declared constructor", reported in 2009 by Sylvester Hesp: + // https://connect.microsoft.com/VisualStudio/feedback/details/484295 + struct derived_struct: empty_struct + { + int data; + }; + + bool is_value_initialized(const derived_struct& arg) + { + return arg.data == 0; + } + + + class virtual_destructor_holder + { + public: + int i; + virtual ~virtual_destructor_holder() + { + } + }; + + bool is_value_initialized(const virtual_destructor_holder& arg) + { + return arg.i == 0; + } + + // Equivalent to the Stats class from GCC Bug 33916, + // "Default constructor fails to initialize array members", reported in 2007 by + // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 + // and fixed for GCC 4.2.4. + class private_int_array_pair + { + friend bool is_value_initialized(const private_int_array_pair& arg); + private: + int first[12]; + int second[12]; + }; + + bool is_value_initialized(const private_int_array_pair& arg) + { + for ( unsigned i = 0; i < 12; ++i) + { + if ( (arg.first[i] != 0) || (arg.second[i] != 0) ) + { + return false; + } + } + return true; + } + + struct int_pair_struct + { + int first; + int second; + }; + + typedef int int_pair_struct::*ptr_to_member_type; + + struct ptr_to_member_struct + { + ptr_to_member_type data; + }; + + bool is_value_initialized(const ptr_to_member_struct& arg) + { + return arg.data == 0; + } + + template + bool is_value_initialized(const T(& arg)[2]) + { + return + is_value_initialized(arg[0]) && + is_value_initialized(arg[1]); + } + + template + bool is_value_initialized(const boost::value_initialized& arg) + { + return is_value_initialized(arg.data()); + } + + // Returns zero when the specified object is value-initializated, and one otherwise. + // Prints a message to standard output if the value-initialization has failed. + template + unsigned failed_to_value_initialized(const T& object, const char *const object_name) + { + if ( is_value_initialized(object) ) + { + return 0u; + } + else + { + std::cout << "Note: Failed to value-initialize " << object_name << '.' << std::endl; + return 1u; + } + } + +// A macro that passed both the name and the value of the specified object to +// the function above here. +#define FAILED_TO_VALUE_INITIALIZE(value) failed_to_value_initialized(value, #value) + + // Equivalent to the dirty_stack() function from GCC Bug 33916, + // "Default constructor fails to initialize array members", reported in 2007 by + // Michael Elizabeth Chastain: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 + void dirty_stack() + { + unsigned char array_on_stack[4096]; + for (unsigned i = 0; i < sizeof(array_on_stack); ++i) + { + array_on_stack[i] = 0x11; + } + } + +} + + +int main() +{ + dirty_stack(); + + // TODO More types may be added later. + const unsigned num_failures = + FAILED_TO_VALUE_INITIALIZE(boost::value_initialized()) + + FAILED_TO_VALUE_INITIALIZE(boost::value_initialized()) + + FAILED_TO_VALUE_INITIALIZE(boost::value_initialized()) + + FAILED_TO_VALUE_INITIALIZE(boost::value_initialized()); + +#ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED + // One or more failures are expected. + return num_failures > 0 ? EXIT_SUCCESS : EXIT_FAILURE; +#else + // No failures are expected. + return num_failures == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +#endif +} diff --git a/libs/utility/throw_exception.html b/libs/utility/throw_exception.html new file mode 100644 index 00000000..75a10518 --- /dev/null +++ b/libs/utility/throw_exception.html @@ -0,0 +1,15 @@ + + + + + Automatic redirection + + +Automatic redirection failed, please go to +../throw_exception/doc/html/throw_exception.html#using_boost_throw_exception
+

Copyright © Beman Dawes, 2001

+

Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy + at www.boost.org/LICENSE_1_0.txt)

+ + diff --git a/libs/utility/utility.htm b/libs/utility/utility.htm new file mode 100644 index 00000000..7569b210 --- /dev/null +++ b/libs/utility/utility.htm @@ -0,0 +1,19 @@ + + + Boost.Utility + + + +Automatic redirection failed, please go to +./doc/html/index.html +
+ + Boost.Utility
+
+ 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/libs/utility/value_init.htm b/libs/utility/value_init.htm new file mode 100644 index 00000000..68954f73 --- /dev/null +++ b/libs/utility/value_init.htm @@ -0,0 +1,19 @@ + + + Boost.Utility + + + +Automatic redirection failed, please go to +./doc/html/utility/utilities/value_init.html +
+ + Boost.Utility
+
+ 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/rst.css b/rst.css new file mode 100644 index 00000000..afd9a98c --- /dev/null +++ b/rst.css @@ -0,0 +1,149 @@ +@import url("doc/src/boostbook.css"); +@import url("doc/src/docutils.css"); +/* Copyright David Abrahams 2006. 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) + */ + +dl.docutils dt { + font-weight: bold } + +img.boost-logo { + border: none; + vertical-align: middle +} + +pre.literal-block span.concept { + font-style: italic; +} + +.nav { +display: inline; +list-style-type: none; +} + +.prevpage { +padding-top: -5px; +text-align: left; +float: left; +} + +.nextpage { +padding-top: -20px; +text-align: right; +float: right; +} + +div.small { + font-size: smaller } + +h2 a { + font-size: 90%; +} +h3 a { + font-size: 80%; +} +h4 a { + font-size: 70%; +} +h5 a { + font-size: 60%; +} + +dl,table +{ + text-align: left; + font-size: 10pt; + line-height: 1.15; +} + + +/*============================================================================= + Tables +=============================================================================*/ + +/* The only clue docutils gives us that tables are logically tables, + and not, e.g., footnotes, is that they have border="1". Therefore + we're keying off of that. We used to manually patch docutils to + add a "table" class to all logical tables, but that proved much too + fragile. +*/ + + table[border="1"] + { + width: 92%; + margin-left: 4%; + margin-right: 4%; + } + + table[border="1"] + { + padding: 4px; + } + + /* Table Cells */ + table[border="1"] tr td + { + padding: 0.5em; + text-align: left; + font-size: 9pt; + } + + table[border="1"] tr th + { + padding: 0.5em 0.5em 0.5em 0.5em; + border: 1pt solid white; + font-size: 80%; + } + + @media screen + { + + /* Tables */ + table[border="1"] tr td + { + border: 1px solid #DCDCDC; + } + + table[border="1"] tr th + { + background-color: #F0F0F0; + border: 1px solid #DCDCDC; + } + + pre, + .screen + { + border: 1px solid #DCDCDC; + } + + td pre + td .screen + { + border: 0px + } + + .sidebar pre + { + border: 0px + } + + } + + pre, + .screen + { + font-size: 9pt; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + /* Program listings in tables don't get borders */ + td pre, + td .screen + { + margin: 0pc 0pc 0pc 0pc; + padding: 0pc 0pc 0pc 0pc; + } +
+

pointee and indirect_reference

+ +++ + + + + + + + + + + + +
Author:David Abrahams
Contact:dave@boost-consulting.com
Organization:Boost Consulting
Date:2006-09-11
Copyright:Copyright David Abrahams 2004.
+ + + + +++ + + + +
abstract:Provides the capability to deduce the referent types of +pointers, smart pointers and iterators in generic code.
+
+
+

Reference

+
+

pointee

+ + + +
+template <class Dereferenceable>
+struct pointee
+{
+    typedef /* see below */ type;
+};
+
+ +++ + + + +
Requires:For an object x of type Dereferenceable, *x +is well-formed. If ++x is ill-formed it shall neither be +ambiguous nor shall it violate access control, and +Dereferenceable::element_type shall be an accessible type. +Otherwise iterator_traits<Dereferenceable>::value_type shall +be well formed. [Note: These requirements need not apply to +explicit or partial specializations of pointee]
+

type is determined according to the following algorithm, where +x is an object of type Dereferenceable:

+
+if ( ++x is ill-formed )
+{
+    return ``Dereferenceable::element_type``
+}
+else if (``*x`` is a mutable reference to
+         std::iterator_traits<Dereferenceable>::value_type)
+{
+    return iterator_traits<Dereferenceable>::value_type
+}
+else
+{
+    return iterator_traits<Dereferenceable>::value_type const
+}
+
+
+
+

indirect_reference

+ + + +
+template <class Dereferenceable>
+struct indirect_reference
+{
+    typedef /* see below */ type;
+};
+
+ +++ + + + +
Requires:For an object x of type Dereferenceable, *x +is well-formed. If ++x is ill-formed it shall neither be +ambiguous nor shall it violate access control, and +pointee<Dereferenceable>::type& shall be well-formed. +Otherwise iterator_traits<Dereferenceable>::reference shall +be well formed. [Note: These requirements need not apply to +explicit or partial specializations of indirect_reference]
+

type is determined according to the following algorithm, where +x is an object of type Dereferenceable:

+
+if ( ++x is ill-formed )
+    return ``pointee<Dereferenceable>::type&``
+else
+    std::iterator_traits<Dereferenceable>::reference
+
+
+
+
+

Iterator Archetype

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@styleadvisor.com
Organization:Boost Consulting, Indiana University Open Systems +Lab, Zephyr Associates, Inc.
Date:2006-09-11
Copyright:Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2004.
+ + + + +++ + + + +
abstract:The iterator_archetype class constructs a minimal implementation of +one of the iterator access concepts and one of the iterator traversal concepts. +This is used for doing a compile-time check to see if a the type requirements +of a template are really enough to cover the implementation of the template. +For further information see the documentation for the boost::concept_check library.
+
+
+

Reference

+
+

iterator_archetype Synopsis

+
+namespace iterator_archetypes
+{
+    // Access categories
+
+    typedef /*implementation  defined*/ readable_iterator_t;
+    typedef /*implementation  defined*/ writable_iterator_t;
+    typedef /*implementation  defined*/ readable_writable_iterator_t;
+    typedef /*implementation  defined*/ readable_lvalue_iterator_t;
+    typedef /*implementation  defined*/ writable_lvalue_iterator_t;
+
+}
+
+template <
+    class Value
+  , class AccessCategory
+  , class TraversalCategory
+>
+class iterator_archetype
+{
+    typedef /* see below */ value_type;
+    typedef /* see below */ reference;
+    typedef /* see below */ pointer;
+    typedef /* see below */ difference_type;
+    typedef /* see below */ iterator_category;
+};
+
+
+
+

Access Category Tags

+

The access category types provided correspond to the following +standard iterator access concept combinations:

+
+readable_iterator_t :=
+
+  Readable Iterator
+
+writable_iterator_t :=
+
+  Writeable Iterator
+
+readable_writable_iterator_t :=
+
+  Readable Iterator & Writeable Iterator & Swappable Iterator
+
+readable_lvalue_iterator_t :=
+
+  Readable Iterator & Lvalue Iterator
+
+writeable_lvalue_iterator_t :=
+
+  Readable Iterator & Writeable Iterator & Swappable Iterator & Lvalue Iterator
+
+
+
+

iterator_archetype Requirements

+

The AccessCategory argument must be one of the predefined access +category tags. The TraversalCategory must be one of the standard +traversal tags. The Value type must satisfy the requirements of +the iterator concept specified by AccessCategory and +TraversalCategory as implied by the nested traits types.

+
+
+

iterator_archetype Models

+

iterator_archetype models the iterator concepts specified by the +AccessCategory and TraversalCategory +arguments. iterator_archetype does not model any other access +concepts or any more derived traversal concepts.

+
+
+

Traits

+

The nested trait types are defined as follows:

+
+if (AccessCategory == readable_iterator_t)
+
+  value_type = Value
+  reference  = Value
+  pointer    = Value*
+
+else if (AccessCategory == writable_iterator_t)
+
+  value_type = void
+  reference  = void
+  pointer    = void
+
+else if (AccessCategory == readable_writable_iterator_t)
+
+  value_type = Value
+
+  reference :=
+
+    A type X that is convertible to Value for which the following
+    expression is valid. Given an object x of type X and v of type
+    Value.
+
+    x = v
+
+  pointer    = Value*
+
+else if (AccessCategory == readable_lvalue_iterator_t)
+
+  value_type = Value
+  reference  = Value const&
+  pointer    = Value const*
+
+else if (AccessCategory == writable_lvalue_iterator_t)
+
+  value_type = Value
+  reference  = Value&
+  pointer    = Value*
+
+if ( TraversalCategory is convertible to forward_traversal_tag )
+
+  difference_type := ptrdiff_t
+
+else
+
+  difference_type := unspecified type
+
+
+iterator_category :=
+
+  A type X satisfying the following two constraints:
+
+     1. X is convertible to X1, and not to any more-derived
+        type, where X1 is defined by:
+
+          if (reference is a reference type
+              && TraversalCategory is convertible to forward_traversal_tag)
+          {
+              if (TraversalCategory is convertible to random_access_traversal_tag)
+                  X1 = random_access_iterator_tag
+              else if (TraversalCategory is convertible to bidirectional_traversal_tag)
+                  X1 = bidirectional_iterator_tag
+              else
+                  X1 = forward_iterator_tag
+          }
+          else
+          {
+              if (TraversalCategory is convertible to single_pass_traversal_tag
+                  && reference != void)
+                  X1 = input_iterator_tag
+              else
+                  X1 = output_iterator_tag
+          }
+
+     2. X is convertible to TraversalCategory
+
+
+
+
+

Filter Iterator

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de
Organization:Boost Consulting, Indiana University Open Systems +Lab, University of Hanover Institute for Transport +Railway Operation and Construction
Date:2006-09-11
Copyright:Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
+ + + + +++ + + + +
abstract: + + +The filter iterator adaptor creates a view of an iterator range in +which some elements of the range are skipped. A predicate function +object controls which elements are skipped. When the predicate is +applied to an element, if it returns true then the element is +retained and if it returns false then the element is skipped +over. When skipping over elements, it is necessary for the filter +adaptor to know when to stop so as to avoid going past the end of the +underlying range. A filter iterator is therefore constructed with pair +of iterators indicating the range of elements in the unfiltered +sequence to be traversed.
+
+
+

filter_iterator synopsis

+ + + + +
+template <class Predicate, class Iterator>
+class filter_iterator
+{
+ public:
+    typedef iterator_traits<Iterator>::value_type value_type;
+    typedef iterator_traits<Iterator>::reference reference;
+    typedef iterator_traits<Iterator>::pointer pointer;
+    typedef iterator_traits<Iterator>::difference_type difference_type;
+    typedef /* see below */ iterator_category;
+
+    filter_iterator();
+    filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());
+    filter_iterator(Iterator x, Iterator end = Iterator());
+    template<class OtherIterator>
+    filter_iterator(
+        filter_iterator<Predicate, OtherIterator> const& t
+        , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+        );
+    Predicate predicate() const;
+    Iterator end() const;
+    Iterator const& base() const;
+    reference operator*() const;
+    filter_iterator& operator++();
+private:
+    Predicate m_pred; // exposition only
+    Iterator m_iter;  // exposition only
+    Iterator m_end;   // exposition only
+};
+
+

If Iterator models Readable Lvalue Iterator and Bidirectional Traversal +Iterator then iterator_category is convertible to +std::bidirectional_iterator_tag. +Otherwise, if Iterator models Readable Lvalue Iterator and Forward Traversal +Iterator then iterator_category is convertible to +std::forward_iterator_tag. +Otherwise iterator_category is +convertible to std::input_iterator_tag.

+
+
+

filter_iterator requirements

+

The Iterator argument shall meet the requirements of Readable +Iterator and Single Pass Iterator or it shall meet the requirements of +Input Iterator.

+

The Predicate argument must be Assignable, Copy Constructible, and +the expression p(x) must be valid where p is an object of type +Predicate, x is an object of type +iterator_traits<Iterator>::value_type, and where the type of +p(x) must be convertible to bool.

+
+
+

filter_iterator models

+

The concepts that filter_iterator models are dependent on which +concepts the Iterator argument models, as specified in the +following tables.

+ ++++ + + + + + + + + + + + + + + + + +
If Iterator modelsthen filter_iterator models
Single Pass IteratorSingle Pass Iterator
Forward Traversal IteratorForward Traversal Iterator
Bidirectional Traversal IteratorBidirectional Traversal Iterator
+ ++++ + + + + + + + + + + + + + + + + +
If Iterator modelsthen filter_iterator models
Readable IteratorReadable Iterator
Writable IteratorWritable Iterator
Lvalue IteratorLvalue Iterator
+ ++++ + + + + + + + + + + + + + + + + + + + +
If Iterator modelsthen filter_iterator models
Readable Iterator, Single Pass IteratorInput Iterator
Readable Lvalue Iterator, Forward Traversal IteratorForward Iterator
Writable Lvalue Iterator, Forward Traversal IteratorMutable Forward Iterator
Writable Lvalue Iterator, Bidirectional IteratorMutable Bidirectional Iterator
+

filter_iterator<P1, X> is interoperable with filter_iterator<P2, Y> +if and only if X is interoperable with Y.

+
+
+

filter_iterator operations

+

In addition to those operations required by the concepts that +filter_iterator models, filter_iterator provides the following +operations.

+

filter_iterator();

+ +++ + + + + + +
Requires:Predicate and Iterator must be Default Constructible.
Effects:Constructs a filter_iterator whose``m_pred``, m_iter, and m_end +members are a default constructed.
+

filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());

+ +++ + + + +
Effects:Constructs a filter_iterator where m_iter is either +the first position in the range [x,end) such that f(*m_iter) == true +or else``m_iter == end``. The member m_pred is constructed from +f and m_end from end.
+

filter_iterator(Iterator x, Iterator end = Iterator());

+ +++ + + + + + +
Requires:Predicate must be Default Constructible and +Predicate is a class type (not a function pointer).
Effects:Constructs a filter_iterator where m_iter is either +the first position in the range [x,end) such that m_pred(*m_iter) == true +or else``m_iter == end``. The member m_pred is default constructed.
+
+template <class OtherIterator>
+filter_iterator(
+    filter_iterator<Predicate, OtherIterator> const& t
+    , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+    );``
+
+ +++ + + + + + +
Requires:OtherIterator is implicitly convertible to Iterator.
Effects:Constructs a filter iterator whose members are copied from t.
+

Predicate predicate() const;

+ +++ + + + +
Returns:m_pred
+

Iterator end() const;

+ +++ + + + +
Returns:m_end
+

Iterator const& base() const;

+ +++ + + + +
Returns:m_iterator
+

reference operator*() const;

+ +++ + + + +
Returns:*m_iter
+

filter_iterator& operator++();

+ +++ + + + + + +
Effects:Increments m_iter and then continues to +increment m_iter until either m_iter == m_end +or m_pred(*m_iter) == true.
Returns:*this
+ + + +
+template <class Predicate, class Iterator>
+filter_iterator<Predicate,Iterator>
+make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());
+
+ +++ + + + +
Returns:filter_iterator<Predicate,Iterator>(f, x, end)
+
+template <class Predicate, class Iterator>
+filter_iterator<Predicate,Iterator>
+make_filter_iterator(Iterator x, Iterator end = Iterator());
+
+ +++ + + + +
Returns:filter_iterator<Predicate,Iterator>(x, end)
+ + + +
+
+

Example

+

This example uses filter_iterator and then +make_filter_iterator to output only the positive integers from an +array of integers. Then make_filter_iterator is is used to output +the integers greater than -2.

+
+struct is_positive_number {
+  bool operator()(int x) { return 0 < x; }
+};
+
+int main()
+{
+  int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 };
+  const int N = sizeof(numbers_)/sizeof(int);
+
+  typedef int* base_iterator;
+  base_iterator numbers(numbers_);
+
+  // Example using filter_iterator
+  typedef boost::filter_iterator<is_positive_number, base_iterator>
+    FilterIter;
+
+  is_positive_number predicate;
+  FilterIter filter_iter_first(predicate, numbers, numbers + N);
+  FilterIter filter_iter_last(predicate, numbers + N, numbers + N);
+
+  std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator<int>(std::cout, " "));
+  std::cout << std::endl;
+
+  // Example using make_filter_iterator()
+  std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
+            boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
+            std::ostream_iterator<int>(std::cout, " "));
+  std::cout << std::endl;
+
+  // Another example using make_filter_iterator()
+  std::copy(
+      boost::make_filter_iterator(
+          std::bind2nd(std::greater<int>(), -2)
+        , numbers, numbers + N)
+
+    , boost::make_filter_iterator(
+          std::bind2nd(std::greater<int>(), -2)
+        , numbers + N, numbers + N)
+
+    , std::ostream_iterator<int>(std::cout, " ")
+  );
+
+  std::cout << std::endl;
+
+  return boost::exit_success;
+}
+
+

The output is:

+
+4 5 8
+4 5 8
+0 -1 4 5 8
+
+

The source code for this example can be found here.

+
+
+

Iterator Facade and Adaptor

+ +++ + + + + + + + + + + + +
Author:David Abrahams, Jeremy Siek, Thomas Witt
Contact:dave@boost-consulting.com, jsiek@osl.iu.edu, witt@styleadvisor.com
Organization:Boost Consulting, Indiana University Open Systems +Lab, Zephyr Associates, Inc.
Date:2006-09-11
Number:This is a revised version of N1530=03-0113, which was +accepted for Technical Report 1 by the C++ standard +committee's library working group.
+ + + + + +++ + + + +
copyright:Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
+ +++ + + + +
abstract:We propose a set of class templates that help programmers +build standard-conforming iterators, both from scratch and +by adapting other iterators.
+
+

Table of Contents

+
+
+
+

Motivation

+

Iterators play an important role in modern C++ programming. The +iterator is the central abstraction of the algorithms of the Standard +Library, allowing algorithms to be re-used in in a wide variety of +contexts. The C++ Standard Library contains a wide variety of useful +iterators. Every one of the standard containers comes with constant +and mutable iterators2, and also reverse versions of those +same iterators which traverse the container in the opposite direction. +The Standard also supplies istream_iterator and +ostream_iterator for reading from and writing to streams, +insert_iterator, front_insert_iterator and +back_insert_iterator for inserting elements into containers, and +raw_storage_iterator for initializing raw memory [7].

+

Despite the many iterators supplied by the Standard Library, obvious +and useful iterators are missing, and creating new iterator types is +still a common task for C++ programmers. The literature documents +several of these, for example line_iterator [3] and Constant_iterator +[9]. The iterator abstraction is so powerful that we expect +programmers will always need to invent new iterator types.

+

Although it is easy to create iterators that almost conform to the +standard, the iterator requirements contain subtleties which can make +creating an iterator which actually conforms quite difficult. +Further, the iterator interface is rich, containing many operators +that are technically redundant and tedious to implement. To automate +the repetitive work of constructing iterators, we propose +iterator_facade, an iterator base class template which provides +the rich interface of standard iterators and delegates its +implementation to member functions of the derived class. In addition +to reducing the amount of code necessary to create an iterator, the +iterator_facade also provides compile-time error detection. +Iterator implementation mistakes that often go unnoticed are turned +into compile-time errors because the derived class implementation must +match the expectations of the iterator_facade.

+

A common pattern of iterator construction is the adaptation of one +iterator to form a new one. The functionality of an iterator is +composed of four orthogonal aspects: traversal, indirection, equality +comparison and distance measurement. Adapting an old iterator to +create a new one often saves work because one can reuse one aspect of +functionality while redefining the other. For example, the Standard +provides reverse_iterator, which adapts any Bidirectional Iterator +by inverting its direction of traversal. As with plain iterators, +iterator adaptors defined outside the Standard have become commonplace +in the literature:

+
    +
  • Checked iter[13] adds bounds-checking to an existing iterator.
  • +
  • The iterators of the View Template Library[14], which adapts +containers, are themselves adaptors over the underlying iterators.
  • +
  • Smart iterators [5] adapt an iterator's dereferencing behavior by +applying a function object to the object being referenced and +returning the result.
  • +
  • Custom iterators [4], in which a variety of adaptor types are enumerated.
  • +
  • Compound iterators [1], which access a slice out of a container of containers.
  • +
  • Several iterator adaptors from the MTL [12]. The MTL contains a +strided iterator, where each call to operator++() moves the +iterator ahead by some constant factor, and a scaled iterator, which +multiplies the dereferenced value by some constant.
  • +
+ + + + + +
[1]We use the term concept to mean a set of requirements +that a type must satisfy to be used with a particular template +parameter.
+ + + + + +
[2]The term mutable iterator refers to iterators over objects that +can be changed by assigning to the dereferenced iterator, while +constant iterator refers to iterators over objects that cannot be +modified.
+

To fulfill the need for constructing adaptors, we propose the +iterator_adaptor class template. Instantiations of +iterator_adaptor serve as a base classes for new iterators, +providing the default behavior of forwarding all operations to the +underlying iterator. The user can selectively replace these features +in the derived iterator class. This proposal also includes a number +of more specialized adaptors, such as the transform_iterator that +applies some user-specified function during the dereference of the +iterator.

+
+
+

Impact on the Standard

+

This proposal is purely an addition to the C++ standard library. +However, note that this proposal relies on the proposal for New +Iterator Concepts.

+
+
+

Design

+
+

Iterator Concepts

+

This proposal is formulated in terms of the new iterator concepts +as proposed in n1550, since user-defined and especially adapted +iterators suffer from the well known categorization problems that are +inherent to the current iterator categories.

+

This proposal does not strictly depend on proposal n1550, as there +is a direct mapping between new and old categories. This proposal +could be reformulated using this mapping if n1550 was not accepted.

+
+
+

Interoperability

+

The question of iterator interoperability is poorly addressed in the +current standard. There are currently two defect reports that are +concerned with interoperability issues.

+

Issue 179 concerns the fact that mutable container iterator types +are only required to be convertible to the corresponding constant +iterator types, but objects of these types are not required to +interoperate in comparison or subtraction expressions. This situation +is tedious in practice and out of line with the way built in types +work. This proposal implements the proposed resolution to issue +179, as most standard library implementations do nowadays. In other +words, if an iterator type A has an implicit or user defined +conversion to an iterator type B, the iterator types are interoperable +and the usual set of operators are available.

+

Issue 280 concerns the current lack of interoperability between +reverse iterator types. The proposed new reverse_iterator template +fixes the issues raised in 280. It provides the desired +interoperability without introducing unwanted overloads.

+
+
+

Iterator Facade

+ + + + + +

While the iterator interface is rich, there is a core subset of the +interface that is necessary for all the functionality. We have +identified the following core behaviors for iterators:

+
    +
  • dereferencing
  • +
  • incrementing
  • +
  • decrementing
  • +
  • equality comparison
  • +
  • random-access motion
  • +
  • distance measurement
  • +
+

In addition to the behaviors listed above, the core interface elements +include the associated types exposed through iterator traits: +value_type, reference, difference_type, and +iterator_category.

+

Iterator facade uses the Curiously Recurring Template +Pattern (CRTP) [Cop95] so that the user can specify the behavior +of iterator_facade in a derived class. Former designs used +policy objects to specify the behavior, but that approach was +discarded for several reasons:

+
+
    +
  1. the creation and eventual copying of the policy object may create +overhead that can be avoided with the current approach.
  2. +
  3. The policy object approach does not allow for custom constructors +on the created iterator types, an essential feature if +iterator_facade should be used in other library +implementations.
  4. +
  5. Without the use of CRTP, the standard requirement that an +iterator's operator++ returns the iterator type itself +would mean that all iterators built with the library would +have to be specializations of iterator_facade<...>, rather +than something more descriptive like +indirect_iterator<T*>. Cumbersome type generator +metafunctions would be needed to build new parameterized +iterators, and a separate iterator_adaptor layer would be +impossible.
  6. +
+
+
+

Usage

+

The user of iterator_facade derives his iterator class from a +specialization of iterator_facade and passes the derived +iterator class as iterator_facade's first template parameter. +The order of the other template parameters have been carefully +chosen to take advantage of useful defaults. For example, when +defining a constant lvalue iterator, the user can pass a +const-qualified version of the iterator's value_type as +iterator_facade's Value parameter and omit the +Reference parameter which follows.

+

The derived iterator class must define member functions implementing +the iterator's core behaviors. The following table describes +expressions which are required to be valid depending on the category +of the derived iterator type. These member functions are described +briefly below and in more detail in the iterator facade +requirements.

+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionEffects
i.dereference()Access the value referred to
i.equal(j)Compare for equality with j
i.increment()Advance by one position
i.decrement()Retreat by one position
i.advance(n)Advance by n positions
i.distance_to(j)Measure the distance to j
+
+ +

In addition to implementing the core interface functions, an iterator +derived from iterator_facade typically defines several +constructors. To model any of the standard iterator concepts, the +iterator must at least have a copy constructor. Also, if the iterator +type X is meant to be automatically interoperate with another +iterator type Y (as with constant and mutable iterators) then +there must be an implicit conversion from X to Y or from Y +to X (but not both), typically implemented as a conversion +constructor. Finally, if the iterator is to model Forward Traversal +Iterator or a more-refined iterator concept, a default constructor is +required.

+
+
+

Iterator Core Access

+

iterator_facade and the operator implementations need to be able +to access the core member functions in the derived class. Making the +core member functions public would expose an implementation detail to +the user. The design used here ensures that implementation details do +not appear in the public interface of the derived iterator type.

+

Preventing direct access to the core member functions has two +advantages. First, there is no possibility for the user to accidently +use a member function of the iterator when a member of the value_type +was intended. This has been an issue with smart pointer +implementations in the past. The second and main advantage is that +library implementers can freely exchange a hand-rolled iterator +implementation for one based on iterator_facade without fear of +breaking code that was accessing the public core member functions +directly.

+

In a naive implementation, keeping the derived class' core member +functions private would require it to grant friendship to +iterator_facade and each of the seven operators. In order to +reduce the burden of limiting access, iterator_core_access is +provided, a class that acts as a gateway to the core member functions +in the derived iterator class. The author of the derived class only +needs to grant friendship to iterator_core_access to make his core +member functions available to the library.

+ + +

iterator_core_access will be typically implemented as an empty +class containing only private static member functions which invoke the +iterator core member functions. There is, however, no need to +standardize the gateway protocol. Note that even if +iterator_core_access used public member functions it would not +open a safety loophole, as every core member function preserves the +invariants of the iterator.

+
+
+

operator[]

+

The indexing operator for a generalized iterator presents special +challenges. A random access iterator's operator[] is only +required to return something convertible to its value_type. +Requiring that it return an lvalue would rule out currently-legal +random-access iterators which hold the referenced value in a data +member (e.g. counting_iterator), because *(p+n) is a reference +into the temporary iterator p+n, which is destroyed when +operator[] returns.

+

Writable iterators built with iterator_facade implement the +semantics required by the preferred resolution to issue 299 and +adopted by proposal n1550: the result of p[n] is an object +convertible to the iterator's value_type, and p[n] = x is +equivalent to *(p + n) = x (Note: This result object may be +implemented as a proxy containing a copy of p+n). This approach +will work properly for any random-access iterator regardless of the +other details of its implementation. A user who knows more about +the implementation of her iterator is free to implement an +operator[] that returns an lvalue in the derived iterator +class; it will hide the one supplied by iterator_facade from +clients of her iterator.

+
+
+

operator->

+

The reference type of a readable iterator (and today's input +iterator) need not in fact be a reference, so long as it is +convertible to the iterator's value_type. When the value_type +is a class, however, it must still be possible to access members +through operator->. Therefore, an iterator whose reference +type is not in fact a reference must return a proxy containing a copy +of the referenced value from its operator->.

+

The return types for iterator_facade's operator-> and +operator[] are not explicitly specified. Instead, those types +are described in terms of a set of requirements, which must be +satisfied by the iterator_facade implementation.

+ + + + + +
[Cop95][Coplien, 1995] Coplien, J., Curiously Recurring Template +Patterns, C++ Report, February 1995, pp. 24-27.
+
+
+
+

Iterator Adaptor

+ + + + + +

The iterator_adaptor class template adapts some Base3 +type to create a new iterator. Instantiations of iterator_adaptor +are derived from a corresponding instantiation of iterator_facade +and implement the core behaviors in terms of the Base type. In +essence, iterator_adaptor merely forwards all operations to an +instance of the Base type, which it stores as a member.

+ + + + + +
[3]The term "Base" here does not refer to a base class and is +not meant to imply the use of derivation. We have followed the lead +of the standard library, which provides a base() function to access +the underlying iterator object of a reverse_iterator adaptor.
+

The user of iterator_adaptor creates a class derived from an +instantiation of iterator_adaptor and then selectively +redefines some of the core member functions described in the +iterator_facade core requirements table. The Base type need +not meet the full requirements for an iterator; it need only +support the operations used by the core interface functions of +iterator_adaptor that have not been redefined in the user's +derived class.

+

Several of the template parameters of iterator_adaptor default +to use_default. This allows the +user to make use of a default parameter even when she wants to +specify a parameter later in the parameter list. Also, the +defaults for the corresponding associated types are somewhat +complicated, so metaprogramming is required to compute them, and +use_default can help to simplify the implementation. Finally, +the identity of the use_default type is not left unspecified +because specification helps to highlight that the Reference +template parameter may not always be identical to the iterator's +reference type, and will keep users from making mistakes based on +that assumption.

+
+
+

Specialized Adaptors

+

This proposal also contains several examples of specialized adaptors +which were easily implemented using iterator_adaptor:

+
    +
  • indirect_iterator, which iterates over iterators, pointers, +or smart pointers and applies an extra level of dereferencing.
  • +
  • A new reverse_iterator, which inverts the direction of a Base +iterator's motion, while allowing adapted constant and mutable +iterators to interact in the expected ways (unlike those in most +implementations of C++98).
  • +
  • transform_iterator, which applies a user-defined function object +to the underlying values when dereferenced.
  • +
  • filter_iterator, which provides a view of an iterator range in +which some elements of the underlying range are skipped.
  • +
+
    +
  • counting_iterator, which adapts any incrementable type +(e.g. integers, iterators) so that incrementing/decrementing the +adapted iterator and dereferencing it produces successive values of +the Base type.
  • +
  • function_output_iterator, which makes it easier to create custom +output iterators.
  • +
+

Based on examples in the Boost library, users have generated many new +adaptors, among them a permutation adaptor which applies some +permutation to a random access iterator, and a strided adaptor, which +adapts a random access iterator by multiplying its unit of motion by a +constant factor. In addition, the Boost Graph Library (BGL) uses +iterator adaptors to adapt other graph libraries, such as LEDA [10] +and Stanford GraphBase [8], to the BGL interface (which requires C++ +Standard compliant iterators).

+
+
+
+

Proposed Text

+
+

Header <iterator_helper> synopsis [lib.iterator.helper.synopsis]

+
+struct use_default;
+
+struct iterator_core_access { /* implementation detail */ };
+
+template <
+    class Derived
+  , class Value
+  , class CategoryOrTraversal
+  , class Reference  = Value&
+  , class Difference = ptrdiff_t
+>
+class iterator_facade;
+
+template <
+    class Derived
+  , class Base
+  , class Value      = use_default
+  , class CategoryOrTraversal  = use_default
+  , class Reference  = use_default
+  , class Difference = use_default
+>
+class iterator_adaptor;
+
+template <
+    class Iterator
+  , class Value = use_default
+  , class CategoryOrTraversal = use_default
+  , class Reference = use_default
+  , class Difference = use_default
+>
+class indirect_iterator;
+
+template <class Dereferenceable>
+struct pointee;
+
+template <class Dereferenceable>
+struct indirect_reference;
+
+template <class Iterator>
+class reverse_iterator;
+
+template <
+    class UnaryFunction
+  , class Iterator
+  , class Reference = use_default
+  , class Value = use_default
+>
+class transform_iterator;
+
+template <class Predicate, class Iterator>
+class filter_iterator;
+
+template <
+    class Incrementable
+  , class CategoryOrTraversal  = use_default
+  , class Difference = use_default
+>
+class counting_iterator;
+
+template <class UnaryFunction>
+class function_output_iterator;
+
+
+
+

Iterator facade [lib.iterator.facade]

+ + + +

iterator_facade is a base class template that implements the +interface of standard iterators in terms of a few core functions +and associated types, to be supplied by a derived iterator class.

+
+

Class template iterator_facade

+ + + + + +
+template <
+    class Derived
+  , class Value
+  , class CategoryOrTraversal
+  , class Reference  = Value&
+  , class Difference = ptrdiff_t
+>
+class iterator_facade {
+ public:
+    typedef remove_const<Value>::type value_type;
+    typedef Reference reference;
+    typedef Value* pointer;
+    typedef Difference difference_type;
+    typedef /* see below */ iterator_category;
+
+    reference operator*() const;
+    /* see below */ operator->() const;
+    /* see below */ operator[](difference_type n) const;
+    Derived& operator++();
+    Derived operator++(int);
+    Derived& operator--();
+    Derived operator--(int);
+    Derived& operator+=(difference_type n);
+    Derived& operator-=(difference_type n);
+    Derived operator-(difference_type n) const;
+ protected:
+    typedef iterator_facade iterator_facade_;
+};
+
+// Comparison operators
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type // exposition
+operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+           iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+           iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+// Iterator difference
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+/* see below */
+operator-(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+          iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+// Iterator addition
+template <class Dr, class V, class TC, class R, class D>
+Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&,
+                   typename Derived::difference_type n);
+
+template <class Dr, class V, class TC, class R, class D>
+Derived operator+ (typename Derived::difference_type n,
+                   iterator_facade<Dr,V,TC,R,D> const&);
+
+

The iterator_category member of iterator_facade is

+
+iterator-category(CategoryOrTraversal, value_type, reference)
+
+

where iterator-category is defined as follows:

+
+iterator-category(C,R,V) :=
+   if (C is convertible to std::input_iterator_tag
+       || C is convertible to std::output_iterator_tag
+   )
+       return C
+
+   else if (C is not convertible to incrementable_traversal_tag)
+       the program is ill-formed
+
+   else return a type X satisfying the following two constraints:
+
+      1. X is convertible to X1, and not to any more-derived
+         type, where X1 is defined by:
+
+           if (R is a reference type
+               && C is convertible to forward_traversal_tag)
+           {
+               if (C is convertible to random_access_traversal_tag)
+                   X1 = random_access_iterator_tag
+               else if (C is convertible to bidirectional_traversal_tag)
+                   X1 = bidirectional_iterator_tag
+               else
+                   X1 = forward_iterator_tag
+           }
+           else
+           {
+               if (C is convertible to single_pass_traversal_tag
+                   && R is convertible to V)
+                   X1 = input_iterator_tag
+               else
+                   X1 = C
+           }
+
+      2. category-to-traversal(X) is convertible to the most
+         derived traversal tag type to which X is also
+         convertible, and not to any more-derived traversal tag
+         type.
+
+

[Note: the intention is to allow iterator_category to be one of +the five original category tags when convertibility to one of the +traversal tags would add no information]

+ + + +

The enable_if_interoperable template used above is for exposition +purposes. The member operators should only be in an overload set +provided the derived types Dr1 and Dr2 are interoperable, +meaning that at least one of the types is convertible to the other. The +enable_if_interoperable approach uses SFINAE to take the operators +out of the overload set when the types are not interoperable. +The operators should behave as-if enable_if_interoperable +were defined to be:

+
+template <bool, typename> enable_if_interoperable_impl
+{};
+
+template <typename T> enable_if_interoperable_impl<true,T>
+{ typedef T type; };
+
+template<typename Dr1, typename Dr2, typename T>
+struct enable_if_interoperable
+  : enable_if_interoperable_impl<
+        is_convertible<Dr1,Dr2>::value || is_convertible<Dr2,Dr1>::value
+      , T
+    >
+{};
+
+
+
+

iterator_facade Requirements

+

The following table describes the typical valid expressions on +iterator_facade's Derived parameter, depending on the +iterator concept(s) it will model. The operations in the first +column must be made accessible to member functions of class +iterator_core_access. In addition, +static_cast<Derived*>(iterator_facade*) shall be well-formed.

+

In the table below, F is iterator_facade<X,V,C,R,D>, a is an +object of type X, b and c are objects of type const X, +n is an object of F::difference_type, y is a constant +object of a single pass iterator type interoperable with X, and z +is a constant object of a random access traversal iterator type +interoperable with X.

+
+

iterator_facade Core Operations

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ExpressionReturn TypeAssertion/NoteUsed to implement Iterator +Concept(s)
c.dereference()F::reference Readable Iterator, Writable +Iterator
c.equal(y)convertible to booltrue iff c and y +refer to the same +position.Single Pass Iterator
a.increment()unused Incrementable Iterator
a.decrement()unused Bidirectional Traversal +Iterator
a.advance(n)unused Random Access Traversal +Iterator
c.distance_to(z)convertible to +F::difference_typeequivalent to +distance(c, X(z)).Random Access Traversal +Iterator
+
+
+
+

iterator_facade operations

+

The operations in this section are described in terms of operations on +the core interface of Derived which may be inaccessible +(i.e. private). The implementation should access these operations +through member functions of class iterator_core_access.

+

reference operator*() const;

+ +++ + + + +
Returns:static_cast<Derived const*>(this)->dereference()
+

operator->() const; (see below)

+ +++ + + + +
Returns:

If reference is a reference type, an object +of type pointer equal to:

+
+&static_cast<Derived const*>(this)->dereference()
+
+

Otherwise returns an object of unspecified type such that, +(*static_cast<Derived const*>(this))->m is equivalent to (w = **static_cast<Derived const*>(this), +w.m) for some temporary object w of type value_type.

+
+

unspecified operator[](difference_type n) const;

+ +++ + + + +
Returns:an object convertible to value_type. For constant +objects v of type value_type, and n of type +difference_type, (*this)[n] = v is equivalent to +*(*this + n) = v, and static_cast<value_type +const&>((*this)[n]) is equivalent to +static_cast<value_type const&>(*(*this + n))
+

Derived& operator++();

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->increment();
+return *static_cast<Derived*>(this);
+
+
+

Derived operator++(int);

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+++*this;
+return tmp;
+
+
+

Derived& operator--();

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->decrement();
+return *static_cast<Derived*>(this);
+
+
+

Derived operator--(int);

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+--*this;
+return tmp;
+
+
+

Derived& operator+=(difference_type n);

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->advance(n);
+return *static_cast<Derived*>(this);
+
+
+

Derived& operator-=(difference_type n);

+ +++ + + + +
Effects:
+static_cast<Derived*>(this)->advance(-n);
+return *static_cast<Derived*>(this);
+
+
+

Derived operator-(difference_type n) const;

+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+return tmp -= n;
+
+
+
+template <class Dr, class V, class TC, class R, class D>
+Derived operator+ (iterator_facade<Dr,V,TC,R,D> const&,
+                   typename Derived::difference_type n);
+
+template <class Dr, class V, class TC, class R, class D>
+Derived operator+ (typename Derived::difference_type n,
+                   iterator_facade<Dr,V,TC,R,D> const&);
+
+ +++ + + + +
Effects:
+Derived tmp(static_cast<Derived const*>(this));
+return tmp += n;
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator ==(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + +
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

((Dr1 const&)lhs).equal((Dr2 const&)rhs).

+
+
Otherwise,
+

((Dr2 const&)rhs).equal((Dr1 const&)lhs).

+
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator !=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + +
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

!((Dr1 const&)lhs).equal((Dr2 const&)rhs).

+
+
Otherwise,
+

!((Dr2 const&)rhs).equal((Dr1 const&)lhs).

+
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator <(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+           iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + +
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) < 0.

+
+
Otherwise,
+

((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) > 0.

+
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator <=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + +
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) <= 0.

+
+
Otherwise,
+

((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) >= 0.

+
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator >(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+           iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + +
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) > 0.

+
+
Otherwise,
+

((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) < 0.

+
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,bool>::type
+operator >=(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+            iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + +
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

((Dr1 const&)lhs).distance_to((Dr2 const&)rhs) >= 0.

+
+
Otherwise,
+

((Dr2 const&)rhs).distance_to((Dr1 const&)lhs) <= 0.

+
+
+
+
+template <class Dr1, class V1, class TC1, class R1, class D1,
+          class Dr2, class V2, class TC2, class R2, class D2>
+typename enable_if_interoperable<Dr1,Dr2,difference>::type
+operator -(iterator_facade<Dr1,V1,TC1,R1,D1> const& lhs,
+           iterator_facade<Dr2,V2,TC2,R2,D2> const& rhs);
+
+ +++ + + + + + +
Return Type:

if is_convertible<Dr2,Dr1>::value

+
+
+
then
+

difference shall be +iterator_traits<Dr1>::difference_type.

+
+
Otherwise
+

difference shall be iterator_traits<Dr2>::difference_type

+
+
+
+
Returns:

if is_convertible<Dr2,Dr1>::value

+
+
then
+

-((Dr1 const&)lhs).distance_to((Dr2 const&)rhs).

+
+
Otherwise,
+

((Dr2 const&)rhs).distance_to((Dr1 const&)lhs).

+
+
+
+
+
+
+

Iterator adaptor [lib.iterator.adaptor]

+ + + + + +

Each specialization of the iterator_adaptor class template is derived from +a specialization of iterator_facade. The core interface functions +expected by iterator_facade are implemented in terms of the +iterator_adaptor's Base template parameter. A class derived +from iterator_adaptor typically redefines some of the core +interface functions to adapt the behavior of the Base type. +Whether the derived class models any of the standard iterator concepts +depends on the operations supported by the Base type and which +core interface functions of iterator_facade are redefined in the +Derived class.

+
+

Class template iterator_adaptor

+ + + + + +
+template <
+    class Derived
+  , class Base
+  , class Value               = use_default
+  , class CategoryOrTraversal = use_default
+  , class Reference           = use_default
+  , class Difference = use_default
+>
+class iterator_adaptor
+  : public iterator_facade<Derived, V', C', R', D'> // see details
+{
+    friend class iterator_core_access;
+ public:
+    iterator_adaptor();
+    explicit iterator_adaptor(Base const& iter);
+    typedef Base base_type;
+    Base const& base() const;
+ protected:
+    typedef iterator_adaptor iterator_adaptor_;
+    Base const& base_reference() const;
+    Base& base_reference();
+ private: // Core iterator interface for iterator_facade.
+    typename iterator_adaptor::reference dereference() const;
+
+    template <
+    class OtherDerived, class OtherIterator, class V, class C, class R, class D
+    >
+    bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
+
+    void advance(typename iterator_adaptor::difference_type n);
+    void increment();
+    void decrement();
+
+    template <
+        class OtherDerived, class OtherIterator, class V, class C, class R, class D
+    >
+    typename iterator_adaptor::difference_type distance_to(
+        iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
+
+ private:
+    Base m_iterator; // exposition only
+};
+
+
+
+

iterator_adaptor requirements

+

static_cast<Derived*>(iterator_adaptor*) shall be well-formed. +The Base argument shall be Assignable and Copy Constructible.

+
+
+

iterator_adaptor base class parameters

+

The V', C', R', and D' parameters of the iterator_facade +used as a base class in the summary of iterator_adaptor +above are defined as follows:

+
+V' = if (Value is use_default)
+          return iterator_traits<Base>::value_type
+      else
+          return Value
+
+C' = if (CategoryOrTraversal is use_default)
+          return iterator_traversal<Base>::type
+      else
+          return CategoryOrTraversal
+
+R' = if (Reference is use_default)
+          if (Value is use_default)
+              return iterator_traits<Base>::reference
+          else
+              return Value&
+      else
+          return Reference
+
+D' = if (Difference is use_default)
+          return iterator_traits<Base>::difference_type
+      else
+          return Difference
+
+ + + +
+
+

iterator_adaptor public operations

+

iterator_adaptor();

+ +++ + + + + + +
Requires:The Base type must be Default Constructible.
Returns:An instance of iterator_adaptor with +m_iterator default constructed.
+

explicit iterator_adaptor(Base const& iter);

+ +++ + + + +
Returns:An instance of iterator_adaptor with +m_iterator copy constructed from iter.
+

Base const& base() const;

+ +++ + + + +
Returns:m_iterator
+
+
+

iterator_adaptor protected member functions

+

Base const& base_reference() const;

+ +++ + + + +
Returns:A const reference to m_iterator.
+

Base& base_reference();

+ +++ + + + +
Returns:A non-const reference to m_iterator.
+
+
+

iterator_adaptor private member functions

+

typename iterator_adaptor::reference dereference() const;

+ +++ + + + +
Returns:*m_iterator
+
+template <
+class OtherDerived, class OtherIterator, class V, class C, class R, class D
+>
+bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const;
+
+ +++ + + + +
Returns:m_iterator == x.base()
+

void advance(typename iterator_adaptor::difference_type n);

+ +++ + + + +
Effects:m_iterator += n;
+

void increment();

+ +++ + + + +
Effects:++m_iterator;
+

void decrement();

+ +++ + + + +
Effects:--m_iterator;
+
+template <
+    class OtherDerived, class OtherIterator, class V, class C, class R, class D
+>
+typename iterator_adaptor::difference_type distance_to(
+    iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const;
+
+ +++ + + + +
Returns:y.base() - m_iterator
+
+
+
+

Specialized adaptors [lib.iterator.special.adaptors]

+

The enable_if_convertible<X,Y>::type expression used in +this section is for exposition purposes. The converting constructors +for specialized adaptors should be only be in an overload set provided +that an object of type X is implicitly convertible to an object of +type Y. +The signatures involving enable_if_convertible should behave +as-if enable_if_convertible were defined to be:

+
+template <bool> enable_if_convertible_impl
+{};
+
+template <> enable_if_convertible_impl<true>
+{ struct type; };
+
+template<typename From, typename To>
+struct enable_if_convertible
+  : enable_if_convertible_impl<is_convertible<From,To>::value>
+{};
+
+

If an expression other than the default argument is used to supply +the value of a function parameter whose type is written in terms +of enable_if_convertible, the program is ill-formed, no +diagnostic required.

+

[Note: The enable_if_convertible approach uses SFINAE to +take the constructor out of the overload set when the types are not +implicitly convertible. +]

+
+

Indirect iterator

+ + + +

indirect_iterator adapts an iterator by applying an +extra dereference inside of operator*(). For example, this +iterator adaptor makes it possible to view a container of pointers +(e.g. list<foo*>) as if it were a container of the pointed-to type +(e.g. list<foo>). indirect_iterator depends on two +auxiliary traits, pointee and indirect_reference, to +provide support for underlying iterators whose value_type is +not an iterator.

+
+

Class template pointee

+ + + +
+template <class Dereferenceable>
+struct pointee
+{
+    typedef /* see below */ type;
+};
+
+ +++ + + + +
Requires:For an object x of type Dereferenceable, *x +is well-formed. If ++x is ill-formed it shall neither be +ambiguous nor shall it violate access control, and +Dereferenceable::element_type shall be an accessible type. +Otherwise iterator_traits<Dereferenceable>::value_type shall +be well formed. [Note: These requirements need not apply to +explicit or partial specializations of pointee]
+

type is determined according to the following algorithm, where +x is an object of type Dereferenceable:

+
+if ( ++x is ill-formed )
+{
+    return ``Dereferenceable::element_type``
+}
+else if (``*x`` is a mutable reference to
+         std::iterator_traits<Dereferenceable>::value_type)
+{
+    return iterator_traits<Dereferenceable>::value_type
+}
+else
+{
+    return iterator_traits<Dereferenceable>::value_type const
+}
+
+
+
+

Class template indirect_reference

+ + + +
+template <class Dereferenceable>
+struct indirect_reference
+{
+    typedef /* see below */ type;
+};
+
+ +++ + + + +
Requires:For an object x of type Dereferenceable, *x +is well-formed. If ++x is ill-formed it shall neither be +ambiguous nor shall it violate access control, and +pointee<Dereferenceable>::type& shall be well-formed. +Otherwise iterator_traits<Dereferenceable>::reference shall +be well formed. [Note: These requirements need not apply to +explicit or partial specializations of indirect_reference]
+

type is determined according to the following algorithm, where +x is an object of type Dereferenceable:

+
+if ( ++x is ill-formed )
+    return ``pointee<Dereferenceable>::type&``
+else
+    std::iterator_traits<Dereferenceable>::reference
+
+
+
+

Class template indirect_iterator

+ + + +
+template <
+    class Iterator
+  , class Value = use_default
+  , class CategoryOrTraversal = use_default
+  , class Reference = use_default
+  , class Difference = use_default
+>
+class indirect_iterator
+{
+ public:
+    typedef /* see below */ value_type;
+    typedef /* see below */ reference;
+    typedef /* see below */ pointer;
+    typedef /* see below */ difference_type;
+    typedef /* see below */ iterator_category;
+
+    indirect_iterator();
+    indirect_iterator(Iterator x);
+
+    template <
+        class Iterator2, class Value2, class Category2
+      , class Reference2, class Difference2
+    >
+    indirect_iterator(
+        indirect_iterator<
+             Iterator2, Value2, Category2, Reference2, Difference2
+        > const& y
+      , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition
+    );
+
+    Iterator const& base() const;
+    reference operator*() const;
+    indirect_iterator& operator++();
+    indirect_iterator& operator--();
+private:
+   Iterator m_iterator; // exposition
+};
+
+

The member types of indirect_iterator are defined according to +the following pseudo-code, where V is +iterator_traits<Iterator>::value_type

+
+if (Value is use_default) then
+    typedef remove_const<pointee<V>::type>::type value_type;
+else
+    typedef remove_const<Value>::type value_type;
+
+if (Reference is use_default) then
+    if (Value is use_default) then
+        typedef indirect_reference<V>::type reference;
+    else
+        typedef Value& reference;
+else
+    typedef Reference reference;
+
+if (Value is use_default) then
+    typedef pointee<V>::type* pointer;
+else
+    typedef Value* pointer;
+
+if (Difference is use_default)
+    typedef iterator_traits<Iterator>::difference_type difference_type;
+else
+    typedef Difference difference_type;
+
+if (CategoryOrTraversal is use_default)
+    typedef iterator-category (
+        iterator_traversal<Iterator>::type,``reference``,``value_type``
+    ) iterator_category;
+else
+    typedef iterator-category (
+        CategoryOrTraversal,``reference``,``value_type``
+    ) iterator_category;
+
+
+
+

indirect_iterator requirements

+

The expression *v, where v is an object of +iterator_traits<Iterator>::value_type, shall be valid +expression and convertible to reference. Iterator shall +model the traversal concept indicated by iterator_category. +Value, Reference, and Difference shall be chosen so +that value_type, reference, and difference_type meet +the requirements indicated by iterator_category.

+

[Note: there are further requirements on the +iterator_traits<Iterator>::value_type if the Value +parameter is not use_default, as implied by the algorithm for +deducing the default for the value_type member.]

+
+
+

indirect_iterator models

+

In addition to the concepts indicated by iterator_category +and by iterator_traversal<indirect_iterator>::type, a +specialization of indirect_iterator models the following +concepts, Where v is an object of +iterator_traits<Iterator>::value_type:

+
+
    +
  • Readable Iterator if reference(*v) is convertible to +value_type.
  • +
  • Writable Iterator if reference(*v) = t is a valid +expression (where t is an object of type +indirect_iterator::value_type)
  • +
  • Lvalue Iterator if reference is a reference type.
  • +
+
+

indirect_iterator<X,V1,C1,R1,D1> is interoperable with +indirect_iterator<Y,V2,C2,R2,D2> if and only if X is +interoperable with Y.

+
+
+

indirect_iterator operations

+

In addition to the operations required by the concepts described +above, specializations of indirect_iterator provide the +following operations.

+

indirect_iterator();

+ +++ + + + + + +
Requires:Iterator must be Default Constructible.
Effects:Constructs an instance of indirect_iterator with +a default-constructed m_iterator.
+

indirect_iterator(Iterator x);

+ +++ + + + +
Effects:Constructs an instance of indirect_iterator with +m_iterator copy constructed from x.
+
+template <
+    class Iterator2, class Value2, unsigned Access, class Traversal
+  , class Reference2, class Difference2
+>
+indirect_iterator(
+    indirect_iterator<
+         Iterator2, Value2, Access, Traversal, Reference2, Difference2
+    > const& y
+  , typename enable_if_convertible<Iterator2, Iterator>::type* = 0 // exposition
+);
+
+ +++ + + + + + +
Requires:Iterator2 is implicitly convertible to Iterator.
Effects:Constructs an instance of indirect_iterator whose +m_iterator subobject is constructed from y.base().
+

Iterator const& base() const;

+ +++ + + + +
Returns:m_iterator
+

reference operator*() const;

+ +++ + + + +
Returns:**m_iterator
+

indirect_iterator& operator++();

+ +++ + + + + + +
Effects:++m_iterator
Returns:*this
+

indirect_iterator& operator--();

+ +++ + + + + + +
Effects:--m_iterator
Returns:*this
+
+
+
+

Reverse iterator

+ + + +

The reverse iterator adaptor iterates through the adapted iterator +range in the opposite direction.

+
+

Class template reverse_iterator

+ + + +
+template <class Iterator>
+class reverse_iterator
+{
+public:
+  typedef iterator_traits<Iterator>::value_type value_type;
+  typedef iterator_traits<Iterator>::reference reference;
+  typedef iterator_traits<Iterator>::pointer pointer;
+  typedef iterator_traits<Iterator>::difference_type difference_type;
+  typedef /* see below */ iterator_category;
+
+  reverse_iterator() {}
+  explicit reverse_iterator(Iterator x) ;
+
+  template<class OtherIterator>
+  reverse_iterator(
+      reverse_iterator<OtherIterator> const& r
+    , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+  );
+  Iterator const& base() const;
+  reference operator*() const;
+  reverse_iterator& operator++();
+  reverse_iterator& operator--();
+private:
+  Iterator m_iterator; // exposition
+};
+
+

If Iterator models Random Access Traversal Iterator and Readable +Lvalue Iterator, then iterator_category is convertible to +random_access_iterator_tag. Otherwise, if +Iterator models Bidirectional Traversal Iterator and Readable +Lvalue Iterator, then iterator_category is convertible to +bidirectional_iterator_tag. Otherwise, iterator_category is +convertible to input_iterator_tag.

+
+
+

reverse_iterator requirements

+

Iterator must be a model of Bidirectional Traversal Iterator. The +type iterator_traits<Iterator>::reference must be the type of +*i, where i is an object of type Iterator.

+
+
+

reverse_iterator models

+

A specialization of reverse_iterator models the same iterator +traversal and iterator access concepts modeled by its Iterator +argument. In addition, it may model old iterator concepts +specified in the following table:

+ ++++ + + + + + + + + + + + + + + + + + + + +
If I modelsthen reverse_iterator<I> models
Readable Lvalue Iterator, +Bidirectional Traversal IteratorBidirectional Iterator
Writable Lvalue Iterator, +Bidirectional Traversal IteratorMutable Bidirectional Iterator
Readable Lvalue Iterator, +Random Access Traversal IteratorRandom Access Iterator
Writable Lvalue Iterator, +Random Access Traversal IteratorMutable Random Access Iterator
+

reverse_iterator<X> is interoperable with +reverse_iterator<Y> if and only if X is interoperable with +Y.

+
+
+

reverse_iterator operations

+

In addition to the operations required by the concepts modeled by +reverse_iterator, reverse_iterator provides the following +operations.

+

reverse_iterator();

+ +++ + + + + + +
Requires:Iterator must be Default Constructible.
Effects:Constructs an instance of reverse_iterator with m_iterator +default constructed.
+

explicit reverse_iterator(Iterator x);

+ +++ + + + +
Effects:Constructs an instance of reverse_iterator with +m_iterator copy constructed from x.
+
+template<class OtherIterator>
+reverse_iterator(
+    reverse_iterator<OtherIterator> const& r
+  , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+);
+
+ +++ + + + + + +
Requires:OtherIterator is implicitly convertible to Iterator.
Effects:Constructs instance of reverse_iterator whose +m_iterator subobject is constructed from y.base().
+

Iterator const& base() const;

+ +++ + + + +
Returns:m_iterator
+

reference operator*() const;

+ +++ + + + +
Effects:
+
+Iterator tmp = m_iterator;
+return *--tmp;
+
+

reverse_iterator& operator++();

+ +++ + + + + + +
Effects:--m_iterator
Returns:*this
+

reverse_iterator& operator--();

+ +++ + + + + + +
Effects:++m_iterator
Returns:*this
+
+
+
+

Transform iterator

+ + + +

The transform iterator adapts an iterator by modifying the +operator* to apply a function object to the result of +dereferencing the iterator and returning the result.

+
+

Class template transform_iterator

+ + + + +
+template <class UnaryFunction,
+          class Iterator,
+          class Reference = use_default,
+          class Value = use_default>
+class transform_iterator
+{
+public:
+  typedef /* see below */ value_type;
+  typedef /* see below */ reference;
+  typedef /* see below */ pointer;
+  typedef iterator_traits<Iterator>::difference_type difference_type;
+  typedef /* see below */ iterator_category;
+
+  transform_iterator();
+  transform_iterator(Iterator const& x, UnaryFunction f);
+
+  template<class F2, class I2, class R2, class V2>
+  transform_iterator(
+        transform_iterator<F2, I2, R2, V2> const& t
+      , typename enable_if_convertible<I2, Iterator>::type* = 0      // exposition only
+      , typename enable_if_convertible<F2, UnaryFunction>::type* = 0 // exposition only
+  );
+  UnaryFunction functor() const;
+  Iterator const& base() const;
+  reference operator*() const;
+  transform_iterator& operator++();
+  transform_iterator& operator--();
+private:
+  Iterator m_iterator; // exposition only
+  UnaryFunction m_f;   // exposition only
+};
+
+

If Reference is use_default then the reference member of +transform_iterator is +result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type. +Otherwise, reference is Reference.

+

If Value is use_default then the value_type member is +remove_cv<remove_reference<reference> >::type. Otherwise, +value_type is Value.

+

If Iterator models Readable Lvalue Iterator and if Iterator +models Random Access Traversal Iterator, then iterator_category is +convertible to random_access_iterator_tag. Otherwise, if +Iterator models Bidirectional Traversal Iterator, then +iterator_category is convertible to +bidirectional_iterator_tag. Otherwise iterator_category is +convertible to forward_iterator_tag. If Iterator does not +model Readable Lvalue Iterator then iterator_category is +convertible to input_iterator_tag.

+
+
+

transform_iterator requirements

+

The type UnaryFunction must be Assignable, Copy Constructible, and +the expression f(*i) must be valid where f is an object of +type UnaryFunction, i is an object of type Iterator, and +where the type of f(*i) must be +result_of<UnaryFunction(iterator_traits<Iterator>::reference)>::type.

+

The argument Iterator shall model Readable Iterator.

+
+
+

transform_iterator models

+

The resulting transform_iterator models the most refined of the +following that is also modeled by Iterator.

+
+
    +
  • Writable Lvalue Iterator if transform_iterator::reference is a non-const reference.
  • +
  • Readable Lvalue Iterator if transform_iterator::reference is a const reference.
  • +
  • Readable Iterator otherwise.
  • +
+
+

The transform_iterator models the most refined standard traversal +concept that is modeled by the Iterator argument.

+

If transform_iterator is a model of Readable Lvalue Iterator then +it models the following original iterator concepts depending on what +the Iterator argument models.

+ ++++ + + + + + + + + + + + + + + + + + + + +
If Iterator modelsthen transform_iterator models
Single Pass IteratorInput Iterator
Forward Traversal IteratorForward Iterator
Bidirectional Traversal IteratorBidirectional Iterator
Random Access Traversal IteratorRandom Access Iterator
+

If transform_iterator models Writable Lvalue Iterator then it is a +mutable iterator (as defined in the old iterator requirements).

+

transform_iterator<F1, X, R1, V1> is interoperable with +transform_iterator<F2, Y, R2, V2> if and only if X is +interoperable with Y.

+
+
+

transform_iterator operations

+

In addition to the operations required by the concepts modeled by +transform_iterator, transform_iterator provides the following +operations.

+

transform_iterator();

+ +++ + + + +
Returns:An instance of transform_iterator with m_f +and m_iterator default constructed.
+

transform_iterator(Iterator const& x, UnaryFunction f);

+ +++ + + + +
Returns:An instance of transform_iterator with m_f +initialized to f and m_iterator initialized to x.
+
+template<class F2, class I2, class R2, class V2>
+transform_iterator(
+      transform_iterator<F2, I2, R2, V2> const& t
+    , typename enable_if_convertible<I2, Iterator>::type* = 0      // exposition only
+    , typename enable_if_convertible<F2, UnaryFunction>::type* = 0 // exposition only
+);
+
+ +++ + + + + + +
Returns:An instance of transform_iterator with m_f +initialized to t.functor() and m_iterator initialized to +t.base().
Requires:OtherIterator is implicitly convertible to Iterator.
+

UnaryFunction functor() const;

+ +++ + + + +
Returns:m_f
+

Iterator const& base() const;

+ +++ + + + +
Returns:m_iterator
+

reference operator*() const;

+ +++ + + + +
Returns:m_f(*m_iterator)
+

transform_iterator& operator++();

+ +++ + + + + + +
Effects:++m_iterator
Returns:*this
+

transform_iterator& operator--();

+ +++ + + + + + +
Effects:--m_iterator
Returns:*this
+
+
+
+

Filter iterator

+ + + +

The filter iterator adaptor creates a view of an iterator range in +which some elements of the range are skipped. A predicate function +object controls which elements are skipped. When the predicate is +applied to an element, if it returns true then the element is +retained and if it returns false then the element is skipped +over. When skipping over elements, it is necessary for the filter +adaptor to know when to stop so as to avoid going past the end of the +underlying range. A filter iterator is therefore constructed with pair +of iterators indicating the range of elements in the unfiltered +sequence to be traversed.

+
+

Class template filter_iterator

+ + + + +
+template <class Predicate, class Iterator>
+class filter_iterator
+{
+ public:
+    typedef iterator_traits<Iterator>::value_type value_type;
+    typedef iterator_traits<Iterator>::reference reference;
+    typedef iterator_traits<Iterator>::pointer pointer;
+    typedef iterator_traits<Iterator>::difference_type difference_type;
+    typedef /* see below */ iterator_category;
+
+    filter_iterator();
+    filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());
+    filter_iterator(Iterator x, Iterator end = Iterator());
+    template<class OtherIterator>
+    filter_iterator(
+        filter_iterator<Predicate, OtherIterator> const& t
+        , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+        );
+    Predicate predicate() const;
+    Iterator end() const;
+    Iterator const& base() const;
+    reference operator*() const;
+    filter_iterator& operator++();
+private:
+    Predicate m_pred; // exposition only
+    Iterator m_iter;  // exposition only
+    Iterator m_end;   // exposition only
+};
+
+

If Iterator models Readable Lvalue Iterator and Bidirectional Traversal +Iterator then iterator_category is convertible to +std::bidirectional_iterator_tag. +Otherwise, if Iterator models Readable Lvalue Iterator and Forward Traversal +Iterator then iterator_category is convertible to +std::forward_iterator_tag. +Otherwise iterator_category is +convertible to std::input_iterator_tag.

+
+
+

filter_iterator requirements

+

The Iterator argument shall meet the requirements of Readable +Iterator and Single Pass Iterator or it shall meet the requirements of +Input Iterator.

+

The Predicate argument must be Assignable, Copy Constructible, and +the expression p(x) must be valid where p is an object of type +Predicate, x is an object of type +iterator_traits<Iterator>::value_type, and where the type of +p(x) must be convertible to bool.

+
+
+

filter_iterator models

+

The concepts that filter_iterator models are dependent on which +concepts the Iterator argument models, as specified in the +following tables.

+ ++++ + + + + + + + + + + + + + + + + +
If Iterator modelsthen filter_iterator models
Single Pass IteratorSingle Pass Iterator
Forward Traversal IteratorForward Traversal Iterator
Bidirectional Traversal IteratorBidirectional Traversal Iterator
+ ++++ + + + + + + + + + + + + + + + + +
If Iterator modelsthen filter_iterator models
Readable IteratorReadable Iterator
Writable IteratorWritable Iterator
Lvalue IteratorLvalue Iterator
+ ++++ + + + + + + + + + + + + + + + + + + + +
If Iterator modelsthen filter_iterator models
Readable Iterator, Single Pass IteratorInput Iterator
Readable Lvalue Iterator, Forward Traversal IteratorForward Iterator
Writable Lvalue Iterator, Forward Traversal IteratorMutable Forward Iterator
Writable Lvalue Iterator, Bidirectional IteratorMutable Bidirectional Iterator
+

filter_iterator<P1, X> is interoperable with filter_iterator<P2, Y> +if and only if X is interoperable with Y.

+
+
+

filter_iterator operations

+

In addition to those operations required by the concepts that +filter_iterator models, filter_iterator provides the following +operations.

+

filter_iterator();

+ +++ + + + + + +
Requires:Predicate and Iterator must be Default Constructible.
Effects:Constructs a filter_iterator whose``m_pred``, m_iter, and m_end +members are a default constructed.
+

filter_iterator(Predicate f, Iterator x, Iterator end = Iterator());

+ +++ + + + +
Effects:Constructs a filter_iterator where m_iter is either +the first position in the range [x,end) such that f(*m_iter) == true +or else``m_iter == end``. The member m_pred is constructed from +f and m_end from end.
+

filter_iterator(Iterator x, Iterator end = Iterator());

+ +++ + + + + + +
Requires:Predicate must be Default Constructible and +Predicate is a class type (not a function pointer).
Effects:Constructs a filter_iterator where m_iter is either +the first position in the range [x,end) such that m_pred(*m_iter) == true +or else``m_iter == end``. The member m_pred is default constructed.
+
+template <class OtherIterator>
+filter_iterator(
+    filter_iterator<Predicate, OtherIterator> const& t
+    , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0 // exposition
+    );``
+
+ +++ + + + + + +
Requires:OtherIterator is implicitly convertible to Iterator.
Effects:Constructs a filter iterator whose members are copied from t.
+

Predicate predicate() const;

+ +++ + + + +
Returns:m_pred
+

Iterator end() const;

+ +++ + + + +
Returns:m_end
+

Iterator const& base() const;

+ +++ + + + +
Returns:m_iterator
+

reference operator*() const;

+ +++ + + + +
Returns:*m_iter
+

filter_iterator& operator++();

+ +++ + + + + + +
Effects:Increments m_iter and then continues to +increment m_iter until either m_iter == m_end +or m_pred(*m_iter) == true.
Returns:*this
+
+
+
+

Counting iterator

+ + + +

counting_iterator adapts an object by adding an operator* that +returns the current value of the object. All other iterator operations +are forwarded to the adapted object.

+
+

Class template counting_iterator

+ + + +
+template <
+    class Incrementable
+  , class CategoryOrTraversal = use_default
+  , class Difference = use_default
+>
+class counting_iterator
+{
+public:
+    typedef Incrementable value_type;
+    typedef const Incrementable& reference;
+    typedef const Incrementable* pointer;
+    typedef /* see below */ difference_type;
+    typedef /* see below */ iterator_category;
+
+    counting_iterator();
+    counting_iterator(counting_iterator const& rhs);
+    explicit counting_iterator(Incrementable x);
+    Incrementable const& base() const;
+    reference operator*() const;
+    counting_iterator& operator++();
+    counting_iterator& operator--();
+private:
+    Incrementable m_inc; // exposition
+};
+
+

If the Difference argument is use_default then +difference_type is an unspecified signed integral +type. Otherwise difference_type is Difference.

+

iterator_category is determined according to the following +algorithm:

+
+if (CategoryOrTraversal is not use_default)
+    return CategoryOrTraversal
+else if (numeric_limits<Incrementable>::is_specialized)
+    return iterator-category(
+        random_access_traversal_tag, Incrementable, const Incrementable&)
+else
+    return iterator-category(
+         iterator_traversal<Incrementable>::type,
+         Incrementable, const Incrementable&)
+
+
+
[Note: implementers are encouraged to provide an implementation of
+
operator- and a difference_type that avoids overflows in +the cases where std::numeric_limits<Incrementable>::is_specialized +is true.]
+
+
+
+

counting_iterator requirements

+

The Incrementable argument shall be Copy Constructible and Assignable.

+

If iterator_category is convertible to forward_iterator_tag +or forward_traversal_tag, the following must be well-formed:

+
+Incrementable i, j;
+++i;         // pre-increment
+i == j;      // operator equal
+
+

If iterator_category is convertible to +bidirectional_iterator_tag or bidirectional_traversal_tag, +the following expression must also be well-formed:

+
+--i
+
+

If iterator_category is convertible to +random_access_iterator_tag or random_access_traversal_tag, +the following must must also be valid:

+
+counting_iterator::difference_type n;
+i += n;
+n = i - j;
+i < j;
+
+
+
+

counting_iterator models

+

Specializations of counting_iterator model Readable Lvalue +Iterator. In addition, they model the concepts corresponding to the +iterator tags to which their iterator_category is convertible. +Also, if CategoryOrTraversal is not use_default then +counting_iterator models the concept corresponding to the iterator +tag CategoryOrTraversal. Otherwise, if +numeric_limits<Incrementable>::is_specialized, then +counting_iterator models Random Access Traversal Iterator. +Otherwise, counting_iterator models the same iterator traversal +concepts modeled by Incrementable.

+

counting_iterator<X,C1,D1> is interoperable with +counting_iterator<Y,C2,D2> if and only if X is +interoperable with Y.

+
+
+

counting_iterator operations

+

In addition to the operations required by the concepts modeled by +counting_iterator, counting_iterator provides the following +operations.

+

counting_iterator();

+ +++ + + + + + +
Requires:Incrementable is Default Constructible.
Effects:Default construct the member m_inc.
+

counting_iterator(counting_iterator const& rhs);

+ +++ + + + +
Effects:Construct member m_inc from rhs.m_inc.
+

explicit counting_iterator(Incrementable x);

+ +++ + + + +
Effects:Construct member m_inc from x.
+

reference operator*() const;

+ +++ + + + +
Returns:m_inc
+

counting_iterator& operator++();

+ +++ + + + + + +
Effects:++m_inc
Returns:*this
+

counting_iterator& operator--();

+ +++ + + + + + +
Effects:--m_inc
Returns:*this
+

Incrementable const& base() const;

+ +++ + + + +
Returns:m_inc
+
+
+
+

Function output iterator

+ + + +

The function output iterator adaptor makes it easier to create custom +output iterators. The adaptor takes a unary function and creates a +model of Output Iterator. Each item assigned to the output iterator is +passed as an argument to the unary function. The motivation for this +iterator is that creating a conforming output iterator is non-trivial, +particularly because the proper implementation usually requires a +proxy object.

+ + +
+

function_output_iterator requirements

+

UnaryFunction must be Assignable and Copy Constructible.

+
+
+

function_output_iterator models

+

function_output_iterator is a model of the Writable and +Incrementable Iterator concepts.

+
+
+

function_output_iterator operations

+

explicit function_output_iterator(const UnaryFunction& f = UnaryFunction());

+ +++ + + + +
Effects:Constructs an instance of function_output_iterator +with m_f constructed from f.
+

operator*();

+ +++ + + + +
Returns:An object r of unspecified type such that r = t +is equivalent to m_f(t) for all t.
+

function_output_iterator& operator++();

+ +++ + + + +
Returns:*this
+

function_output_iterator& operator++(int);

+ +++ + + + +
Returns:*this
+ +
+
+
+
+